← All work

Bracing for a hit

If you warn a walking robot that a shove is coming, does it stay on its feet? Two simulated robot dogs, identical but for a four-number warning, shoved about 148,000 times.

5× fewer falls at 250 N Unitree Go1 · MuJoCo mjlab · PPO 148k measured shoves Simulation only

Same shove, three robots

All three at 250 N, roughly 1.8× the robot's own weight. The overlay uses the code's names for them: anticipatory, reactive, anticipatory (blind). These are independent rollouts, not the same shoves replayed, so read them as an illustration rather than the measurement.

What I did

I trained two robots to walk while something shoved their body from a random direction every three to six seconds. The only difference between them: one saw a warning shortly before each shove — which direction it was coming from, how hard, and how long until it landed — and the other had to deal with the shove after it arrived. Then I froze both and shoved them at seven fixed strengths, 1024 robots in parallel, and counted the falls.

The warning only matters once the shove is hard

Up to 160 N the two robots are the same: 0.9% and 0.8% falls, a tie. Reacting after the shove lands is fast enough at that strength — the robot thinks 50 times a second. The gap only opens at 200 N and becomes large at 250 N.

That is the part worth knowing, because the obvious experiment misses it. Had I only tested up to 160 N, the honest conclusion would have been "warning the robot does nothing."

Line chart of falls per shove against shove strength for three robots. Warned and not-warned track each other near zero until 160 N, then separate: at 250 N the warned robot falls 1.2% of the time and the unwarned one 6.1%. The warning-switched-off line climbs steeply from 120 N to 52.3% at 250 N.
Falls per shove, by shove strength. Bars are 95% Wilson intervals — replotted from the study's own eval tables in the site's palette.

Falls per shove

ShoveWarnedNot warnedWarning off
35 N0.0%0.0%0.0%
60 N0.0%0.1%0.0%
90 N0.1%0.5%0.6%
120 N0.5%0.4%2.3%
160 N0.9%0.8%10.4%
200 N0.7%1.7%27.8%
250 N1.2% [1.0, 1.5]6.1% [5.5, 6.6]52.3% [51.4, 53.2]

Between 6,692 and 11,188 shoves per cell. Ranges are 95% confidence intervals.

How far the body tipped

ShoveWarnedNot warnedWarning off
35 N4.9°5.6°5.5°
120 N13.0°15.9°21.2°
250 N16.5°29.2°54.2°

Mean peak trunk tilt. Past 70° counts as a fall. The warned robot tips about as far under the hardest shove as the unwarned one does under a medium one.

The warning became a crutch

This is the part I did not see coming. I took the trained warned robot and fed it zeros where the warning normally goes — nothing else changed. It went from falling 1.2% of the time to 52.3%.

That is not a fall back to normal. The robot that never had a warning falls 6.1% of the time, so removing the warning left this one about nine times worse than never having had one. It learned "brace when told" instead of the more general skill of recovering from a shove.

This is the third clip from the top of the page. The arrow is still drawn for you; the robot can no longer see it. If a real robot's warning came from a camera or a sensor that failed, this is what you would get — and making it cope without the warning is a separate job you do not get for free.

A ball, so you can see it

Every number above comes from a force applied directly to the robot's body, because that gives an exact strength to put on the chart. The trouble is that "a force was applied to the body" is not something you can watch.

So here is the same trained robot, unchanged, with a real 5 kg ball thrown at it instead. No measurement comes from these clips. About one throw in three misses — the ball is aimed where the robot is going to be, and the warned robot slows down when it sees the throw coming.

How it works

  • The robot walks on flat ground following speed commands. Every three to six seconds a force hits its body from a random direction, slightly above its centre, so it tips rather than just slides.
  • A curriculum moves each robot up or down a difficulty ladder — harder for anything that survives, gentler for anything that falls — so all 4096 robots training in parallel sit near their own limit.
  • The warning is four numbers: two for direction, one for strength, one for time until it lands. All four are zero when nothing is coming. Deleting those four numbers from what the robot senses, and nothing else, is the entire difference between the two robots.
  • The value estimator sees the warning during training for both robots; only the part that chooses actions differs. Otherwise the unwarned robot would be handicapped twice, and the comparison would measure the wrong thing.
  • 4000 training rounds each, 393 million simulated steps per robot, about 2.4 hours on a T4. Evaluation runs 1024 robots in parallel at seven fixed strengths.

What this does not prove

  • Each robot was trained once. The confidence intervals cover the testing, not the training. The crutch result is safe from this — it compares one robot against itself — but the headline warned-vs-unwarned comparison is not. Three to five seeds each is the first thing this needs.
  • The ceiling was too low. Both robots hit my 250 N cap and stayed there, so the shoves stopped getting harder before the robots stopped improving. I picked that cap by working out how hard you would have to shove a 13.93 kg object floating in space, and forgot that four legs on the ground soak up a lot of the blow.
  • It is all simulation, and the warning is perfect — exactly the right direction, strength and timing, every time. A real one would be noisy and sometimes wrong. Given how badly this robot does when the warning disappears, how it copes with a wrong warning is an open and fairly important question.

What is mine and what is not

The robot model, the walking task, the training algorithm and the reward functions all come from mjlab. I wrote about 450 lines on top of it: the threat command that picks a shove, counts down to it, tells the robot what is coming and applies the force; the difficulty curriculum; and the two environment configs, which differ by one line.

I wrote no reward functions — mjlab already has the ones this task needs, and adding my own would have introduced differences that had nothing to do with the question. I did remove mjlab's built-in random push, which is an instant velocity change that ignores mass and cannot be aimed, scaled or announced; leaving it in would have added a second kind of shove neither robot could ever be warned about.

Links

Code on GitHub — the write-up, the ~148,000-row eval tables, and the tests that check the two setups differ by exactly one thing.

Release — both trained policies, every training checkpoint, and all 40 clips: each robot at each shove strength, learning from scratch, and the ball throws.