ΒΆPaper Feed

Issue 25 Β· Project 01 GitHub Robotics βœ“ read

kingjulio8238/nanoG1

nanoG1 - G1 walking policy trained in < 60s

TL;DR: nanoG1 trains a Unitree G1 humanoid to walk from scratch β€” pure PPO, no demos, no reference motion β€” in ~59 seconds of wall-clock on a single GPU, for about $0.17. The trick is not a new RL algorithm but a robot-specialized physics engine: MuJoCo-semantics simulation compiled per-robot into straight-line CUDA, hitting 7.25M physics steps/s (claimed 1.8Γ— mujoco_warp at matched solver settings). It's a nanoGPT-style artifact β€” small, readable, one-command reproducible β€” and it ships the full stack down to real-hardware deployment scripts.

What it is and why it matters

The standing assumption in humanoid RL is that time-to-walk is measured in hours (or GPU-days), and that MuJoCo-fidelity contact is the bottleneck. nanoG1's thesis is that MuJoCo isn't slow, it's just general: for a fixed robot, the kinematic tree, contact set, and solver layout are compile-time constants, so the entire physics step can inline into dispatch-free CUDA with no broadphase and a fixed-iteration solver. Specialize the simulator to the G1 and you get 7.25M steps/s at mujoco_warp's exact solver settings, 8.5M at the lighter production config β€” which turns 75M PPO samples into a 59-second training run.

If the numbers hold up, this is an orders-of-magnitude cost collapse for locomotion RL, and it reframes where speed should come from: not cheaper physics (they claim trajectory-level validation against the MuJoCo C engine), but eliminating generality you don't need.

G1 physics throughput, RTX PRO 6000 (matched settings where applicable)physics steps/s (millions)012345677.25nanoG14mujoco_warp2.3Genesis*1.1MJXFrom the README. Genesis uses its own non-MuJoCo solver β€” not matched physics. nanoG1's own training config hits 8.5M.

How it works

The engine is a pinned PufferLib fork (the README is upfront that the core ideas β€” per-environment compile-time specialization, zero Python in the hot loop, the CUDA trainer, Muon optimizer β€” are PufferLib's). nanoG1 builds the G1 as a PufferLib environment with MuJoCo-grade soft-convex contact, friction cones, and domain randomization, then trains with PPO + V-trace at 1.28M samples/s end-to-end.

The single biggest learning lever, per the README, is a left↔right symmetry loss (after Yu et al. 2018): regularizing toward a mirror-symmetric gait cut samples-to-walk ~26% and smoothed the result. Everything tunable β€” reward weights, PPO/Muon hyperparameters, dt/decimation/solver β€” lives in one file, recipe.py.

G1-specialized engine tree/contacts/solver baked at compile time 7.25M physics steps/s PPO + V-trace + symmetry loss (βˆ’26%) 1.28M samples/s 75M samples β†’ 58.9 s Browser demo (WASM) 655 KB policy Real G1 via DDS 50 Hz, PD targets
The speed comes from the leftmost box: the simulator is compiled per-robot, so generality is traded for a ~2Γ— step-rate win over mujoco_warp β€” which compounds into a sub-minute training run.

What's actually there

  • Code: full training pipeline (speedrun.sh β†’ env, engine, train on Modal, quality gate), eval battery, and a reproducible benchmark suite with mujoco_warp/MJX/Genesis competitors (bench/). MIT licensed.
  • Weights: the trained 655 KB policy is committed at assets/nanoG1.bin, plus a model on Hugging Face.
  • Demos: a browser demo (raylib β†’ WASM, host physics) where you drive the trained G1.
  • Hardware deployment: deploy/ runs the policy on a physical G1 over Unitree's low-level DDS interface at 50 Hz, with a zero-torque β†’ home β†’ policy safety sequence and WASD teleop.
  • Evidence: 58.9 s / 75M samples on an RTX PRO 6000; benchmark numbers reproducible via modal run bench/bench_nanog1.py, with a RESULTS.md for exact settings and provenance.

Caveats

This is days-old (46 stars) and the honest gaps are visible. The engine is locked to the G1 β€” the whole point is per-robot compilation β€” so it's not a general fast-MuJoCo replacement without re-baking, and the fork is pinned rather than upstreamed. The task is flat-ground walking; nothing here about rough terrain, recovery, or manipulation. The real-robot section is deployment code, not a demonstrated result: the README says the policy is sim-trained and tells you to hang the robot from a gantry with E-stop in hand, which suggests sim-to-real is not a settled claim. Training requires a Modal account (only paid part, ~$0.17); there's no plain local-CUDA path documented. The Genesis comparison is fairly flagged as non-matched physics.

Still, as a legible reference implementation of specialized-simulation RL β€” and a demonstration that time-to-walk can be seconds, not hours β€” it's worth a read even if you never own a G1.

Try it

git clone https://github.com/kingjulio8238/nanoG1 && cd nanoG1
bash speedrun.sh          # needs uv + a Modal account; ~$0.17 GPU spend
# or validate cheaply first:
modal run train.py --smoke   # ~$0.02
python eval.py assets/nanoG1.bin
bash web/build_demo.sh && ./build/g1demo assets/nanoG1.bin

Or skip everything and drive the pre-trained policy in the browser demo linked from the README.