This repository implements a navigation-driven hybrid execution framework for the Unitree G1 humanoid robot. It builds upon the locomotion pipeline provided by rl_sar (Ziqi Fan) which offers a robust SIM–REAL reinforcement learning locomotion stack.
We extend and adapt this pipeline to integrate:
-
ROS 2 Nav2-based SLAM and global planning
-
Navigation-driven /cmd_vel control
-
MuJoCo–Gazebo pose synchronization
-
Structured deployment workflow for real robot execution
While rl_sar focuses on locomotion policy deployment, this project introduces a navigation-first architecture, where high-level planning and SLAM drive physics-grounded RL locomotion in a unified execution stack.
The same command interface (/cmd_vel) is preserved across all deployment levels:
Simulation (Gazebo + MuJoCo) ↓ Hardware-in-the-loop testing ↓ Real robot execution (Unitree G1 / G1 EDU23)
This enables consistent experimentation and reproducible evaluation from simulation to hardware.
The system is organized into four interacting layers:
1️⃣ Navigation Layer (ROS 2 Nav2 + SLAM)
-
Mapping via slam_toolbox
-
Localization
-
Global and local planning
-
/cmd_vel generation
Nav2 decides where the robot should move.
2️⃣ Locomotion Layer (MuJoCo + RL Policy)
-
Physics-grounded locomotion
-
29-DoF Robomimic-based RL controller
-
Joint remapping from policy space (29 DoF) to hardware space (23 active joints on EDU23)
The RL controller determines how the robot walks.
3️⃣ Hybrid Bridge Layer
A dedicated bridge ensures consistency between navigation and locomotion:
-
/cmd_vel filtering and saturation
-
Safety timeouts (freshness gating)
-
Gait parameter handling
-
Pose synchronization (MuJoCo → Gazebo)
-
Unified interface for simulation and real deployment
This layer guarantees that planning outputs are safely transformed into locomotion inputs.
4️⃣ Deployment Layer (SIM → REAL)
The framework supports multiple runtime modes:
-
Simulation (MuJoCo only)
-
Hybrid Gazebo + MuJoCo navigation
-
Fake LowState testing (safe debugging)
-
Real robot mode via Unitree SDK2
All modes share the same execution logic and command interface.
Core Design Principle
The architecture follows a strict separation of responsibilities:
-
Navigation decides where to go
-
RL locomotion decides how to walk
-
The bridge guarantees execution consistency
This modular structure enables:
Navigation-aware humanoid locomotion
Stable sim-to-real policy transfer
Controlled evaluation of SLAM + RL stacks
Reproducible experiments across simulation and hardware
In real deployment mode:
-
The RL locomotion controller runs on the hardware interface
-
Low-level state feedback (LowState) is streamed from the robot (DDS)
-
Nav2 (running on the PC) generates /cmd_vel
-
The bridge applies safety gating before publishing LowCmd
Safety mechanisms include:
-
Command freshness timeout
-
Motor enable sequence
-
Navigation-mode gating
-
Controlled activation of LowCmd publishing
This design ensures consistent behavior across simulation and real-world experiments while preserving hardware safety.
Beyond system integration, this project investigates how:
-
Execution reliability
-
Structured operational modes
-
Transparency in control flow
jointly influence trust in service robotics.
Rather than focusing solely on perception or reasoning modules, we emphasize the importance of a validated execution backbone that:
-
Reduces navigation instability
-
Improves motion predictability
-
Supports explainable operational modes
Enables systematic evaluation of safety and user trust
By unifying simulation, hardware-in-the-loop testing, and real robot deployment under a shared Nav2-based execution substrate, this framework enables principled research on navigation-driven humanoid robotics.
Recommended: Ubuntu 22.04 + ROS 2 Humble + Gazebo Classic (Gazebo 11)
- C++17 toolchain + CMake
- ROS 2 Humble
- Gazebo Classic +
gazebo_ros_pkgs - Nav2 + RViz2
yaml-cpp,TBB,glfw3- Python3 (dev headers)
- MuJoCo runtime library:**
libmujoco.so.3.2.7
This project supports multiple execution modes with a single binary (no rebuild), selected at runtime via ROS 2 parameters.
hw_mode:0=REAL(reads real robot LowState via DDS)1=FAKE_LOWSTATE(synthetic LowState, no robot required)
fake_rl_full(only meaningful whenhw_mode=1):false= mapping/cmd_vel checks only (no RL forward)true= full RL forward + logs (still safe ifpublish_lowcmd=false)
publish_lowcmd:true= publish LowCmd to the robot (movement possible)false= never publish LowCmd (safe dry-run)
Safety rule:
LowCmdis published only whenhw_mode=REALandpublish_lowcmd=true.
| Mode | LowState source | RL Forward | LowCmd computed | LowCmd published | Primary goal |
|---|---|---|---|---|---|
REAL + publish_lowcmd=true |
Real robot (DDS) | ✅ | ✅ | ✅ | Real robot operation (navigation → locomotion) |
REAL + publish_lowcmd=false |
Real robot (DDS) | ✅ | ✅ | ❌ | Safe debugging on robot (no motion output) |
FAKE_LOWSTATE + fake_rl_full=false |
Synthetic | ❌ | ❌ | ❌ | Validate joint mapping + /cmd_vel reception only |
FAKE_LOWSTATE + fake_rl_full=true + publish_lowcmd=false |
Synthetic | ✅ | ✅ | ❌ | Full RL pipeline + logs without robot (safe) |
sudo apt update
sudo apt install -y build-essential cmake git python3 python3-dev python3-pip libtbb-dev libyaml-cpp-dev libglfw3-dev pkg-config
# ROS2 + Nav2 + RViz
sudo apt install -y ros-humble-rclcpp ros-humble-geometry-msgs ros-humble-navigation2 ros-humble-nav2-bringup ros-humble-rviz2 ros-humble-tf2-ros ros-humble-tf2-tools ros-humble-robot-state-publisher ros-humble-joint-state-broadcaster ros-humble-std-srvs
# Gazebo Classic + ROS bridge
sudo apt install -y gazebo
sudo apt install -y ros-humble-gazebo-ros-pkgs ros-humble-gazebo-msgsThis repository expects MuJoCo under:
rl_hnav/src/rl_sar/library/mujoco/
include/mujoco/mujoco.h
lib/libmujoco.so.3.2.7
Check:
ls -lah rl_hnav/src/rl_sar/library/mujoco/lib/libmujoco.so.3.2.7If your repo provides a helper script:
bash rl_hnav/src/rl_sar/scripts/download_mujoco.shcd ~/
git clone https://github.com/uleroboticsgroup/rl_hnav.git
cd rl_hnav
git submodule update --init --recursivecd ~/rl_hnav
source /opt/ros/humble/setup.bash
colcon build
source install/setup.bashcd ~/rl_hnav
colcon build --cmake-args -DUSE_MUJOCO=ON -DENABLE_REAL_ROBOT=ON
source install/setup.bashCommand (as used in this project):
source /opt/ros/humble/setup.bash ###(zsh)
source rl_hnav/install/setup.bash ###(zsh)
ros2 run rl_sar rl_mujoco g1 scene_29dof --ros-args -p navigation_mode:=true -p cmd_vel_timeout_sec:=0.6 -p cmd_vel_topic:=/cmd_velnavigation_mode:=true: use/cmd_velas the command source.cmd_vel_timeout_sec:=0.6: safety stop if/cmd_velis missing.cmd_vel_topic:=/cmd_vel: Nav2 default output topic.
At startup, follow this sequence for safe, stable initialization:
- In RViz, click Pause immediately (or pause in the MuJoCo viewer if available).
- If needed, Reset to bring the robot back to a stable standing pose.
- Press
0to load the policy. - Press
1to execute GetUp. - Click Run/Play to start stepping and enable locomotion.
Open a new terminal, launch then bring up Nav2 + Gazebo that read (/odom) from MuJoCo pose to allow SLAM publishing the map.
source /opt/ros/humble/setup.bash ###(.zsh)
source rl_hnav/install/setup.bash ###(.zsh)
ros2 launch g1_nav2 nav_amcl.launch.pyAfter that:
- MuJoCo publishes odometry (
/odom) and TF (odom → base), - Nav2 publishes
/cmd_vel, - the bridge translates
/cmd_velinto locomotion inputs.
Typical workflow uses multiple terminals (2):
- MuJoCo locomotion (
rl_mujoco) - Gazebo + Bridge + SLAM + Nav2 (from the main pipeline)
- Gazebo Classic world + sensors
- slam_toolbox to create
/map - Nav2 to produce
/cmd_vel - Bridge to synchronize pose/state
source /opt/ros/humble/setup.bash ###(.zsh)
source rl_hnav/install/setup.bash ###(.zsh)
ros2 topic echo /cmd_vel
ros2 topic list | grep -E "/odom|/tf|/scan|/cmd_vel"Nav2 typically requires:
map → odom → base_footprint(orbase_linkdepending on your robot)
Recommended progression:
- cmd_vel only (log commands, no actuation)
- Fake LowState (validate mapping + policy plumbing without hardware)
- Real LowState, dry-run LowCmd (subscribe only)
- Real LowState + Real LowCmd (actuation enabled)
For EDU23, missing joints are masked (policy space stays 29-DoF, hardware has 23 active joints).
cd ~/rl_hnav
colcon build --cmake-args -DUSE_MUJOCO=ON -DENABLE_REAL_ROBOT=ON
source install/setup.bashsource /opt/ros/humble/setup.bash ###(.zsh)
source rl_hnav/install/setup.bash ###(.zsh)
ros2 run rl_sar rl_real_g1_edu23 wlo1 --ros-args \
-p hw_mode:=1 -p fake_rl_full:=true -p publish_lowcmd:=false \
-p navigation_mode:=true -p cmd_vel_topic:=/cmd_velsource /opt/ros/humble/setup.bash ###(.zsh)
source rl_hnav/install/setup.bash ###(.zsh)
ros2 run rl_sar rl_real_g1_edu23 wlo1 --ros-args \
-p hw_mode:=0 -p publish_lowcmd:=true \
-p navigation_mode:=true -p cmd_vel_topic:=/cmd_vel -p cmd_vel_timeout_sec:=0.2
wlo1 is the network interface
If you see:
libmujoco.so.3.2.7: cannot open shared object file
Check:
ldd install/rl_sar/lib/rl_sar/rl_mujoco | grep mujoco- Ensure
/cmd_velis published:
source /opt/ros/humble/setup.bash ###(zsh)
source rl_hnav/install/setup.bash ###(zsh)
ros2 topic echo /cmd_vel- Increase timeout for testing:
source /opt/ros/humble/setup.bash ###(zsh)
source rl_hnav/install/setup.bash ###(zsh)
-p cmd_vel_timeout_sec:=2.0Wholeheartedly welcome contributions from the community to make this framework mature and useful for everyone. These may happen as bug reports, feature requests, or code contributions.
Please cite the following if you use this code or parts of it:
@software{jean-2026g1,
author = {Mayoko Biong J.C, Sánchez-González L., Matellán-Olivera V.,},
title = {rl_hnav: Navigation-Aware Hybrid Execution Stack for Unitree G1
.},
url = {https://github.com/uleroboticsgroup/rl_hnav.git},
year = {2026}
}
Apache-2.0 (inherit where applicable). See headers in source files.
- This project builds upon and extends the following open-source repositories:
- rl_sar
- unitreerobotics/unitree_sdk2-2.0.0
- unitreerobotics/unitree_mujoco
- google-deepmind/mujoco-3.2.7
- This project is funded by the SWEET (Social aWareness for sErvicE roboTs) Marie Skłodowska-Curie Doctoral Network, grant agreement No 101168792

