A ROS2 + Gazebo + MuJoCo workspace for simulating and walking quadruped robots, with three interchangeable locomotion backends (RL, CHAMP, Quad-SDK NMPC) and an RL training pipeline on top.
What's working:
- RL locomotion — PPO trained end-to-end in MuJoCo (no hand-written gait/IK). Also: blind-vs-sighted rough-terrain comparison, fall recovery, asymmetric critic + staged curriculum, HL navigation. See RL Policy Training.
- Quad-SDK NMPC — a real Unitree Go2 config stands up, plans a path, solves NMPC in real time (~20-30ms/solve), and walks to a goal at ~0.7 m/s. See Quad-SDK (NMPC locomotion).
- CHAMP — kinematic gait engine, quick dependency-light walking (generic reference robot; not wired to Go2's physics, see note below).
- Stairs & ledges, indoor autonomy (3D SLAM), arena/warehouse/moving-obstacle worlds — one-command Gazebo demos.
- Go2 model weights — local SB3
.zipcheckpoints (resumable) + downloadable Isaac/rsl_rl/Genesis.ptfiles. See docs/PRETRAINED.md. - 14 research PDFs under docs/papers/.
Go2 is the only fully working robot (real URDF/meshes, both locomotion backends). The other urdf/*_config/ folders are CHAMP config stubs carried over from upstream examples — they reference external ROS1 *_description packages that aren't vendored here, so they don't spawn as-is.
- Repository Structure
- Setup
- Quick Start
- Locomotion Backends
- RL Policy Training
- Model Policies
- SLAM & Autonomy
- Other Controllers & Tools
- Available Robots
- Manipulator Arm
- Intelligence Modules
- Roadmap
- Additional Docs
- References
quadruped-robotics-stack/
├── urdf/go2_unitree/ # Unitree Go2 URDF + meshes — fully working
├── ros2/ # CHAMP + Quad-SDK ROS2 packages
├── launch/ # Top-level launch files (champ_go2_gazebo, stairs, indoor autonomy, slam3d, nav2, ...)
├── scripts/ # Train/play/setup helper scripts
├── training/
│ ├── envs/ # Gazebo SDF + MuJoCo XML worlds/scenes
│ ├── terrain/ # Terrain generators
│ ├── pretrained/ # Downloaded .pt weights (gitignored)
│ └── logs/mujoco/ # Local SB3 checkpoints
├── intelligence/ # Gait, perception, navigation, LLM commander
└── docs/ # DEMOS, PRETRAINED, BENCHMARKS, TROUBLESHOOTING, CHANGELOG, papers/
- Ubuntu 22.04, ROS2 Humble, Gazebo Harmonic (gz-sim8) via
ros_gz_sim, Python 3.8+ - NVIDIA GPU with 10GB+ VRAM for RL training
cd ros2
source /opt/ros/humble/setup.bash
colcon build --symlink-install --cmake-args -DBUILD_TESTING=OFF
source install/setup.bashView Go2 in RViz2:
ros2 launch launch/view_go2.launch.pySpawn Go2 in Gazebo Harmonic + drive with /cmd_vel:
ros2 launch launch/gazebo_go2.launch.py
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.3}, angular: {z: 0.2}}" --rate 10Or keyboard teleop: ros2 launch champ_teleop teleop.launch.py.
Train and run an RL policy (MuJoCo):
pip install -r requirements.txt
./scripts/train_policy.sh mujoco --timesteps 2000000
python3 training/play_policy.py --model training/logs/mujoco/go2_mujoco_final.zip --cmd 0.5 0 0See RL Policy Training for details.
Stairs & ledges (CHAMP walk):
ros2 launch launch/stairs_ledges_go2.launch.py course:=stairs # or course:=ledgesIndoor autonomy (room + 3D SLAM):
ros2 launch launch/indoor_autonomy_go2.launch.pyFull checklist: docs/DEMOS.md.
| Backend | Approach | Status |
|---|---|---|
Native gz-sim (training/launch/gazebo_rl.launch.py) |
RL policy or IK trot, direct JointPositionController |
Working |
CHAMP (ros2/champ_config) |
Kinematic gait engine | Wired for CHAMP's generic reference robot only, not Go2 — champ_gazebo needs Gazebo Classic, this repo runs Gazebo Harmonic |
Quad-SDK (ros2/quad_sdk) |
NMPC + global/local planner | Walking — verified end-to-end |
Quad-SDK is vendored in ros2/quad_sdk/, with RBDL/IPOPT built locally into ros2/quad_sdk_external/. Full porting history and terrain test results: docs/quadsdk_notes.md.
One-time setup:
./scripts/setup_quadsdk_apt_deps.sh # 1. system packages, needs sudo — run yourself
./scripts/build_quadsdk_local_libs.sh # 2. RBDL + IPOPT, no sudo
cd ros2 && colcon build --symlink-install && source install/setup.bash && cd .. # 3. build workspaceEasiest way to try it:
./scripts/walk_quadsdk_go2.sh # flat ground, goal (5, 0)
./scripts/walk_quadsdk_go2.sh 8.0 0.0 gui # custom goal, Gazebo GUI visible
./scripts/walk_quadsdk_go2.sh 5.0 0.0 gui step_20cm.sdf # over a terrain worldOr manually:
./scripts/launch_quadsdk_go2.sh step_20cm.sdf # Terminal 1 — Gazebo + Go2
source ros2/install/setup.bash && source ros2/quad_sdk_external/setup_env.sh
ros2 launch quad_utils quad_plan.py # Terminal 2 — planner + NMPCThree backends via one helper script: ./scripts/train_policy.sh [backend] [options]
Domain randomization, curriculum learning, foot-contact obs, 8-term reward, VecNormalize, TensorBoard logging.
pip install -r requirements.txt
./scripts/train_policy.sh mujoco # default 2M steps, 8 envs
./scripts/train_policy.sh mujoco --timesteps 5000000 --n_envs 16 --cmd 1.0 0.0 0.0
./scripts/train_policy.sh mujoco --resume training/logs/mujoco/checkpoints/go2_mujoco_500000_steps.zipUse the matching vecnorm_<steps>_steps.pkl when resuming — stale normalization stats can make a good checkpoint look broken. Output: training/logs/mujoco/. View curves: tensorboard --logdir training/logs/mujoco.
Regenerate after any new run: python3 scripts/plot_eval_comparison.py. Notable: flat walk (gated reward) climbs to ~2300 by 3.6M steps then collapses — a reach-reward exploit, see CHANGELOG.
training/train_vision_compare.py trains blind (49-dim proprio) and sighted (67-dim, +18-point height-scan) policies on the same procedurally randomized terrain/obstacle curriculum:
python3 training/train_vision_compare.py --timesteps 1000000 --n_envs 8 --cmd 0.4 0.0 0.0Output: training/logs/vision_compare/{blind,sighted}/ + a comparison plot. Env is smoke-tested, not yet a full trained-and-evaluated comparison.
Separate get-up policy trained from random fallen poses (ported from FR-Net):
python3 training/train_recovery.py --timesteps 1000000 --n_envs 8
python3 training/play_recovery.py --model training/logs/recovery/best_model.zipCompose with the walk policy: python3 training/play_composed.py --walk training/logs/mujoco/best_model.zip --recovery training/logs/recovery/best_model.zip.
python3 training/train_mujoco.py --asymmetric --obs-history 5
python3 training/train_curriculum.py --asymmetric --obs-history 5 --gait # flat -> rough -> stairs
python3 training/train_hl_nav.py --walk-model training/logs/mujoco/best_model.zip --timesteps 200000ros2 launch launch/arena_go2.launch.py
ros2 launch launch/warehouse_go2.launch.py
ros2 launch launch/moving_obstacle_go2.launch.pyFuel downloads: python3 scripts/download_worlds.py — see training/envs/worlds/README.md.
Real Gazebo Harmonic physics via ROS2 topics (JointPositionController + ros_gz_bridge).
./scripts/train_policy.sh gazebo # auto-launches Gazebo headlessly
ros2 launch training/launch/gazebo_rl.launch.py headless:=true # or launch standaloneForward walking via
/cmd_velhad a reward bug (fixed, retrain needed) — see CHANGELOG.
Multi-terrain world (ramps/stairs/rough patch/obstacles): ros2 launch training/launch/gazebo_rl.launch.py world:="$(pwd)/training/envs/go2_multi_terrain.sdf".
ros2 launch launch/stairs_ledges_go2.launch.py course:=stairs # easy 6cm -> mid 8cm -> hard 12cm + descent
ros2 launch launch/stairs_ledges_go2.launch.py course:=ledges # platforms, gaps, hollow stairs, curb
./scripts/train_stairs.sh # sighted height-scan
./scripts/train_stairs.sh --blind # proprioception onlyDetails: training/terrain/README.md. Regenerate worlds with python3 scripts/generate_stairs_ledges.py.
pip install -e training/
./scripts/train_policy.sh isaac go2 --headlessRegistered tasks: go2, h1, h1_2, g1.
| Kind | Location | Use |
|---|---|---|
| SB3 MuJoCo walk | training/logs/mujoco/*.zip + vecnorm_*.pkl |
training/play_policy.py, resume with train_mujoco.py --resume |
| SB3 blind stairs | training/logs/stairs/*.zip |
./scripts/train_stairs.sh --blind --init-from-flat |
Isaac locomotion .pt |
training/pretrained/go2_locomotion/ |
Use with Go2_Isaac_ros2 |
Parkour .pt |
training/pretrained/go2_parkour/ |
Use with parkour-drl stack |
| Classical stairs/ledges | CHAMP / Quad-SDK | launch/stairs_ledges_go2.launch.py, walk_quadsdk_go2.sh |
python3 scripts/download_pretrained.py # fetch/refresh .pt files (gitignored)
python3 training/play_policy.py --model training/logs/mujoco/best_model.zip --cmd 0.5 0 0Full table and known-issue notes (including the arm's reach reward never having trained — fixed, not yet retrained): docs/PRETRAINED.md, CHANGELOG.
Play a checkpoint (OpenCV viewer):
python3 training/play_policy.py --model best_model.zip --record policy_demo.mp4| Key | Action |
|---|---|
| R | Reset episode |
| ESC | Quit |
Keyboard teleop with a trained policy: python3 training/teleop_mujoco.py --model training/logs/mujoco/best_model.zip (W/S forward-back, A/D strafe, Q/E yaw).
Headless IK controller (no RL) — pure IK trot/walk/bound, gait auto-switches with speed:
python3 training/headless_control.pyDeploy in MuJoCo: deploy_mujoco.py only supports H1/H1_2/G1 legged_gym-style JIT .pt policies, not Go2's SB3 checkpoints — use play_policy.py for Go2 instead.
2D SLAM (SLAM Toolbox):
python3 scripts/gz_pose_to_odom.py # bridges Gazebo pose -> /odom + TF
ros2 launch launch/slam_go2.launch.py # subscribes /scan, publishes /map3D LiDAR SLAM + frontier exploration (RTAB-Map):
ros2 launch launch/slam3d_go2.launch.py headless:=true explore:=truescripts/frontier_explorer_go2.py grows a real occupancy grid and walks the robot toward frontier cells. track_obstacles:=true adds Kalman-tracked obstacle clustering. locomotion:=nmpc swaps CHAMP for the Quad-SDK backend (same lidar/RTAB-Map setup, also verified end-to-end).
Nav2 against the CHAMP map/config: ros2 launch launch/nav2_go2.launch.py.
- CHAMP simulation:
ros2 launch ros2/champ_config/launch/gazebo.launch.py+ros2 launch champ_teleop teleop.launch.py(see backends note — doesn't fully launch end-to-end on this repo's Gazebo Harmonic setup). - Intelligence modules: gait scheduling, terrain estimation, waypoint nav, LLM commander — see Intelligence Modules.
| Robot | Status |
|---|---|
| Unitree Go2 | Working — real URDF/meshes, NMPC + RL both drive it |
| Unitree H1 / H1_2 / G1 | legged_gym task only, no URDF vendored here |
| Spot / Mini Cheetah / ANYmal B / ANYmal C / Mini Pupper / Go1 | Stub — CHAMP config only, references an unvendored ROS1 *_description package |
Only Go2 actually spawns and walks; don't expect the stub rows to work as-is.
Go2 can carry a 5-DOF arm (no gripper) mounted on the body — CHAMP's stock demo arm, reworked into a reusable xacro macro and mounted on Go2's base link.
ros2 launch training/launch/gazebo_rl.launch.py headless:=falseDriven via ros2_control (arm_position_controller). Not yet done: not wired into the RL training envs, NMPC, or CHAMP's gait engine — visual/kinematic attachment only, holding a fixed pose.
Higher-level autonomy stack on top of the base sim + RL policy:
intelligence/
├── locomotion_manager.py # fuses all modules into one running ROS2 node
├── gait/gait_scheduler.py # auto-select gait by speed
├── perception/terrain_estimator.py # classify terrain from IMU + foot forces
├── navigation/waypoint_navigator.py # pure-pursuit waypoint following
├── terrain/adaptive_controller.py # terrain + gait -> safe velocity command
└── llm_commander/llm_commander.py # natural language -> robot commands via Claude API
Run the full stack:
python3 intelligence/locomotion_manager.py # Terminal 1
python3 intelligence/navigation/waypoint_navigator.py --ros-args \
-p waypoints:="[2.0,0.0, 2.0,2.0, 0.0,0.0]" -r /cmd_vel:=/cmd_vel_raw # Terminal 2LocomotionManager publishes safe adapted /cmd_vel + JSON /locomotion_status. LLM control: export ANTHROPIC_API_KEY=... then python3 intelligence/llm_commander/llm_commander.py, then publish to /natural_language_cmd.
FixFixed.global_body_planner_nodesegfault on hard terrain.Retrain MuJoCo RL policy against reward-hack fix.Retrained, partially verified — real forward velocity, but episodes still end early (~1.5-2s falls).FixFixed, verified in sim — headless/cmd_velwalking on the native Gazebo backend.training/launch/gazebo_rl.launch.pyresponds to/cmd_vel(forward + turn) with visible motion; actual speed tracks well below commanded (~25% of 0.25 m/s over a short window), likely needs gait tuning.Evaluate multi-terrain RL pipeline.Evaluated — no meaningful blind/sighted gap found.- Wire the manipulator arm into something that does work — currently decorative only.
Fall-recovery env + arm-in-MuJoCo-RL + Gazebo reward fix.Done, need more training/verification.
Full postmortems: docs/CHANGELOG.md.
| Doc | Contents |
|---|---|
| DEMOS.md | Indoor autonomy, stairs/ledges, stack checker, rosbag, Gazebo RL eval |
| PRETRAINED.md | Model names, local paths, usage notes |
| papers/README.md | 14 local PDFs — stairs, parkour, recovery, adaptation |
| BENCHMARKS.md | RL / autonomy / backend comparison tables |
| TROUBLESHOOTING.md | SLAM, obstacle tracking, Gazebo RL, RViz checks |
| PROJECT_GROWTH_PLAN.md | Feature and structure checklist |
| quadsdk_notes.md | Quad-SDK porting history + terrain test results |
| CHANGELOG.md | Full bug postmortems / root-cause writeups |
| training/terrain/README.md | Stair/ledge generators + Unitree terrain_tool |
- CHAMP Framework — ROS2 locomotion controller
- Unitree RL Gym — PPO policy training
- legged_gym (ETH Zurich) — original RL gym
- Isaac Lab — modern GPU training framework
- docs/papers — StairMaster, blind stairs, parkour, LEEPS, SoloParkour, RMA, FR-Net, DreamRiser
- IsaacLab-Quadruped-Tasks — Go2 stairs RL tasks
- Robot Parkour Learning — gaps / climb / crawl
- Extreme Parkour — fast parkour training
- HF Go2 parkour checkpoints — RPL / visual distill weights





