humanoid-loco: Unitree G1 locomotion with reinforcement learning

Velocity-commanded walking trained with PPO and domain randomization in MuJoCo Playground (MJX), exported to ONNX and tested sim-to-sim in plain CPU MuJoCo on 500 seeded episodes per condition.

NVIDIA L4, simulation, no real robotsim-to-sim, not sim-to-realevery number from results/*.json

Code on GitHubFull results

0 / 500falls in plain CPU MuJoCo, nominal (20 s episodes)
42 vs 97falls with a 1-step action delay: DR vs no DR at the same training steps
130.7M stepstraining in 108 minutes on one NVIDIA L4
0.154 m/smean velocity-tracking error, nominal

Videos

PPO + domain randomization, plain CPU MuJoCo
The ONNX policy running in a different simulator from the one it was trained in (sim-to-sim).
PPO + domain randomization, MJX
Same policy in the training simulator, same scripted velocity commands.
Ablation: PPO without domain randomization, plain CPU MuJoCo
Also walks in the nominal case; the difference shows up under latency and low friction (table below).
Failed run: RSL-RL PPO, 72 minute budget
Did not learn to stand within its budget. Kept on purpose: failures are part of the result.
Isaac Lab: RSL-RL PPO, Isaac-Velocity-Flat-G1-v0, in Isaac Sim (PhysX)
147.5M env steps in 48 minutes on one NVIDIA L4. Constant command 0.8 m/s forward; the camera follows one robot (Isaac Lab G1, 37 joints). Trained and shown in the same simulator: this is not a transfer test.
Isaac Lab: RSL-RL PPO, Isaac-Velocity-Rough-G1-v0 (rough terrain, height scan)
266.4M env steps in 110 minutes (stopped at wall-clock cap, 2710 of 3000 iterations). Within Isaac Sim, nominal: 4/500 falls on the task's own terrain mix.
Side by side: CPU MuJoCo (left) and Isaac Sim (right)
Left: brax PPO + DR policy on the Menagerie G1 in plain CPU MuJoCo. Right: Isaac Lab RSL-RL policy on the Isaac Lab G1 in Isaac Sim. Different policies, robot models, commands and simulators; a visual impression, not a matched comparison.

Falls in plain CPU MuJoCo (out of 500 episodes, 20 s each)

conditionPPO + DR (final)PPO + DR (step-matched)PPO, no DRRSL-RL PPO + DR
nominal0/5000.0%4/5000.8%3/5000.6%500/500100.0%
floor friction x0.526/5005.2%19/5003.8%43/5008.6%500/500100.0%
floor friction x1.50/5000.0%3/5000.6%3/5000.6%500/500100.0%
torso mass +3 kg2/5000.4%3/5000.6%5/5001.0%500/500100.0%
torso mass -3 kg1/5000.2%1/5000.2%1/5000.2%500/500100.0%
random pushes (harsher than training)338/50067.6%440/50088.0%435/50087.0%500/500100.0%
1-step action delay9/5001.8%42/5008.4%97/50019.4%500/500100.0%
2-step action delay491/50098.2%500/500100.0%500/500100.0%500/500100.0%
sensor noise (training level)0/5000.0%4/5000.8%5/5001.0%500/500100.0%
more accurate solver0/5000.0%2/5000.4%2/5000.4%500/500100.0%

Same seeds (start state, velocity command, pushes) for every policy. Wilson 95% intervals are in the full results.

Does domain randomization help? Paired comparison at the same training steps

conditionfalls, PPO + DRfalls, PPO no DRexact McNemar p
nominal431
floor friction x0.519430.00072
floor friction x1.5331
torso mass +3 kg350.69
torso mass -3 kg111
random pushes (harsher than training)4404350.65
1-step action delay42971.3e-07
2-step action delay5005001
sensor noise (training level)451
more accurate solver221

Highlighted rows: p < 0.01. One training seed per policy, so this speaks to these two checkpoints, not to domain randomization in general.

Isaac Lab track: same task idea, Isaac Sim + RSL-RL

Isaac Sim 4.5.0.0 and Isaac Lab v2.1.1 installed on this host; Isaac-Velocity-Flat-G1-v0 trained with RSL-RL PPO, 4096 parallel envs, 1500 iterations, 147,456,000 env steps, 48 minutes, final mean training episode length 1000 of 1000 steps.

Evaluation within Isaac Sim (PhysX), not sim-to-sim; 500 episodes of 20 s per condition. Different robot model, fall definition and command ranges than the MuJoCo table above, so compare within this table only.

conditionflat policy: falls (Wilson 95%)rough-terrain policy (terrain mix)
nominal0/5000.0% [0.0%, 0.8%]
lin-vel err 0.121 m/s
4/5000.8% [0.3%, 2.0%]
lin-vel err 0.108 m/s
robot contact friction x0.50/5000.0% [0.0%, 0.8%]
lin-vel err 0.116 m/s
9/5001.8% [0.9%, 3.4%]
lin-vel err 0.112 m/s
robot contact friction x1.50/5000.0% [0.0%, 0.8%]
lin-vel err 0.124 m/s
3/5000.6% [0.2%, 1.7%]
lin-vel err 0.108 m/s
torso mass +3 kg3/5000.6% [0.2%, 1.7%]
lin-vel err 0.151 m/s
8/5001.6% [0.8%, 3.1%]
lin-vel err 0.120 m/s
torso mass -3 kg0/5000.0% [0.0%, 0.8%]
lin-vel err 0.102 m/s
4/5000.8% [0.3%, 2.0%]
lin-vel err 0.098 m/s
random pushes (none in training)395/50079.0% [75.2%, 82.3%]
lin-vel err 0.326 m/s
269/50053.8% [49.4%, 58.1%]
lin-vel err 0.299 m/s
1-step action delay123/50024.6% [21.0%, 28.6%]
lin-vel err 0.288 m/s
50/50010.0% [7.7%, 12.9%]
lin-vel err 0.163 m/s
2-step action delay477/50095.4% [93.2%, 96.9%]
lin-vel err 0.844 m/s
432/50086.4% [83.1%, 89.1%]
lin-vel err 0.660 m/s
sensor noise (training level)0/5000.0% [0.0%, 0.8%]
lin-vel err 0.119 m/s
6/5001.2% [0.6%, 2.6%]
lin-vel err 0.109 m/s

Isaac to MuJoCo sim-to-sim was not attempted: the Isaac Lab G1 has 37 action joints (with hands), the Menagerie G1 used above has 29 actuators, and only 18 joint names match, so no exact joint and observation mapping exists.

How it was built

Limits

Pavan Yadav Annappa. Model: Unitree G1 from MuJoCo Menagerie (BSD-3-Clause). Code: MIT.