Demos to Deploymenta hands-on lab

How robots copy, drift, and keep moving while they think

A line-painting robot learns Main Street by watching a master painter. One pothole and it wanders off; a big brain and it stops to think with the nozzle open. Every mistake stays on the road. This lab walks the imitation-learning and real-time-execution chapters of Hugging Face's Robot Learning tutorial, ACT, SmolVLA and Real-Time Chunking, with the real algorithms on a toy street. About 75 minutes of play.

0 · Main Street: the master paints, the apprentice copies

The town is repainting the centre line of Main Street with a robot. Nobody wants to program it, so the master painter drives it by joystick from the kerb, twenty times down twenty different streets, and every tick is logged: what the robot's camera read, and how the master steered. Those logs are the demonstrations. The robot's own steering rule, its policy, will be learned from them. Every term with a wavy red underline is tappable.

The striper = the robot
its steering rule is the policy
The master = the human demonstrator
driving by teleoperation
The logbook = the demonstrations
20 runs, 50 pages a second
The apprentice's notebook = the training set
what it looks things up in (nearest neighbours)
A pothole = a disturbance
knocks the heading 0.2 rad (steps 0–2)
A work order = an action chunk
50 waypoints, one per tick (step 3)
The drafting desk = inference
its think time is the latency (step 3)
The wet cement = a fork in the demos
half went left, half right (step 4)
A kink = a seam between chunks
a blob is a stop (steps 3–7)

Covers Robot Learning tutorial §4: imitation learning, behaviour cloning · HF Robotics Course Unit 1: recording a LeRobotDataset by teleoperation

Watch the master paint

The street is drawn straightened, left to right, and stretched sideways so that centimetres show (the factor is printed in the corner of every street): the grey band is the asphalt, the dashed chalk line is the centre line, and the yellow is paint. The master's hand wobbles a little, and the logbook records that too.

0
runs logged
0
pages (one per tick)
–
pages within 5 cm of the line
–
furthest the master strayed

The apprentice takes the joystick

The simplest way to learn from the logbook is behaviour cloning: at every tick, read the camera, find the five most similar pages in the notebook, and steer the way the master steered on them. Here the learner is a lookup, not a neural network, so you can see exactly which pages it used. A neural network trained on the same pages has no examples there either: it would fill the gap with a different guess, but it would still be a guess.

–
metres painted off the line (> 5 cm)
–
furthest off the line
–
the master on the same street
–
pages it found at its worst moment
the apprentice's paintthe master's line on this streetpothole
Guess first!
On the clean street, the apprentice paints as well as the master. After the pothole at 4 m, what happens?
3.80 m of its paint is more than 5 cm off; the master, kicked by the same pothole, never strays past 4.3 cm. At its worst moment, 7.9 cm off, the five pages it found were all about 3 cm off, at the very edge of what the master ever did: the notebook has no page for being nearly 8 cm off, so it steers as if it were 3.
Say it out loud
Behaviour cloning is supervised learning on the expert's states. It copies the master perfectly where the master went, and has nothing to copy anywhere else.

1 · Off the map: why small mistakes compound

The notebook is a map of situations. Plot every page by the striper's offset from the line and its heading error, and the master's twenty runs fill a tiny patch around (0, 0): a good painter is never far off. The pothole throws the apprentice out of that patch, and from then on every lookup returns the edge of the patch. That's covariate shift: the learner's own mistakes change the questions it gets asked.

Covers Robot Learning tutorial §4: compounding errors in BC · Ross & Bagnell (2010) via Ross, Gordon & Bagnell (2011), Theorem 2.1: J(π) ≤ J(π*) + T²ε

The notebook map

–
map cells with a page
–
of the run spent outside the pages
Each cell is 3.3 cm of offset by 0.033 rad of heading. The yellow cells hold the master's pages. The apprentice's run is drawn from the pothole on: every tick it stands outside the yellow patch, the nearest page is somewhere on the patch's edge.
a page from the master's runsthe apprentice after the pothole

Make the street longer

Ross and Bagnell's bound for behaviour cloning: if the learner errs with probability ε per step on the expert's states, over a horizon of T steps it can make up to T²ε mistakes, because a mistake early on can cost every step after it. Run twelve streets at each length, with potholes at 0.08 per metre, and see how the off-line paint grows.

Guess first!
Go from 8 m streets to 32 m streets: four times the length, with potholes at the same rate. How much more off-line paint does the apprentice leave?
About 1.5 m to 12.1 m: 7.9×. Each pothole costs more the longer the apprentice has left to wander, so the total grows faster than the street. It's short of the full T² because a later pothole sometimes knocks it back towards the line; the bound is the worst case. The master stays at 0.00 m until 32 m.
Guess first!
The master's twenty runs: what share of the pages are within 5 cm of the line?
100.0%, and 99.4% have the heading within 0.05 rad. A good demonstrator is the problem: their data never shows a recovery, because they never needed one.
Say it out loud
The expert's data only covers the expert's states. One mistake takes the learner off that map, where every answer is a guess from the edge, so errors compound: up to T²ε over a horizon of T.

2 · The master rides along: DAgger

The fix is to get pages for the places the apprentice actually goes. DAgger does it in rounds: the apprentice drives six practice streets full of potholes (with the master grabbing the joystick back a share β of the time), the master rides along and says what he would steer at every state it reached, those pages go into the notebook, and the apprentice is refit. Round 1 was the demonstrations themselves (β₁ = 1); after that β halves each round.

Covers Ross, Gordon & Bagnell (2011), Algorithm 3.1: π_i = β_i·π* + (1 − β_i)·π̂_i, β_i = p^(i−1) · Theorem 3.2: cost linear in T

Ride along, round by round

1
round
1
β this round
–
pages in the notebook
–
map cells with a page
Green cells hold pages the master wrote riding along: what he would steer from where the apprentice actually was.
the master's runspages written riding alongthe pothole run
Guess first!
Instead of riding along, the master logs twenty more ordinary runs: forty in all. On the pothole street, what happens?
4.96 m off the line, at worst 24.3 cm: no better than with twenty. Twenty more runs of a master who never leaves the line are twenty more pages of being on the line. One round of riding along takes the same street to 0.00 m off, at worst 3.1 cm.
Guess first!
After one round of riding along, the apprentice on the pothole street paints…
0.00 m off, at worst 3.1 cm. The pages that matter are the ones for being 5–10 cm off and pointing away, and those only exist where the apprentice went. Over twelve 16 m streets with potholes: 4.50 m off before, 0.16 m after three rounds (the review board's case 3).
Say it out loud
More expert demonstrations don't fix drift; labels on the learner's own states do. DAgger collects them by letting the learner drive and the expert annotate, which makes the cost grow linearly in T instead of quadratically.

3 · The drafting desk: big policies think in chunks

The apprentice now gets a big brain, the kind of vision-language-action model that reads cameras and instructions. A model that size can't answer fifty times a second, so it answers once with a work order: 50 waypoints, where the nozzle should be on each of the next 50 ticks. A fixed servo steers to them. π0 and SmolVLA both predict 50 actions; ACT predicts 100, and in its ablation success rose from 1% with one action at a time to 44% with chunks of 100. The catch is time. This step pulls over to think: synchronous inference.

Covers Robot Learning tutorial §4: action chunking (ACT), "Optimized Inference" · π0: H = 50 at 50 Hz, re-plan every 25 actions · RTC §4.2: 76 ms model latency, d ≈ 6 ticks with the network

Stop, think, drive

think time d10 ticks · 200 ms
waypoints driven per order (s)
0.0 s
clock
–
work orders
0
blobs
–
time stopped
waypoints to drivepreviewed by the servo, then droppedstopped (timeline)
Guess first!
Think time 10 ticks (200 ms), drive 25 waypoints per order. What share of the trip is the striper standing still?
d/(d + s) = 10/35 = 28.6%, and the 40-street fleet measures 28.9%: 6.7 s of 23.3 s, in about 34 blobs. Halve the order to 10 waypoints and it's 50%.
Guess first!
To stop less often, drive all 50 waypoints of every order. What's the cost?
Idle drops to 16.7% at d = 10, but the striper now drives a full second on each plan, and off-line paint goes from 0.74 m to 1.55 m: the far end of a chunk is the part predicted from the oldest information. π0 re-plans after 25 of its 50.
Say it out loud
Big policies predict a chunk of actions because they can't think every tick. Thinking synchronously makes the robot idle d/(d + s) of the time; driving more of each chunk stops less but reacts later.

4 · The committee: averaging overlapping chunks

Now there's wet cement on every street, and the master went round it on the left in half his runs and on the right in the other half. A work order is a sample from those runs, so it commits to one side. ACT's way to drive smoothly is temporal ensembling: ask for a new order every tick, and drive, at each tick, the weighted average of every order that has a waypoint for it, weights exp(−m·i) with i = 0 the oldest and m = 0.01 (from ACT's code). Every order votes. That smooths the seams, and it is fifty orders a second, with d of them being drafted at once while each one thinks: d times the compute of a single desk.

Covers ACT §IV-A, Algorithm 2: "we query the policy at every timestep", w_i = exp(−m·i) · LeRobot: temporal ensembling requires n_action_steps = 1 · RTC: temporal ensembling "performs poorly across the board" in simulation and couldn't run on the robots at +100 ms

The committee drives

think time d25 ticks · 500 ms
m (larger = older votes count more)0.01
The votes for one tick where the master starts to swerve: each dot is one order's waypoint for that tick, blue if that order went left, purple if right, fainter the less it weighs. The dashed line is what the committee drives.
–
streets with tracks in the cement
–
streets with a side flip
–
orders asked for per second
–
kinks per street
Guess first!
With no think time (d = 0) the committee paints round the cement on all 40 streets. At d = 25 (500 ms), how many end up with tracks in the cement?
21 of 40. With half a second of lag, the votes for the swerve come from orders drafted before the striper had committed; some went left, some right, and the average of left and right is straight ahead, into the cement. It's Fork in the Road's averaging problem, now across time.
Say it out loud
Temporal ensembling queries every step and averages overlapping chunks. Smooth when the plans agree; at a fork it averages two good plans into a bad one, and it costs a forward pass per control tick, d of them in flight at once.

5 · Order ahead: asynchronous inference

SmolVLA's answer to the blobs: never pull over. Keep driving the current order and radio for the next one while there are still waypoints in hand. The rule is one number, the threshold g: send a fresh observation whenever g·50 or fewer waypoints remain. g = 0 waits for an empty queue (the paper's sequential limit, here: drive all 50, then stop); g = 1 would ask at every tick, but with one order in flight at a time it asks again the moment the last one lands, every d ticks. When the new order lands, the waypoints that overlap the old queue are merged by an aggregation rule; the numbers below use "keep the newest" unless you pick another. The queue never runs dry if g ≥ d/50.

Covers SmolVLA §3.3, Algorithm 1: |A_t|/n < g, n = 50 · §4.6: async finished tasks ~30% faster (13.75 s → 9.70 s) and placed 19 cubes in 60 s against 9 · LeRobot async: chunk_size_threshold (0.5 in code), aggregate_fn "weighted_average" = 0.3·old + 0.7·new

Drive and order ahead

think time d10 ticks · 200 ms
threshold g0.5
overlap aggregation
0.0 s
clock
–
waypoints in the queue
0
blobs
–
vs stop-and-think (s = 25)
Guess first!
Think time 10 ticks. What is the smallest g that keeps the queue from running dry?
d/n = 10/50 = 0.2: ask when 10 waypoints are left and the new order lands just as they run out. Below it the striper still stops (2.0 s a street at g = 0.1); from 0.2 on it stops only once, for the very first order. At g = 0.5 a street takes 16.8 s against 23.3 s for stop-and-think, 28% faster; that it lands near SmolVLA's ~30% is a coincidence of these settings, not a reproduction.
Guess first!
Think time 20 ticks. Go from g = 0.5 to g = 1: ask for a fresh order as often as possible. At the cement…
27 of 40 streets flip sides at g = 0.7 and 28 at g = 1, against none at 0.5, and 19 to 24 end in the cement. Every fresh order is a fresh sample, and each one that lands replaces a plan the striper was already following. Step 6 looks at that seam.
Say it out loud
Async inference keeps acting while the next chunk is computed: ask when the queue falls to g·n, and it never runs dry once g ≥ latency/(Δt·n). It removes the stops; it doesn't decide how the new chunk joins the old.

6 · Seams: switching to a stale plan

The plainest way to think while moving, the RTC paper's "naive async": start drafting the next order d ticks before the current one is due to run out, and switch to it the moment it lands, dropping the waypoints whose time has passed. The new order was drafted from a camera frame d ticks old, without knowing which waypoints the striper would drive in the meantime. Where the two plans disagree there's a seam; at the cement, where they can disagree about the side, there's a side flip.

Covers RTC §2: inference delay d = ⌊δ/Δt⌋, execution horizon s, d ≤ s ≤ H − d · "naively switching chunks as soon as the new one is ready"

Switch on arrival

think time d25 ticks · 500 ms
0.0 s
clock
0
kinks
0
side flips
–
in the cement
▲ where a new order took over^ a kinktracks in the cement
Guess first!
Naive switching, 40 streets. Up to d = 20 (400 ms) no street flips sides. At d = 25 (500 ms)?
26 of 40 flip and 19 end with tracks in the cement. At 500 ms the order drafted just before the swerve lands mid-swerve, and half the time it was a sample from the other side. Below that, the seams still grow: 0.4 kinks a street at d = 5, 5.3 at d = 20.
Say it out loud
Switching to a new chunk the moment it lands joins two plans that were drafted apart. The longer the delay, the bigger the seam, and at a fork the new plan can be the other mode.

7 · Tracing paper: Real-Time Chunking

Physical Intelligence's fix keeps the async timing and changes the drafting. By the time the new order lands, the first d of its waypoints will already have been driven from the old order: they are frozen, and the new order must continue them. The rest of the overlap is soft: the new order is pulled towards the old one with weights that decay to zero, so it eases from the old plan into the new instead of jumping. RTC does this by guiding a flow-matching sampler (inpainting), with no retraining. The notebook has no sampler to guide, so this page uses an analogue over its pages: draw the 16 most similar, shift each to continue the frozen waypoints, weight each by its agreement under the soft mask, sample one, and blend it in with the same mask. The mask is RTC's; the conditioning is a lookup-table stand-in for its guidance.

Covers RTC (Black, Galliker & Levine 2025) eq. 5: W_i = 1 for i < d; c_i(e^c_i − 1)/(e − 1), c_i = (H − s − i)/(H − s − d + 1), for d ≤ i < H − s; 0 after · robust to delays "in excess of 300 milliseconds"; 20% faster than synchronous on π0.5

The soft mask

think time d10
driven per order s25

Naive or tracing paper, same street, same delay

think time d25 ticks · 500 ms
how the new order joins
0.0 s
clock
0
kinks
0
side flips
–
in the cement

What it doesn't fix: reacting to something new

Pour the cement late, 1.6 m ahead of the striper, and measure how far it drives blind: metres on orders drafted before the pour. Frozen waypoints are, by design, not up for revision.

Guess first!
d = 25 (500 ms), 40 streets. Naive switching flipped sides on 26. With tracing paper?
1 of 40, and 2 with tracks in the cement against 19; kinks drop from 29.3 a street to 7.5. The frozen waypoints carry the side the striper has committed to, and pages from that side continue them best. It isn't free: at short delays the tracing-paper striper paints a little more off the line than plain switching (the table's last column), because it keeps leaning on an older plan.
Guess first!
Cement poured 1.6 m ahead, d = 10. Which drives blind the shortest distance?
Stop-and-think with s = 10: 0.07 m, because it looks again every 10 waypoints, but it stands still 16.7 s per street. Tracing paper with s = 25 drives 0.63 m blind; with s = 10 it's 0.27 m while stopping only for its first order. How far it drives blind is set by s and d, not by how the orders are joined; but what it does next isn't. Tracing paper with s = 25 ends in the cement on 3 of 40 streets against 0 for plain switching: the soft mask leans on a plan drafted before the pour.
Say it out loud
Real-Time Chunking freezes the actions that will run before the new chunk lands and inpaints the rest towards the old chunk under a decaying mask. Async timing with far fewer seams and mode flips; reaction still costs d plus the execution horizon, and leaning on the old plan has a price when the world changes.

★ Road-crew review board

Three stripers came back with complaints from the town. For each: run it as configured, pick a fix, re-run it on twenty streets, and name the cause. The tempting wrong fixes are on the list, and they fail for the reason the step taught. Each case is scored on the re-run and the cause.

☆☆☆

✓ Field test

Ten questions. Answer each by operating the widget in the step named, not from memory. Eight or more earns the check.

What's exact here, and what's a teaching model

  • The real algorithms: behaviour cloning as supervised learning on the demonstrator's (observation, action) pairs; DAgger's loop and its β_i = p^(i−1) mixing (Ross, Gordon & Bagnell 2011, Algorithm 3.1); synchronous execution and its idle share d/(d + s); naive asynchronous switching; ACT's temporal ensembling, a query every tick and w_i = exp(−m·i) with w₀ the oldest and m = 0.01 (ACT's released code); SmolVLA's asynchronous queue with threshold g (asked when |A|/n ≤ g, as LeRobot's code does), the g = 0 sequential limit and three of LeRobot's four aggregation rules; Real-Time Chunking's frozen prefix, s = max(d, s_min) and soft mask (eq. 5). Waypoints are indexed by actions executed, not wall time, as LeRobot's async client indexes actions by timestep.
  • Teaching models, labelled on the page: the street (two sines), the striper (a unicycle at 1 m/s, 50 Hz), its servo (pure pursuit on the waypoint 12 ticks ahead), the potholes (heading kicks), the cement and its detour, and the master (pure pursuit plus a small wobble) are hand-designed. The apprentice is a 5-nearest-neighbour lookup over the logbook, a real learner but not a neural network; the "big brain" of steps 3–7 is the same lookup with a simulated think time. RTC proper guides a flow-matching sampler; here it is an analogue over the notebook's pages (shift to continue the frozen prefix, weight by masked agreement with a chosen width, blend with the mask): RTC's mask and timing, a stand-in for its guidance. Every run is seeded, so it is the same for everyone.
  • The directions are real; the striper isn't a real robot. Real chunks are joint targets from camera frames at the robot's control rate (50 Hz for ACT and π0, 30 fps in SmolVLA's experiments), policies are networks with up to hundreds of millions of parameters, and their failures are messier. The drift, the blobs, the seams, the averaged fork and the frozen prefix are the same ideas at that scale.

Sources (exact quotes and sections in SOURCES.md): Capuano et al., Robot Learning: A Tutorial (2025), §4–5 · Ross, Gordon & Bagnell, A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning (2011) · Zhao et al., Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (ACT, 2023) · Black et al., π0 (2024) · Shukor et al., SmolVLA (2025) and the LeRobot async inference docs · Black, Galliker & Levine, Real-Time Execution of Action Chunking Flow Policies (2025).

Part of a series of hands-on labs: Inference Kitchen (serving) · Finishing School (post-training) · Arm Playground (kinematics and control) · Policy Pond (reinforcement learning) · Fork in the Road (diffusion policies) · Duck's-Eye View (robot vision) · Demos to Deployment (imitation learning and real-time execution) · Inside a VLA (what the drafting desk is doing)