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.
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.
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:
- — the remaining distance to the target after control steps.
- — the starting distance to the target.
- — the friction factor: the fraction of commanded motion the actuator actually delivers ( is the sim's assumption).
- — the controller's proportional gain.
- — the fixed number of control steps before checking success.
- Sim assumes f = 1
A gain tuned so that is small enough to converge within steps in sim is really only tuned for — it has no reason to also work for a smaller .
- Domain randomization means tuning against a range of f, not one value
Training against produces a controller that's brittle to exactly one number. Training against many sampled values (0.6, 0.8, 1.0, ...) produces a gain that keeps small across the whole range — the real robot's actual just needs to be somewhere in that trained range.
Identical gain, identical target, identical step budget — only the friction changed, and that alone flips the outcome from success to failure.
- Sim: f=1, K=0.5, four steps
— comfortably inside the 0.5 tolerance.
- Real: same gain, f=0.6
— the exact same controller, the exact same math, now fails the tolerance.
- Compensating for the known friction closes the gap
Solving for : divide both sides by 4 to get ; take the fourth root, ; so , giving . Any gain past roughly 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.
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
The reality gap here isn't a bug in the physics engine — it's the simulator's clean assumption () simply not matching a real actuator's honest () delivery. High-throughput GPU physics engines make it cheap to train against thousands of randomized 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.