DriftWorld - Fast World Modeling through Drifting

Sep 25, 202627 min

DriftWorld: an action-conditioned world model based on drifting generative models. Generates future frames from the current observation and a candidate action sequence in a single forward pass at 30+ fps (17x faster than diffusion-based baselines).

Summary

The world model is conditioned on c=(ot−F:t,at:t+T)c = (o_{t-F:t}, a_{t: t+T}) where:

  • ot−F:to_{t-F:t} = initial/current observation plus any history frames
  • at:t+Ta_{t: t+T} = proposed sequence of future robot actions
  • x=ot+1:t+T+1x = o_{t+1:t+T+1} = the future video the model should generate So the desired conditional distribution is: p(x∣c)=p(ot+1:t+T+1∣ot−F:t,at:t+T)p(x \mid c) = p(o_{t+1: t+ T + 1} \mid o_{t-F:t}, a_{t: t+T})The generator produces: xi=fθ(ϵi,c),ϵi∼pϵx_i = f_\theta(\epsilon_i, c), \epsilon_i \sim p_\epsilon, giving a model distribution: qθ(x∣c)q_\theta(x \mid c)
  • Conditional drifting field defined by the initial observation and action sequence, with a modification that accentuates action following (bias against o^t+1≈ot\hat{o}_{t+1} \approx o_t)

    • i.e., for each specific starting scene and proposed robot action sequence, build a sector vector field that tells generated future videos how to move toward the correct feature, & modify that field so predictions that merely copy the starting frame are pushed away more strongly
    • 🔑 Conditional - means that samples are only compared within the same starting observation and action sequence
      • ^ a batch containing BB different demonstrations therefore has BB separate drifting fields, rather than one global field mixing unrelated scenes and actions.
  • A drifting feature space that leverages DINOv2/v3 to maintain visual sharpness in complex scenes

  • A U-Net architecture that ensures each video frame is precisely conditioned on the corresponding action

Training: noise + history + actions→U-Net→future VAE latents→{VAE latent drift lossdecode→DINO drift loss\boxed{\text{noise + history + actions} \rightarrow \text{U-Net} \rightarrow \text{future VAE latents} \rightarrow \begin{cases} \text{VAE latent drift loss}\\ \text{decode} \rightarrow \text{DINO drift loss} \end{cases}} Inference:noise + history + actions→U-Net→future VAE latents→VAE decoder→future images\boxed{\text{noise + history + actions} \rightarrow \text{U-Net} \rightarrow \text{future VAE latents} \rightarrow \text{VAE decoder} \rightarrow \text{future images}}

A note on indexing

As a note, the paper has a notational inconsistency: in Section 3.1 it writes actions at:t+T=(at,…,at+T)a_{t:t+T} = (a_t, \ldots, a_{t+T})which contains T+1T+ 1 actions, and predicts ot+1:t+T+1o_{t+1: t+ T+ 1}which contains T+1T+1 future frames. But Algorithm 1 uses: action shape [T,D],positive video shape [1,T,C,H,W]\text{action shape } [T, D], \quad \text{positive video shape } [1, T, C, H, W]which implies TT actions with TT future frames, i.e. - (at,…,at+T−1)→(ot+1,…,ot+T)(a_t, \ldots, a_{t+T - 1}) \rightarrow (o_{t+1}, \ldots , o_{t+T}) None of this impacts the core ideas presented, and these notes also may have inherited some of the notational inconsistency (I tried to stick with (at,…,at+T)→(ot+1,…,ot+1+T)(a_t, \ldots, a_{t+T}) \rightarrow (o_{t+1}, \ldots , o_{t+1+T}), but some parts may be off by one) - please ignore any inconsistencies!

Drifting field

Vanilla conditional drifting field

For one condition cc, let:

  • y+y^+ = the real ground-truth future video for that condition
  • y1−,…,yN−y_1^-, \ldots, y_N^- = generated future videos under the same condition

The drift acting on generated sample xix_i is (intuitively): Vp,qθ(xi∣c)=Vp+(xi∣c)−Vqθ−(xi∣c)V_{p, q_\theta}(x_i \mid c) = V_p^+ (x_i \mid c) - V_{q_\theta}^- (x_i \mid c)The positive term attracts xix_i to the real future (minimizing L\mathcal{L} will minimize VV which minimizes V+V^+, i.e. vector difference between y+y^+ and xix_i) while the negative term accounts for nearby generated samples (minimizing L\mathcal{L} will maximize V−V^-, i.e. prevent generated samples from collapsing to one spot): Vp+(xi∣c)≈wi+(y+−xi),Vqθ−(xi∣c)≈∑j≠iwij−(yj−−xi)V_p^+(x_i \mid c) \approx w_i^+ (y^+ - x_i), \quad V_{q_\theta}^- (x_i \mid c) \approx \sum_{j\neq i} w_{ij}^- (y_j^- - x_i) The weights are based on similarity, through some kernel KK: wi∝K(xi,y+),wij−∝K(xi,yj−)w_i \propto K(x_i, y^+), \quad w_{ij}^- \propto K(x_i, y_j^-)The update target is: xidrift=xi+Vp,qθ(xi∣c)x_i^\text{drift} = x_i + V_{p, q_\theta}(x_i \mid c)The training loss is: Ldrift=Eϵ[∣∣fθ(ϵ,c)−stopgrad(fθ(ϵ,c)+Vp,qθ(fθ(ϵ,c)∣c))∣∣22]\boxed{\mathcal{L}_\text{drift} = \mathbb{E}_\epsilon \left[||f_\theta(\epsilon, c) - \text{stopgrad} (f_\theta(\epsilon, c) + V_{p, q_\theta}(f_\theta(\epsilon, c) \mid c))||^2_2\right]}

  • 💡 So the network output is trained to move in the direction prescribed by the field!

Adding the no-action future to the negative distribution

A common failure mode is the world model ignoring the action and simply copying the current image: o^t+1≈ot\hat{o}_{t+1} \approx o_tThis still achieves a deceptively low reconstruction error because most pixels (the table, walls, background, stationary objects) do not move. To prevent the model from falling in this trap, DriftWorld adds the no-action-future to the negative distribution (i.e. vector field of things to not do):q~(x∣at:t+T,ot−F:t)⏟model’s generated-future distr.=(1−γ)qθ(x∣at:t+T,ot−F:t)⏟current distr. of model generated futures+γp(x∣∅,ot−F:t)⏟distr. corresponding to taking no action\underbrace{\tilde{q} (x \mid a_{t: t+ T}, o_{t-F:t})}_\text{model's generated-future distr.} = (1 - \gamma) \underbrace{q_\theta(x \mid a_{t: t+T}, o_{t-F:t})}_\text{current distr. of model generated futures} + \gamma \underbrace{p(x \mid \varnothing , o_{t-F:t})}_\text{distr. corresponding to taking no action}where γ∈[0,1)\gamma \in [0, 1). Dissecting this equation in more detail:

  • qθ(x∣a,o)q_\theta(x \mid a, o) is the model's generated-future distribution
  • p(x∣∅,o)p(x \mid \varnothing, o) is the distribution corresponding to taking no action
  • In practice, the current frame oto_t is used as a real no-action negative - i.e. the unchanged current image is treated as an example of what the future should not look like when a nonzero action is commanded
    • Algorithm 1 (paper) writes this as: yneg=cat([x,obs[−1]]),\texttt{yneg} = \text{cat}([x, \text{obs}[-1]]),where xx = NN generated future samples, obs[−1]=ot\text{obs}[-1] = o_t = most recent real observation.
      • 📍 Slight nuance: for the real-world datasets, the model predicts 1 future frame per call (and then autoregressively generates), so oto_t naturally has the same shape as the generated future. For a multi-frame output, one would need to construct a matching no-action chunk, e.g. by repeating oto_t, but the paper's pseudocode does not spell out this case.
    • 🔑 So the negative set is: N={x1,…,xN,ot}\mathcal{N} = \{x_1, \ldots, x_N, o_t \}
  • γ\gamma controls how strongly the model is discouraged from simply preserving the current state

The modified field is therefore: Vp,q~(x∣c)=Vp+(x∣c)−Vq~−(x∣c)V_{p, \tilde{q}}(x \mid c) = V_p^+ (x \mid c) - V_{\tilde{q}}^-(x \mid c )where the negative part is conceptually: Vq~−≈(1−γ)Vqθ−+γVno-action−\boxed{V_{\tilde{q}}^- \approx (1-\gamma)V_{q_\theta}^- + \gamma V_{\text{no-action}}^-}The extra term −γVno-action−-\gamma V_\text{no-action}^- pushes generated videos away from futures that look like "nothing happened."

Drifting feature space

DriftWorld measures attraction & repulsion between particles via feature-space, rather than RGB space / raw particle (in this drifting field, images) space.

driftworld field.png

Particles in DriftWorld's drifting field

The particles are the model's generated future-video samples.

For one fixed condition c=(ot−F:t,at:t+T)c = (o_{t-F: t}, a_{t: t+ T}), the model samples different Gaussian noises ϵi∼N(0,I),  i∈[1,N]\epsilon_i \sim \mathcal{N}(0, I), \,\, i \in [1, N], and each noise produces one generated future chunk: xi=fθ(ϵi,c)  ⟹  one particle xi=one generated candidate future videox_i = f_\theta(\epsilon_i, c) \implies \boxed{\text{one particle }x_i = \text{one generated candidate future video}}For T=1T = 1, a particle is one predicted next frame. For T>1T>1, a particle is an entire predicted future chunk: xi=(o^t+1(i),…,o^t+1+T(i))x_i = \left(\hat{o}_{t+1}^{(i)}, \ldots, \hat{o}_{t+1+T}^{(i)}\right)

  • 🔑 The model generates multiple particles under the same history and actions because different Gaussian noises ϵi\epsilon_i may represent different plausible futures.
  • 🔖 Bookkeeping: For one training example, we have...
    • one positive future y+y^+
    • NnegN_\text{neg} generated particles x1,…,xNnegx_1, \ldots, x_{N_\text{neg}}
    • optionally the no-action image oto_t as an additional negative
  • 📍 The paper's reported numbers of generated negatives are:
    • Push-T: Nneg=8N_\text{neg} = 8
    • Robomimic: Nneg=32N_\text{neg} = 32
    • Bridge-V2/RT-1/Language Table: Nneg=64N_\text{neg} = 64
  • Sneak peek at content of following sections: Each generated particle xix_i receives its own drift vector Vi=Vp,q(xi)V_i = V_{p,q}(x_i). The target for that particle is xitarget=stopgrad(xi+Vi)x_i^\text{target} = \text{stopgrad}(x_i + V_i)

Feature space drifting

  1. Pass each image through a frozen visual encoder ϕ\phi: ϕ:RC×H0×W0→RH×W×D\phi: \mathbb{R}^{C \times H_0 \times W_0}\rightarrow \mathbb{R}^{H \times W \times D}where CC = number of image channels (usually C=3C = 3 for RGB), H0H_0 = original image height in pixels, W0W_0 = original image width in pixels. DINO transforms the image into a lower resolution grid: HH = number of feature-grid rows, WW = number of feature-grid columns, DD = number of features stored at each grid location. For DINOv3 feature vectors: at each location (h,w)∈[0:16,0:16](h, w) \in [0:16, 0:16], we have a 768-dim. feature vector describing the corresponding image region: ϕ(x)h,w∈R768\phi(x)_{h,w} \in \mathbb{R}^{768}
    • For real-world datasets, ϕ\phi is DINOv2 or DINOv3.
    • After passing an image xx through ϕ\phi, it becomes a grid of feature vectors: ϕ(x)={ϕ(x)h,w∈RD}h=1,w=1H,W\phi(x) = \{\phi(x)_{h,w} \in \mathbb{R}^D\}^{H, W}_{h=1, w=1}Each feature vector (ideally 😅) represents what DINO sees at a particular image region: gripper, object edge, plate, countertop texture, etc.
  2. Rather than computing one giant drift between raw images, DriftWorld computes a separate drift at every spatial location: Vh,w(x)=Vp,h,w+(x)−Vq,h,w−(x)V_{h,w}(x) = V^+_{p, h, w}(x) - V^-_{q, h, w} (x)More concretely, define: zih,w=ϕ(xi)h,w,⏟featurized generated particle xiz+h,w=ϕ(y+)h,w,⏟featurized positive particleszj−,h,w=ϕ(yj−)h,w⏟featurized other generated particles\underbrace{z_i^{h,w} = \phi(x_i)_{h,w},}_\text{featurized generated particle $x_i$} \quad \underbrace{z_+^{h,w}=\phi(y^+)_{h,w},}_\text{featurized positive particles} \quad \underbrace{z_j^{-, h, w}= \phi(y_j^-)_{h,w}}_\text{featurized other generated particles}Then the drift at location (h,w)(h,w) acts in RD\mathbb{R}^D, where a generic kernel-weighted mean-shift form of V+V^+ and V−V^- is: Vh,w+(zi)=∑k∈Pkτ(zi,zk+)(zk+−zi)∑k∈Pkτ(zi,zk+),Vh,w−(zi)=∑j∈Nkτ(zi,zj−)(zj−−zi)∑j∈Nkτ(zi,zj−)V_{h,w}^+(z_i) = \frac{\sum_{k \in \mathcal{P}}k_\tau (z_i, z_k^+) (z_k^+ - z_i)}{\sum_{k \in \mathcal{P}}k_\tau (z_i , z_k^+)}, \quad V_{h,w}^-(z_i) = \frac{\sum_{j \in \mathcal{N}}k_\tau (z_i, z_j^-) (z_j^- - z_i)}{\sum_{j \in \mathcal{N}}k_\tau (z_i , z_j^-)}For DriftWorld there is usually only one positive future for each condition (ground-truth rollout), so P\mathcal{P} contains one sample, i.e. P={y+}\mathcal{P} = \{y^+\}.
    • P\mathcal{P} = set of positive samples; N\mathcal{N} = set of negative samples.
      • At DINO location (h,w)(h,w), these become feature vectors: Ph,w={ϕ(y+)h,w},Nh,w={ϕ(x1)h,w,…,ϕ(xN)h,w,ϕ(ot)h,w}\mathcal{P}_{h,w}= \{\phi(y^+)_{h,w}\}, \quad \mathcal{N}_{h,w} = \{\phi(x_1)_{h,w}, \ldots , \phi(x_N)_{h,w}, \phi(o_t)_{h,w}\}
    • "generic kernel-weighted mean-shift form"
      • kernel-weighted mean, in generic form, is: μ(z)=∑ik(z,yi)yi∑ik(z,yi)\mu(z) = \frac{\sum_i k(z, y_i)y_i}{\sum_i k(z, y_i)}^ nearby samples contribute heavily; distant samples contribute little.
      • mean-shift direction refers to the fact that we are shifting zz using μ(z)\mu(z): the expression contains yi−zy_i - z because it is the arrow from current particle zz to another sample yiy_i.
      • generic in that the equation we have here omits details such as -
        • dividing features by their average pairwise distance
        • normalizing drift fields by magnitude
        • summing fields computed at multiple temperatures
    • The paper's normalized kernel at temperature τ\tau is: kτ(x,y)=exp⁡(−∣∣x~−y~∣∣2τD)k_\tau (x,y) = \exp \left(- \frac{||\tilde{x} - \tilde{y}||_2}{\tau \sqrt{D}}\right)where x~,y~\tilde{x}, \tilde{y} are feature vectors divided by their average pairwise distance. This keeps the kernel scale from changing drastically merely because one representation (i.e. one feature encoder's outputs) has larger magnitudes or more dimensions.
    • They use several temperatures, where a kernel with a small τ\tau responds mainly to nearby samples and a kernel with a larger τ\tau gives broader attraction and repulsion: V~h,w=∑τ∈TV~h,w(τ)\widetilde{V}_{h,w} = \sum_{\tau \in \mathcal{T}} \widetilde{V}_{h,w}^{(\tau)}
  3. The feature-space training target: let the generated image be xi=fθ(ϵi,c)x_i = f_\theta (\epsilon_i, c). The feature-space target is conceptually: ϕ(xi)h,wtarget=stopgrad[ϕ(xi)h,w+V~h,w]\phi(x_i)^\text{target}_{h,w} = \text{stopgrad} \left[\phi(x_i)_{h,w} + \widetilde{V}_{h,w}\right]The local loss is: ℓh,w=∣∣ϕ(xi)h,w−stopgrad[ϕ(xi)h,w+V~h,w]∣∣22\ell_{h,w} = \bigg|\bigg| \phi(x_i)_{h,w} - \text{stopgrad}\left[\phi(x_i)_{h,w} + \widetilde{V}_{h,w}\right] \bigg|\bigg|_2^2Then they average over locations: Lfeature=1HW∑h=1H∑w=1Wch,wℓh,w\boxed{\mathcal{L}_\text{feature} = \frac{1}{HW} \sum_{h=1}^H \sum_{w=1}^W c_{h,w} \ell_{h,w}}The motion weight is ch,w=1+λtanh⁡(αnh,w)\boxed{c_{h,w} = 1+ \lambda \tanh (\alpha n_{h,w})}where nh,wn_{h,w} is a normalized difference between the DINO features of the current frame and the true future frame at that location.
    • ^ thus locations where the gripper or manipulated object moves receive more weight than a static wall or table.
    • nh,w≥0n_{h,w} \geq 0 = normalized amount of visual motion at location (h,w)(h,w), α>0\alpha>0 controls how quickly the weight rises, λ≥0\lambda \geq 0 controls the maximum extra weight.
      • At 0 motion: nh,w=0  ⟹  tanh⁡(0)=0  ⟹  ch,w=1n_{h,w} = 0 \implies \tanh(0) = 0 \implies c_{h,w} = 1 → a static region receives baseline weight 1.
      • For large motion: tanh⁡(αnh,w)→1  ⟹  ch,w→1+λ\tanh (\alpha n_{h,w}) \rightarrow 1 \implies c_{h,w} \rightarrow 1+ \lambda → weight is bounded 1≤ch,w<1+λ1 \leq c_{h,w} < 1 + \lambda

DINO latent space

For the real-robot datasets, the implementation uses features from blocks 2, 5, and 8 of DINOv3 ViT-B/16. The resulting map is H×W×D=16×16×768H \times W \times D = 16 \times 16 \times 768, which means DriftWorld constructs a 768-dim. conditional drifting field at each of the 16×16=25616 \times 16 = 256 DINO locations and evaluates it on every generated particle. The resulting local particle losses are averaged over particles and motion-weighted across the 256 locations.

Stable Diffusion 3 VAE latent space

They additionally compute a drifting loss in the Stable Diffusion 3 VAE latent space, which outputs a representation 32×32×1632 \times 32 \times 16, so it contributes another: 32×32=102432 \times 32 = 1024local drifting losses.

Total feature-space drifting loss

Ltotal=LDINO+LVAE-latent\boxed{\mathcal{L}_\text{total} = \mathcal{L}_\text{DINO} + \mathcal{L}_\text{VAE-latent}}DINO is used only while constructing the training loss; it is not part of inference. To read more about inference, see section #Inference.

Speculation: Why might drifting in feature-space produce sharper images?

Suppose two generated grippers are shifted by a few pixels.

  • A raw pixel distance can be dominated by: lighting, background texture, tiny color difference, blur spread across neighboring pixels.
  • 💡 DINO features are more responsive to meaningful visual structure such as -
    • "this patch contains the gripper tip"
    • "this is an object boundary"
    • "this region contains the manipulated object"
    • 🔑 So the kernel neighborhood k(ϕ(x),ϕ(y))k(\phi(x), \phi(y)) is based on perceptual or semantic similarity rather than only exact RGB correspondence.

Different drifting space representations considered

  • RGB pixels: exact colors and pixel alignment
  • VAE latents: compressed visual appearance useful for reconstructing the image
    • The VAE was trained to encode enough information to reconstruct images, so its latent geometry strongly retains appearance, texture, color, and local detail. But Euclidean distance in that latent space is not guaranteed to be an ideal perceptual metric.
  • DINO features: higher-level visual structure and semantic/perceptual similarity
    • DINO was trained as a visual representation model, so its features tend to organize images more according to recognizable structure and content.
  • 🔑 The ablation shows that using only the VAE-latent drifting loss leads to blurrier results than adding DINO.

Tallying all fields and losses for one training condition

Consider one real-world training example, e.g. one Bridge-V2 transition.

  • It has one condition: c=(history,actions)c = (\text{history}, \text{actions})
  • It has:
    • one positive future y+y^+
    • N=64N = 64 generated particles x1,…,x64x_1, \ldots, x_{64}

DINO branch

Each generated and real image becomes 16×16×76816 \times 16 \times 768. there are 16×16=25616 \times 16 = 256 spatial locations.

  • At each spatial location (h,w)(h,w):
    • the positive is one vector zh,w+∈R768z_{h,w}^+ \in \mathbb{R}^{768}
    • each particle provides zi,h,w∈R768z_{i,h,w} \in \mathbb{R}^{768}
      • 💡 intuitively, zi,h,wz_{i,h,w} is DINO's description of what appears in that region of particle ii's generated image
    • the negative population contains the generated vectors, plus possibly the no-action vector
  • 🔖 For each generated particle ii, at every location (h,w)(h,w), compute a drift: Vi,h,wDINO∈R768V_{i,h,w}^\text{DINO} \in \mathbb{R}^{768}^ this is one vector
    • So for the DINO branch, the number of particle-location drift evaluations is: 64×256=16,38464 \times 256 = 16,384.
    • 🔑 At spatial location (h,w)(h,w), the drifting field is a function defined over the 768-dim. DINO feature space. Evaluating that field at particle ii's feature vector gives Vi,h,wDINOV_{i,h,w}^\text{DINO}, a 768-dim. instruction telling that particular feature vector how to move toward the ground-truth feature and away from nearby negative generated samples.
  • Its local loss is: ℓi,h,wDINO=∣∣zi,h,w−stopgrad(zi,h,w+Vi,h,w∣∣22\ell_{i,h,w}^\text{DINO} = ||z_{i,h,w} - \text{stopgrad}(z_{i,h,w} + V_{i,h,w}||^2_2
  • Then average over particles and take a motion-weighted average over locations:LDINO=1N∑i=1N1HW∑h=1H∑w=1Wch,wℓi,h,wDINO\mathcal{L}_\text{DINO} = \frac{1}{N} \sum_{i=1}^N \frac{1}{HW} \sum_{h=1}^H \sum_{w=1}^W c_{h,w} \ell_{i,h,w}^\text{DINO}

Mermaid diagram:

VAE-latent branch

Each image's VAE latent has shape 32×32×1632 \times 32 \times 16; there are 32×32=102432 \times 32 = 1024 locations. For each particle and latent location: Vi,h,wVAE∈R16  ⟹  N=64→64×1024=65,536 particle-location field evaluationsV_{i,h,w}^\text{VAE} \in \mathbb{R}^{16}\implies N=64 \rightarrow 64 \times 1024 = 65,536 \text{ particle-location field evaluations}The latent loss is: LVAE=1N∑i=1N1HW∑h=1H∑w=1Wch,wℓi,h,wVAE\mathcal{L}_\text{VAE} = \frac{1}{N} \sum_{i=1}^N \frac{1}{HW} \sum_{h=1}^H \sum_{w=1}^W c_{h,w} \ell_{i,h,w}^\text{VAE}

DINO + VAE combined

Ltotal=LDINO+LVAE-latent  ⟹  256 DINO local losses+1024 VAE-latent local losses\mathcal{L}_\text{total} = \mathcal{L}_\text{DINO} + \mathcal{L}_\text{VAE-latent} \implies 256\text{ DINO local losses} + 1024 \text{ VAE-latent local losses}where each local loss (local in the sense that this is a local spot (h,w)(h,w) on the global image) is a weighted mean over all generated particles NN.

Recap: What is the field?

The field at location (h,w)(h,w) is a function Vh,w:Rd→RdV_{h,w}: \mathbb{R}^d \rightarrow \mathbb{R}^dwhere d=768d = 768 for DINO and d=16d = 16 for the VAE-latent.

  • 💡 VV specifies: "For any possible (DINO/VAE) feature vector zz at this image location, here is the direction in feature space that it should move."
    • The generated particle supplies the query point zi,h,wz_{i, h, w} → evaluating the field there gives a single vector Vi,h,wfeature=Vh,w(zi,h,w)∈RdV_{i,h,w}^\text{feature} = V_{h,w}(z_{i,h,w}) \in \mathbb{R}^d
  • Vh,wV_{h,w} is the field
  • Vi,h,wV_{i,h,w} is the single arrow obtained by evaluating the field at particle ii

How to interpret the drift target?

Recall the drift target is zi,h,wtarget=zi,h,w+Vi,h,wfeaturez_{i,h,w}^\text{target} = z_{i,h,w} + V_{i,h,w}^\text{feature}

  • 💡 The vector Vi,h,wfeatureV_{i,h,w}^\text{feature} essentially answers - "How should DINO/VAE-latent's representation of this generated patch (h,w)(h,w) change so that it becomes more like the correct future patch and less like the wrong generated patches?"

Architecture

U-Net

The generator fθf_\theta is a U-Net. It takes Gaussian noise + history observations + future actions and produces a predicted future video. Mathematically: o^t+1:t+1+T=fθ(ϵ1:T,ot−F:t,at:t+T)\boxed{\hat{o}_{t+1: t+1+T} = f_\theta(\epsilon_{1:T}, o_{t-F:t}, a_{t: t+ T})}Unlike diffusion, they do not run this U-Net repeatedly at many noise levels → it runs once!

  • For simple datasets: the output is directly an RGB video.
  • For complex real-world datasets: the U-Net operates in the latent space of a Stable Diffusion 3 VAE: z^t+1:t+1+T=fθ(ϵ,zt−F:t,at:t+T)  ⟹  o^t+1:t+1+T=VAE-Decoder(z^t+1:t+1+T)\hat{z}_{t+1: t+ 1+T} = f_\theta (\epsilon, z_{t-F:t}, a_{t: t+ T}) \implies \hat{o}_{t+1: t+1+T} = \text{VAE-Decoder}(\hat{z}_{t+1: t+1+ T})

How history enters the U-Net

History observations are concatenated channel-wise with the Gaussian noise: for one predicted time index ii, this is conceptually:ui(0)=Concatchannels[ϵi,ot−F,…,ot]u_i^{(0)} = \text{Concat}_\text{channels}[\epsilon_i, o_{t-F}, \ldots, o_t]For latent-space operation, replace each oo with its VAE latent zz: ui(0)=Concatchannels[ϵi,zt−F,…,zt]u_i^{(0)} = \text{Concat}_\text{channels}[\epsilon_i, z_{t-F}, \ldots, z_t]The history therefore supplies the scene appearance and current physical state directly to every future-frame stream.

Shapes

  • BB = number of independent training conditions in the minibatch
  • NN = number of generated particles per condition
  • TT = number of predicted future frames
  • FhF_h = number of history frames
  • CzC_z = channels per image or latent frame
  • Hz,WzH_z, W_z = spatial dimensions
  • DaD_a = action dimension

Omitting BB: ϵ∈RN×T×Cz×Hz×Wz,obs∈RFh×Cz×Hz×Wz,a∈RT×Da\epsilon \in \mathbb{R}^{N \times T \times C_z \times H_z \times W_z}, \quad \text{obs} \in \mathbb{R}^{F_h \times C_z \times H_z \times W_z}, \quad a \in \mathbb{R}^{T \times D_a}The history must be supplied to every particle and predicted time index.

  • Flattening history along the channel axis: zhist-flat∈RB×(FhCz)×Hz×Wzz_\text{hist-flat} \in \mathbb{R}^{B \times (F_h C_z) \times H_z \times W_z}Broadcast it across NN particles and TT future indices: zhist-broadcast∈RB×N×T×(FhCz)×Hz×Wzz_\text{hist-broadcast} \in \mathbb{R}^{B \times N \times T \times (F_h C_z) \times H_z \times W_z}
  • Concatenate with noise: u(0)∈RB×N×T×((1+Fh)Cz)×Hz×Wzu^{(0)} \in \mathbb{R}^{B \times N \times T \times ((1 + F_h)C_z) \times H_z \times W_z}where u(0)u^{(0)} is the initial input to the U-Net (noise + history input vector).

Spatial-temporal U-Net blocks

At an intermediate U-Net layer, the network no longer stores RGB pixels: it stores learned features HlH^l, for layer ll: H(l)∈RB×T×Cl×Hl×WlH^{(l)} \in \mathbb{R}^{B \times T \times C_l \times H_l \times W_l} where:

  • BB = batch size
  • TT = predicted video frames
  • ClC_l = feature channels at U-Net layer ll
  • HlH_l = spatial height at that layer
  • WlW_l = spatial width at that layer

In this paper, U-Net convolutions are factorized into two operations: spatial and temporal.

Spatial convolution

Apply the same 2D convolution independently to each time index: this learns the spatial patterns inside each image, such as the edges, robot geometry, object shapes, and local contacts. S:,i,:,:,:=Convspatial(U:,i,:,:,:),i=1,…,TS_{:, i, :, :, :} = \text{Conv}_\text{spatial}(U_{:, i, :, :, :}), \quad i = 1, \ldots, T

Temporal convolution

Then, at each spatial location (h,w)(h,w), apply a temporal convolution across frames: this communicates information across time, such as where the gripper was in nearby frames, whether the object is moving, and temporal continuity. R:,:,:,h,w=Convtemporal(S:,:,:,h,w)R_{:, :, :, h, w} = \text{Conv}_\text{temporal} (S_{:, :, :, h, w})

Combined convolution

Thus a factorized block is approximately: U′=TempConv(SpatialConv(U))U' = \text{TempConv}(\text{SpatialConv}(U))This is cheaper than a full 3D convolution over (T,H,W)(T, H, W), while still modeling both spatial appearance and temporal evolution.

  • factorized - in that instead of doing a full Convspatial,temporal\text{Conv}_{\text{spatial}, \text{temporal}}, we've factored the two pieces into Convspatial\text{Conv}_\text{spatial} and Convtemporal\text{Conv}_\text{temporal}

Action-conditioning with FiLM

  • 💡 How FiLM gives frame ii action at+ia_{t+i}

Frame-wise FiLM is the mechanism behind how actions modulate future-frames in this model → how the conditioning on actions occurs.

  1. First, each action receives an embedding: ei=MLPa(at+i)e_i = \text{MLP}_a (a_{t+i})
  2. At each U-Net residual block ll, another learned projection turns that embedding into scale and shift vectors: (γi(l),βi(l))=WFiLM(l)ei+bFiLM(l)\left(\gamma_i^{(l)}, \beta_i^{(l)}\right)=W^{(l)}_{\text{FiLM}}e_i + b_\text{FiLM}^{(l)}
  3. If the block's normalized feature map for frame ii is: ... FiLM applies FiLM(Hi(l);at+i)=(1+γi(l))⊙Norm(Hi(l))+βi(l)\text{FiLM} \left(H_i^{(l)}; a_{t+i}\right) = \left(1 + \gamma_i^{(l)} \right)\odot \text{Norm} \left(H_i^{(l)}\right) + \beta_i^{(l)}The vectors γi(l),βi(l)∈RCl\gamma_i^{(l)}, \beta_i^{(l)} \in \mathbb{R}^{C_l} are broadcast across the spatial dimensions.
  • 💡 The important indexing is: at+i→(γi,βi)→features for predicted frame ot+i+1a_{t+i} \rightarrow (\gamma_i, \beta_i) \rightarrow \text{features for predicted frame } o_{t+i+1}So frame ii does not initially receive a pooled summary of the entire action chunk: it receives modulation derived from its corresponding action.

In tensor form: action embedding:Ea=[e0,…,eT−1]∈RB×T×DaFiLM parameters:Γ(l),Bl∈RB×T×ClH~b,i,c,h,w(l)=(1+Γb,i,c(l))Hb,i,c,h,w(l)+Bb,i,c(l)\begin{align*} \text{action embedding:}\quad & E_a = [e_0, \ldots, e_{T-1} ] \in \mathbb{R}^{B \times T \times D_a} \\ \text{FiLM parameters:}\quad &\Gamma^{(l)}, B^{l} \in \mathbb{R}^{B \times T \times C_l} \\ &\boxed{\widetilde{H}_{b, i, c, h, w}^{(l)} = \left(1 + \Gamma_{b,i,c}^{(l)}\right) H_{b, i, c, h, w}^{(l)} + B_{b,i,c}^{(l)}} \end{align*}

The shared time index ii is the mathematical reason that action at+ia_{t+i} modulates future-frame stream ii.

  • ⚠️ ^It is not a guarantee that the network will obey the action - it could still learn to ignore FiLM - but the architecture provides a direct, aligned conditioning path, and the drifting/motion-weighting losses penalize ignoring it.
    • 🔖 2 explicit mechanisms where the loss penalizes ignoring actions:
      • No-action negative: the negative repulsion term pushes the model to not ignore actions (i.e. predict something that resembles no actions)
      • Motion-weighted local losses: increases the contribution of moving locations → optimization pressure to follow the actions

FiLM vs. AdaLN

FiLM is a generalized version of AdaLN: both use conditioning information to produce an affine transformation: condition→(scale,shift)\text{condition} \rightarrow (\text{scale}, \text{shift})

  • FiLM: The basic FiLM equation is: FiLM(H;c)=γ(c)⊙H+β(c)\text{FiLM}(H; c) = \gamma(c) \odot H + \beta(c)It may be applied to convolutional features, with or without a normalization immediately before it.
  • AdaLN: Adaptive LayerNorm is a normalization-specific (LayerNorm) form of conditional affine modulation: AdaLN(H;c)=γ(c)⊙LayerNorm(H)+β(c)\text{AdaLN}(H; c) = \gamma(c) \odot \text{LayerNorm}(H) + \beta(c)
  • 📍 The DriftWorld paper only says that it uses F

Feature map H(l)H^{(l)}

Let H(0)=u(0)H^{(0)} = u^{(0)} be the concatenated noise and history input, see section #Shapes.

  • The first U-Net layers transform it:
    • H(1)=Block(0)(H(0))H^{(1)} = \text{Block}^{(0)} (H^{(0)})
    • H(2)=Downsample(Block(1)(H(1)))H^{(2)} = \text{Downsample}\left(\text{Block}^{(1)}(H^{(1)}) \right)
    • ... and so on

H(l)H^{(l)} = the intermediate activation tensor after some U-Net layer or residual block ll with shape: H(l)∈RB×T×Cl×Hl×WlH^{(l)}\in \mathbb{R}^{B \times T \times C_l \times H_l \times W_l}

  • A "normalized feature map" would mean something like: Hˉ(l)=Norm(H(l))\bar{H}^{(l)} = \text{Norm} (H^{(l)})

The full architecture

  1. Gaussian video noise
  2. History frames concatenated channel-wise
  3. Action MLP
  4. U-Net encoder
  5. Residual blocks with frame-wise FiLM
  6. Factorized spatial and temporal convolutions
  7. Attention at selected resolutions
  8. U-Net bottleneck
  9. U-Net decoder with skip connections
  10. Output RGB frames or VAE latents
  11. Optional VAE decoder for real-world datasets
  12. During training only, DINO/VAE feature extraction for the drifting loss

The reported U-Net configurations are:

Dataset groupParametersBase channelsChannel multipliers# res blocksAttention resolutions# negative samplesFeature extractorTemperatures τ\tau
Push-T8.73M96[1,1,1,1][1, 1, 1, 1]2[4,8][4, 8]8None{0.02.0.05,0.2}\{0.02. 0.05, 0.2\}
Robomimic74.2M96[1,2,4,4][1,2,4,4]2[4,8][4,8]32None{0.02.0.05,0.2}\{0.02. 0.05, 0.2\}
Bridge-RT-1/Language Table160M160[1,2,4,4][1,2,4,4]2[4,8][4,8]64Dinov3{0.02.0.05}\{0.02. 0.05\}

Compact math summary: ui(0)=Concat[ϵi,Enc(ot−F:t)],ei=MLPa(at+i),Hi(l+1)=ResBlock(l)(),(γi(l),βi(l))=Wlei+blo^t+1:t+1+T=Dec(UNetθ(u(0),e1:T))\begin{align*} u_i^{(0)} &= \text{Concat}[\epsilon_i , \text{Enc}(o_{t-F:t})], \\ e_i &= \text{MLP}_a(a_{t+i}), \\ H_i^{(l+1)}&= \text{ResBlock}^{(l)}\left(\right), \quad \left(\gamma_i^{(l)}, \beta_i^{(l)}\right) = W_l e_i + b_l \\ \hat{o}_{t+1: t+ 1+ T} &= \text{Dec}\left(\text{UNet}_\theta\left(u^{(0)}, e_{1:T}\right)\right)\end{align*}The U-Net makes the video; the DINO defines a better geometry for telling the U-Net how its generated samples should drift during training.

Mermaid diagram

Inference

Inference steps

Training vs. inference: DINO

During training

For a generated latent z^=fθ(ϵ,zhistory,a)\hat{z} = f_\theta (\epsilon, z_\text{history}, a), the pipeline is approximately: z^→VAE-Deco^→DINOϕ(o^)\hat{z} \xrightarrow{\text{VAE-Dec}} \hat{o} \xrightarrow{\text{DINO}} \phi(\hat{o})The ground truth image also passes through DINO: o+→DINOϕ(o+)o^+ \xrightarrow{\text{DINO}} \phi(o^+)The DINO features are used to compute the training drift and loss: LDINO\mathcal{L}_\text{DINO}. Gradients then flow back through the generated-image path to train the U-Net.

At inference

There is no ground-truth future and no training loss to compute at inference! Therefore no DINO comparison is needed.

The inference pipeline is only: ϵ,zhistory,a→fθ U-Netz^future→VAE-Deco^future\epsilon, z_\text{history}, a \xrightarrow{f_\theta \text{ U-Net}} \hat{z}_\text{future} \xrightarrow{\text{VAE-Dec}} \hat{o}_\text{future}So at inference, we use:

  1. VAE encoder for history images, when operating in latent space
  2. the trained action-conditioned U-Net fθf_\theta
  3. the VAE decoder for the predicted future latents
  • 💡 DINO is a training-time teacher/metric, not part of the deployed generator
    • Analogy: we train the student using a detailed answer key, but the student does not carry the answer key during the exam.

Training specifics

TL;DR: For one batch element (problem) bb: (this is one transition of (image at time tt) → (ground truth image at t+1t+1))

  1. At each spatial chunk (h,w)(h,w) , treat the corresponding features from the NnegN_\text{neg} generated futures and the one real future as points in feature space.
  2. Use their kernel similarities to assign each generated point an arrow toward the real point and away from the generated/no-action cloud.
  3. Train the U-Net so its generated features moves by that arrow.
  4. Average these local losses over particles and spatial locations, then combine the independent losses across the batch.

My raw unedited summary: We take one spot (h,w)(h,w) on the image, the feature latents of this same patch for all generated NnegN_\text{neg} samples and the positive sample + kernel, use those points + kernel which weights the attraction/repulsion based on feature-space proximity to form a vector field function VV that pulls the generated → true point & pushes generated points away from each other / no action, and then apply that vector to each of the generated points to show the displacement that would occur in one drift step (weighted by some η\eta), and then do MSE on the actual particle - (particle + drift update). And then we sum up the MSEs across all NnegN_\text{neg} (average? 1/ N_neg?) and do this for all (h,w)(h,w) spots. And then do this over all problems in batch BB.

One training step

drift world algo 1.png

From the paper:

When training on a batch of BB videos, we perform this step (Algorithm 1) independently for each video. Since every video contains a unique sequence of history observations and actions, the model must compute BB distinct independent conditional drifting fields. Within each of these BB fields, the drift is calculated using a single positive sample (the ground-truth future frames) and NnegN_\text{neg} negative samples (the model's generated future frames). The total loss is the sum of the BB individual losses in the batch.

  • 🔑 Walking through these steps in more detail: Suppose the batch contains BB different training videos.
  1. Batch element bb has its own condition: cb=(ot−F:t(b),at:t+T−1(b)),b∈[1,B]c_b = \left(o_{t-F:t}^{(b)}, a_{t: t+T-1}^{(b)}\right), \quad b \in [1, B]and one ground-truth feature yb+y_b^+, NnegN_{\text{neg}} generated futures xb,1,…,xb,Nnegx_{b,1}, \ldots, x_{b, N_\text{neg}}.
  2. Because different videos generally have different scenes, histories, actions, and correct futures, the field for video bb is constructed only from: {yb+,xb,q,…,xb,Nneg,ot}\{y_b^+, x_{b,q}, \ldots, x_{b, N_\text{neg}}, o_t\}It does not use the positive or generated samples belonging to another batch element b′b'. So at the broadest level: V(b)=Vp(⋅∣cb),qθ(⋅∣cb)V^{(b)} = V_{p(\cdot \mid c_b), q_\theta(\cdot \mid c_b)}
  3. Then the full batch contains: V(1),V(2),…,V(B)V^{(1)}, V^{(2)}, \ldots, V^{(B)} → these are the aforementioned "BB distinct, independent conditional drifting fields."
    • Independent in the sense that V(b)V^{(b)} only uses samples conditioned on cbc_b.
  • ❓ Why must the drifting fields be separate?
    • Imagine batch element 1 is c1c_1 = "kitchen scene, move gripper right" and batch element 2 is c2c_2 = "table scene, move gripper left"
    • 💡 It would make no sense for particle x1,ix_{1, i} generated for the first scene to be attracted toward the ground-truth future y2+y_2^+ from the second scene.
    • 🔖 So the drift for condition 1 uses: y1+,x1,1,…,x1,Ny_1^+, x_{1, 1}, \ldots, x_{1,N} and the drift for condition 2 uses: y2+,x2,1,…,x2,Ny_2^+, x_{2, 1}, \ldots, x_{2, N} → that is conditional drifting!
  • ❓ How does this fit with our analysis in Section #Feature space drifting? drift world chat vector field pipeline.png
  • 🔑 Note that one conditional vector field is a collection of local feature-space fields: V(b)={Vb,h,w}h=1,w=1H,W  ⟹  one condition-level field=a grid of local feature-space fieldsV^{(b)} = \{V_{b, h, w}\}^{H,W}_{h=1, w=1} \implies \boxed{\text{one condition-level field} = \text{a grid of local feature-space fields}}chatgpt driftworld field.pngScreenshot 2026-07-30 at 3.01.59 PM.png

Normalization

To ensure that the drifting field is insensitive to the raw magnitudes and dimensionalities of samples in the feature spaces, the paper applies two normalizations:

  1. Feature normalization so that the kernel takes on a reasonable range of values regardless of the samples' dimensionality
    • Divide samples by their average pairwise distance
    • Then compute the kernel as: k(x,y)=exp⁡(−1τC∣∣x~−y~∣∣)k(x,y) = \exp \left(-\frac{1}{\tau \sqrt{C}}||\tilde{x} - \tilde{y}|| \right)
  2. Normalize the drifting field by its magnitude so that multiple drifting fields can be summed together

Multi-temperature aggregation

After applying normalizations (#Normalization), they aggregate the drifting field across multiple kernel temperatures τ\tau: V~=∑τV~τ\tilde{V} = \sum_\tau \tilde{V}_\tau

Motion weighting

[Read into more.]

Feature extractor

On real-robot datasets, they compute the drifting loss in (i) the feature space of DINOv3 and (ii) the VAE latent space. The total loss is formed by summing these two components.

  • DINOv3: 16×1616 \times 16 grid of 768768-dim. tokens, so we compute 256256 separate drifting losses on each of the spatial locations and take their weighted mean to form the overall DINOv3 drifting loss
  • VAE-latent: 32×3232 \times 32 grid of 1616-dim. tokens, so we compute 10241024 separate drifting losses on each of the spatial locations and take their weighted mean to form the overall latent drifting loss

Self-forcing

Model training of DriftWorld occurs in 2 stages:

  1. Condition DriftWorld on the ground-truth history frames
  2. Initialize from stage 1 checkpoint^ and train by letting DriftWorld generate autoregressively, taking its own generated frames (with gradient detached) as input. Each of the nnegn_\text{neg} generated negative samples continues its own rollout.

Post-training on on failure demonstrations

For the Robomimic Lift and Can tasks, DriftWorld is initially trained on the multi-human dataset, which contains only successful demonstrations → i.e. the model is trained on a biased distribution with overly optimistic estimates of policy success.

  • 🔑 They post-train the models (DriftWorld + baselines) on a dataset with a large percentage of failure demonstrations, which is created by rolling out early checkpoints of a diffusion policy.
  • This enables the models to accurately simulate failures (since a good world model should simulate what actually would happen, which can consist of success and failure).

Data

TaskNumber of trajectories
Push-T500 expert demonstrations + random-exploration trajectories (does not say number)
RT-187,212
Language Table442,226
Robomimic700 trajectories for each of Lift, Can, and Square, so 3×700=21003 \times 700 = 2100 total
Note that one trajectory yields many training windows: from one long video they can sample many tuples of the form: (ot−F:t,at:t+T,ot+1:t+1+T)(o_{t-F:t}, a_{t: t+T}, o_{t+1: t+1 + T})so the actual number of training examples seen by SGD is much larger than the raw trajectory count.