Force-aware visuo-tactile world model
A second head on the tactile expert of VideoTactileMoTDF predicts
recovered contact force from the same hidden state h_G that feeds the GelSight
diffusion head. 20 held-out windows, short and long horizon.
How to read the figures. For each stream the upper strip is ground truth and the
strip directly beneath it is the model's prediction. One column = one latent frame, so
every strip column lines up with the force circle below it.
The bottom panels show normal force per gel as two rows of circles — GT above,
PRED below (the head reading the model's generated latents). Circle area is
proportional to newtons, so radius goes as √F; area is what the eye integrates, and a
radius-proportional encoding would exaggerate large forces roughly quadratically. The scale is
fixed at 7.87 N (the react_calib ceiling) across every figure, so circles are
comparable between samples. A hollow ring means no contact — distinct from nothing
being drawn. The thin red trace underneath is the predicted contact probability, with the 0.5
threshold dotted, so a confident miss is distinguishable from a borderline one.
The blue shaded region is the clean ground-truth context the sampler was seeded with
(2 latent frames = 8 fps6 frames). Everything right of the blue line is what the model
actually generated. The rows marked “predicted frames only” in the tables
below exclude that context — on a short window it is half the frames, so the unrestricted
numbers flatter the rollout.
What the circle value actually is. One circle = one latent frame = 4 fps6 frames, and its
value is the mean force conditioned on contact — the model's training target. So a
2.2 N circle can mean "2.2 N for the whole span" or "one 2.2 N touch in four
frames". To keep that readable: circle opacity encodes the contact fraction (faint = brief
touch), the fraction is printed above any circle below 1.0, and the grey band at the top of
each panel is the raw 6 Hz force straight from force_fps6.pt, so the underlying
signal the circles summarise is always visible.
What the head is and is not. It is trained as auxiliary supervision only and is never
called during sampling — rollouts are unchanged and need no force at test time. Because
force is itself recovered from the GelSight image by react_calib, the head partly
re-derives that mapping rather than adding independent information, and react_calib's
own held-out MAE (1.23 N) is roughly the accuracy floor any readout can beat.
Short horizon — 1 window (16 frames @ 6 fps)
Pixel PSNR: view 24.12 dB · tl 44.03 dB · tr 43.37 dB
| force readout | contact AUROC | force r (on contact) |
MAE | contacting frames |
| head on GT latents | 0.944 | 0.553 | 0.85 N | 106/160 |
| head on GT latents — predicted frames only | 0.973 | 0.644 | 0.83 N | 50/80 |
| head on GENERATED latents | 0.896 | 0.346 | 1.15 N | 106/160 |
| head on GENERATED latents — predicted frames only | 0.883 | 0.370 | 1.45 N | 50/80 |
sample_000 · motherboard_0510_episode_005.pt t=0

GT vs rollout clips: view · tl · tr
sample_001 · motherboard_0510_episode_005.pt t=15

GT vs rollout clips: view · tl · tr
sample_002 · motherboard_0510_episode_005.pt t=30

GT vs rollout clips: view · tl · tr
sample_003 · motherboard_0510_episode_005.pt t=45

GT vs rollout clips: view · tl · tr
sample_004 · motherboard_0510_episode_005.pt t=55

GT vs rollout clips: view · tl · tr
sample_005 · motherboard_0510_episode_006.pt t=0

GT vs rollout clips: view · tl · tr
sample_006 · motherboard_0510_episode_006.pt t=50

GT vs rollout clips: view · tl · tr
sample_007 · motherboard_0510_episode_006.pt t=100

GT vs rollout clips: view · tl · tr
sample_008 · motherboard_0510_episode_006.pt t=150

GT vs rollout clips: view · tl · tr
sample_009 · motherboard_0510_episode_006.pt t=200

GT vs rollout clips: view · tl · tr
sample_010 · motherboard_0510_episode_006.pt t=250

GT vs rollout clips: view · tl · tr
sample_011 · motherboard_0510_episode_006.pt t=300

GT vs rollout clips: view · tl · tr
sample_012 · motherboard_0510_episode_006.pt t=350

GT vs rollout clips: view · tl · tr
sample_013 · motherboard_0510_episode_006.pt t=400

GT vs rollout clips: view · tl · tr
sample_014 · motherboard_0510_episode_006.pt t=450

GT vs rollout clips: view · tl · tr
sample_015 · motherboard_0510_episode_006.pt t=500

GT vs rollout clips: view · tl · tr
sample_016 · motherboard_0510_episode_006.pt t=550

GT vs rollout clips: view · tl · tr
sample_017 · motherboard_0510_episode_006.pt t=600

GT vs rollout clips: view · tl · tr
sample_018 · motherboard_0510_episode_006.pt t=650

GT vs rollout clips: view · tl · tr
sample_019 · motherboard_0510_episode_006.pt t=680

GT vs rollout clips: view · tl · tr
Long horizon — 16 s autoregressive rollout
Pixel PSNR: view 19.57 dB · tl 24.91 dB · tr 25.54 dB
| force readout | contact AUROC | force r (on contact) |
MAE | contacting frames |
| head on GT latents | 0.965 | 0.561 | 0.82 N | 642/960 |
| head on GT latents — predicted frames only | 0.970 | 0.574 | 0.82 N | 586/880 |
| head on GENERATED latents | 0.803 | 0.211 | 1.33 N | 642/960 |
| head on GENERATED latents — predicted frames only | 0.792 | 0.198 | 1.37 N | 586/880 |
sample_000 · motherboard_0510_episode_005.pt t=0

GT vs rollout clips: view · tl · tr
sample_001 · motherboard_0510_episode_005.pt t=15

GT vs rollout clips: view · tl · tr
sample_002 · motherboard_0510_episode_005.pt t=30

GT vs rollout clips: view · tl · tr
sample_003 · motherboard_0510_episode_005.pt t=45

GT vs rollout clips: view · tl · tr
sample_004 · motherboard_0510_episode_005.pt t=55

GT vs rollout clips: view · tl · tr
sample_005 · motherboard_0510_episode_006.pt t=0

GT vs rollout clips: view · tl · tr
sample_006 · motherboard_0510_episode_006.pt t=50

GT vs rollout clips: view · tl · tr
sample_007 · motherboard_0510_episode_006.pt t=100

GT vs rollout clips: view · tl · tr
sample_008 · motherboard_0510_episode_006.pt t=150

GT vs rollout clips: view · tl · tr
sample_009 · motherboard_0510_episode_006.pt t=200

GT vs rollout clips: view · tl · tr
sample_010 · motherboard_0510_episode_006.pt t=250

GT vs rollout clips: view · tl · tr
sample_011 · motherboard_0510_episode_006.pt t=300

GT vs rollout clips: view · tl · tr
sample_012 · motherboard_0510_episode_006.pt t=350

GT vs rollout clips: view · tl · tr
sample_013 · motherboard_0510_episode_006.pt t=400

GT vs rollout clips: view · tl · tr
sample_014 · motherboard_0510_episode_006.pt t=450

GT vs rollout clips: view · tl · tr
sample_015 · motherboard_0510_episode_006.pt t=500

GT vs rollout clips: view · tl · tr
sample_016 · motherboard_0510_episode_006.pt t=550

GT vs rollout clips: view · tl · tr
sample_017 · motherboard_0510_episode_006.pt t=600

GT vs rollout clips: view · tl · tr
sample_018 · motherboard_0510_episode_006.pt t=650

GT vs rollout clips: view · tl · tr
sample_019 · motherboard_0510_episode_006.pt t=680

GT vs rollout clips: view · tl · tr
Checkpoint best-epoch=87 of run
mot_df_vt_force. Held-out episodes motherboard_0510_episode_005/006,
never trained on.