Part XX — Embodied AI & Production Systems: VLA Robotics, High-Throughput Serving & MLOps · Chapter 3

Sim-to-real transfer & physics engines (MuJoCo / Isaac)

Hook

A policy trained entirely in a physics engine like MuJoCo or Isaac Gym never has to fight friction it didn't expect, backlash in a gearbox, or a battery that delivers a little less torque than the spec sheet promised. The real robot does. That mismatch is the reality gap, and it doesn't need a full physics simulator to demonstrate — a controller that assumes it's getting 100% of its commanded motion, meeting an actuator that only delivers 60%, shows the exact same failure mode.

Intuition

After 4 control steps: position 3.750, target 4, error 0.250

Success — within 0.5 of the target

Same gain, same target, same number of control steps. In sim the arrow lands on the target dot. In "real," with the actuator delivering less motion per command than assumed, the same gain undershoots — not because anything is broken, just because the model the controller was tuned against wasn't quite right.

Formalize

A proportional controller commands motion equal to gain times error, but the actuator only delivers a fraction of what's commanded. That turns the position error into a geometric sequence:

eT=e01fKTe_T = e_0 \,\bigl|1 - f\,K\bigr|^{\,T}
  • eTe_T — the remaining distance to the target after TT control steps.
  • e0e_0 — the starting distance to the target.
  • ff — the friction factor: the fraction of commanded motion the actuator actually delivers (f=1f=1 is the sim's assumption).
  • KK — the controller's proportional gain.
  • TT — the fixed number of control steps before checking success.
  1. Sim assumes f = 1

    A gain tuned so that 1K|1-K| is small enough to converge within TT steps in sim is really only tuned for f=1f=1 — it has no reason to also work for a smaller ff.

  2. Domain randomization means tuning against a range of f, not one value

    Training against f=1f=1 produces a controller that's brittle to exactly one number. Training against many sampled ff values (0.6, 0.8, 1.0, ...) produces a gain that keeps eTe_T small across the whole range — the real robot's actual ff just needs to be somewhere in that trained range.

Play
environmentfinal positionerrorresult
sim3.75000.2500success
real3.03960.9604failure

Identical gain, identical target, identical step budget — only the friction changed, and that alone flips the outcome from success to failure.

Worked example
  1. Sim: f=1, K=0.5, four steps

    e4=411(0.5)4=40.54=4(0.0625)=0.25e_4 = 4 \cdot |1 - 1(0.5)|^4 = 4 \cdot 0.5^4 = 4(0.0625) = 0.25 — comfortably inside the 0.5 tolerance.

  2. Real: same gain, f=0.6

    e4=410.6(0.5)4=40.74=4(0.2401)=0.9604e_4 = 4 \cdot |1 - 0.6(0.5)|^4 = 4 \cdot 0.7^4 = 4(0.2401) = 0.9604 — the exact same controller, the exact same math, now fails the tolerance.

  3. Compensating for the known friction closes the gap

    Solving 410.6K40.54|1-0.6K|^4 \le 0.5 for KK: divide both sides by 4 to get 10.6K40.125|1-0.6K|^4 \le 0.125; take the fourth root, 10.6K0.1251/40.595|1-0.6K| \le 0.125^{1/4} \approx 0.595; so 10.6K0.5951-0.6K \le 0.595, giving K(10.595)/0.60.676K \ge (1-0.595)/0.6 \approx 0.676. Any gain past roughly K0.68K \approx 0.68 brings the real robot back under tolerance in the same four steps — the controller doesn't need a better simulator, it needs a gain that assumes less friction than sim did.

Checkpoint

The gain 0.5 was tuned in sim and fails on the real robot (friction 0.6). Find a gain that still reaches the target within tolerance, under real friction, in the same 4 steps.

After 4 control steps: position 3.040, target 4, error 0.960

Failure — outside 0.5 of the target

Move the slider to try it
Summary
eT=e01fKTe_T = e_0 \,\bigl|1 - f\,K\bigr|^{\,T}

The reality gap here isn't a bug in the physics engine — it's the simulator's clean assumption (f=1f=1) simply not matching a real actuator's honest (f<1f<1) delivery. High-throughput GPU physics engines make it cheap to train against thousands of randomized ff values instead of one, which is exactly what domain randomization buys: a policy whose gain was never allowed to overfit to a friction that only existed in simulation. The next chapters turn away from robotics and toward the infrastructure that serves any trained model at scale, starting with the memory hierarchy every GPU kernel has to respect.