The 8 GB Lab Book · Chapter 28

Architecture that buys Hertz

Rig
MuJoCo sim of the biped
Mode
sim
Summary
In the sim, torque held 30 ms stale made the biped fall at 0.83 s, before its first planned step. Staleness cost phase, not distance.

What I expected

My prior was a distance model. A stale command puts the foot where the body was t_lag ago. The cost is s = v x t_lag. At 0.15 m/s, the cost is millimetres to a few centimetres. I expected that the walk would continue at all seven lags, with a shorter stride. I also expected a possible stumble at 250.

I also expected that the fall time, if there was a fall, would decrease when the lag increased. A more stale command would cause an earlier fall.

The theory

Two models of staleness: distance, and phase

Distance model (arithmetic, my prior)

s = v x t_lag;  m/s x s = m
0.15 x 0.030 = 0.0045 m = 0.4 cm
0.15 x 0.120 = 0.018 m = 1.8 cm
0.15 x 0.250 = 0.037 m = 3.7 cm
= predicts a short step, never a fall

Phase model (estimate)

a delay d costs 360 x d x f_c degrees
f_c = loop crossover, call it 5 Hz (guess)
30 ms: 360 x 0.030 x 5 = 54 degrees
120 ms: 216 degrees, past any margin
= predicts a fall, before any step

The unit check is that s x 1/s is dimensionless, and times 360 gives degrees. The pendulum sets the clock, tau = sqrt(l / g), where l is the CoM height. I use 0.8 m for l (not measured), and tau = sqrt(0.8 / 9.81) = 0.29 s. 30 ms is a tenth of tau. Physics permitted it, but this controller did not.

The sweep, what fell and when (sim, measured, 8 s window)

0 ms
1.19 m walked
30 ms
fell at 0.83 s
60 ms
fell at 0.68 s
0.83 s is before the first planned step, so no distance model applies: there was no step to shorten. The phase model fits these falls. My prior does not.

The setup

Render + sweep (Mac, ~6 min)
cd ~/Documents/workspace/Walker-CAD/Something
python3 walking/render_stale_action.py --lag-ms 120
cat output/day28/stale_sweep.json

The measurement

WhatExpectedMeasuredNote
baseline speed (lag 0)-0.15 m/s, 1.19 m in 8 ssim
lag 30 mss = 0.4 cmfell at 0.83 ssim, 8 s window
lag 60 mss = 0.9 cmfell at 0.68 ssim, 8 s window
lag 90 mss = 1.3 cmfell at 0.74 ssim, 8 s window
lag 120 mss = 1.8 cmfell at 0.86 ssim, 8 s window
lag 180 mss = 2.7 cmfell at 1.04 ssim, 8 s window
lag 250 mss = 3.7 cmfell at 1.35 ssim, 8 s window
Measured in the MuJoCo sim unless the row says estimate or predicted.
Command staleness vs time to fall, MuJoCo biped, same controller (8 s window; 0 ms walked the whole window)
Fig 28.1Command staleness vs time to fall, MuJoCo biped, same controller (8 s window; 0 ms walked the whole window).

Where the phase goes: the loop with a FIFO in it

  1. Sensorreads state
  2. Controllercomputes torque
  3. FIFOheld t_lag
  4. Motorapplies
The last box feeds the first. Every other box is fast; the FIFO adds t_lag of pure delay, and delay is the one thing a gain cannot undo. Cache, chunk and gate each put a FIFO in this loop unless they stay out of it.
lag mss = v x t (cm, arith.)fell at (s)x at fall (m)
00.0-1.19 at 8 s
300.40.830.30
600.90.680.19
901.30.740.35
1201.80.860.23
1802.71.04-0.11
2503.71.35-0.56
real motors-not measured yet-
Measured: MuJoCo, 35.4 kg URDF, torque held t_lag in a FIFO. Not monotonic: 60 ms fell fastest, 250 ms lasted longest, and from 180 ms up the body went backwards. Last row: a real actuator with a 30 ms command gap, which holds the last torque or drops to zero. One motor on the bench and a scope on the current measure it.

Where it broke

The distance model was not a bad estimate. It was the wrong model. It describes a foot that lands. The first swing starts at 1 s of quiet standing (gait.py start_time), and the 30 to 120 ms rows fell at 0.68 to 0.86 s, before any foot left the ground. The 180 and 250 ms rows fell at 1.04 and 1.35 s, inside the first swing. Staleness costs phase in the long before it costs centimetres on the ground.

The second result is that fall time did not decrease with lag. 60 ms fell fastest (0.68 s) and 250 ms stayed up longest (1.35 s). My interpretation is that at 60 ms the held torque is near antiphase with the sway and increases the wobble. At 250 ms the torque is so stale that it acts as a constant push, and the body tips slowly instead. If 60 ms is the antiphase point, the sway is near 1 / (2 x 0.060) = 8 Hz.

I wrote a centimetre table before I ran anything. The sweep answered the question that I skipped. The delay is inside the balance loop, and that chooses the model before the units do.

This controller has less than 30 ms of delay margin. The pendulum has a clock of approximately 290 ms. This is a controller with a small margin, not difficult physics. The is not the cause of a margin that the inner loop never had.

Summary

  • The architecture question is not "how fast can the VLA run". It is "what is the oldest command that my balance loop can tolerate". For this controller, the answer is under 30 ms, and 30 ms was the smallest lag that I tried. A VLA cannot be in that loop.
  • Cache, chunk and gate: each trick that buys Hertz for the VLA keeps it out of the torque path. In this sim, a chunked action in the torque path costs balance, not centimetres.
  • The A/B compares the every-frame controller with the same controller fed stale torque. The failure is a fall during standing for four of the six lags, and a fall in the first swing for 180 and 250 ms. The trick to test next is not on the VLA side. It is a faster inner loop.

Sources

These sources are not mine. Measured numbers came off my own board; specs, estimates and paper figures are labeled as such.

  • NanoVLA (late fusion, chunking, routing)
  • Jetson-PI (async inference, perception-execution misalignment)
  • C-VLA hierarchical gate
  • LiteVLA-Edge latency class