unitree_lowlevel is a low-level control layer for Unitree Go2 and G1 robots.
It reads robot state, runs a low-level control loop, exposes hooks for a user-defined high-level controller, and sends joint commands through the appropriate Unitree SDK adapter.
This repository sits between the Unitree communication stack and your controller logic:
- legged_base Shared utilities for legged robots, including timers, math helpers, interpolation, robot state containers, and Pinocchio-based kinematics and dynamics.
unitree_lowlevel(this repository) Hardware abstraction layer (HAL) and controller entry point. It reads sensors, manages the gamepad state machine, provides emergency-stop handling and PD-based initialization, and forwards commands through the correct adapter for Go2 or G1.- unitree_sdk2 Unitree's DDS-based SDK for Go2 and G1 communication.
- unitree_ros2 ROS 2 message packages used to decode Unitree topics correctly.
- unitree_mujoco Simulation environment with the same communication interface as the hardware, useful for controller validation before deployment.
Additional documentation in this repo:
For a reference high-level controller integration, see legged_rl_deploy.
unitree_sdk2 and ROS 2 both use DDS. As long as the ROS_DOMAIN_ID and network interface are configured consistently, the same controller can talk to either hardware or simulation.
To run Unitree MuJoCo:
source src/unitree_lowlevel/scripts/setup.sh lo <ros-distro>
$WORKSPACE/src/unitree_mujoco/simulate/build/unitree_mujoco -i 0 -n loOnce MuJoCo is running, start the controller node with the matching robot config in another terminal.
Note: Unitree MuJoCo reads
src/unitree_mujoco/simulate/config.yaml. Setuse_joystick: 1there if you want joystick input.Note: Unitree typically uses
ROS_DOMAIN_ID=0on hardware and recommendsROS_DOMAIN_ID=1for simulation. This repository keepsROS_DOMAIN_ID=0for both, relying on different network interfaces such aslofor simulation andeth0for hardware.
mkdir -p unitree_ws/src
cd unitree_ws/src
git clone https://github.com/Renkunzhao/unitree_lowlevel.gitThe build script imports additional repositories into src/ and lib/, so start from a workspace root as shown above.
Install Docker Engine and the NVIDIA Container Toolkit first.
For Jetson-based onboard computers, update docker/docker-compose.yaml and replace:
gpus: allwith:
runtime: nvidiaThen build and enter the container:
cd unitree_lowlevel/docker
docker compose up -d --build
docker exec -it unitree_ws bashUsing the VS Code Dev Containers extension is recommended.
Install ROS 2 first. This repository has been tested on Ubuntu 20.04, 22.04, and 24.04.
sudo apt install -y python-is-python3 python3-colcon-common-extensions libopenblas-dev python3-dev python3-vcstool libyaml-cpp-dev libspdlog-dev libboost-all-dev libglfw3-dev libfmt-dev python3-toml
sudo apt install ros-<ros-distro>-pinocchio ros-<ros-distro>-rmw-cyclonedds-cpp ros-<ros-distro>-rosidl-generator-dds-idlcd unitree_lowlevel
./scripts/colcon-config.sh <ros-distro> <Release|Debug>This script:
- imports repositories listed in
scripts/lib.reposandscripts/src.repos - builds and installs
unitree_sdk2 - downloads MuJoCo for simulation
- builds the ROS 2 workspace with
colcon
Before running hardware or simulation, configure the ROS 2 and DDS environment:
source src/unitree_lowlevel/scripts/setup.sh <network-interface> <ros-distro>This script sets:
WORKSPACENetworkInterfaceROS_DOMAIN_ID=0RMW_IMPLEMENTATION=rmw_cyclonedds_cppCYCLONEDDS_URIfor the selected interface
Typical interface choices:
lofor local simulationeth0or the robot-facing NIC for hardware
Stop the default controller once after each boot:
source src/unitree_lowlevel/scripts/setup.sh <network-interface> <ros-distro>
$WORKSPACE/build/unitree_sdk2/bin/go2_stand_example <network-interface>Then start the low-level controller:
ros2 run unitree_lowlevel unitree_lowlevel_node <network-interface> $WORKSPACE/src/unitree_lowlevel/config/go2.yamlFollow the Unitree G1 developer quick start to enter Debug Mode, then run:
source src/unitree_lowlevel/scripts/setup.sh <network-interface> <ros-distro>
ros2 run unitree_lowlevel unitree_lowlevel_node <network-interface> $WORKSPACE/src/unitree_lowlevel/config/g1.yamlNote: The executable name is
unitree_lowlevel_nodefor both robots. The actual robot adapter is selected from the YAML config file.
When the node starts, it waits for confirmation before commanding the robot:
WARNING: Make sure the robot is hung up or lying on the ground.
Press Enter to continue...
Do not skip this check during first bring-up or after changing gains, configs, or controller logic.
The controller uses the following button mappings:
L2 + B: emergency stopSELECT + START: clear emergency stop and return toIDLEL2 + AfromIDLE: enterFixStandL2 + AfromFixStand: enterPreIDLE, then return toIDLESTARTfromFixStand: enterHighControllerSELECTfromHighController: return toFixStand
HighController is the hook for user-defined higher-level logic. This repository provides the low-level loop, state handling, and robot I/O; it does not ship a task-specific high-level controller.
This repository uses vcstool to track workspace dependencies and colcon with CMake for builds.
To export the current dependency state:
cd $WORKSPACE
vcs export lib --exact > $WORKSPACE/src/unitree_lowlevel/scripts/lib.repos
vcs export src > $WORKSPACE/src/unitree_lowlevel/scripts/src.reposReview the generated .repos files and remove unrelated repositories before committing updates.
The repositories below are not required to build or run unitree_lowlevel, but this repository includes helper scripts and configuration to make integration easier.
Reinforcement learning stack for Unitree robots based on Isaac Lab, with C++ deployment code.
source src/unitree_lowlevel/scripts/setup.sh <network-interface> $ROS_DISTRO
cd $WORKSPACE/lib
git clone https://github.com/unitreerobotics/unitree_rl_lab.git
cd unitree_rl_lab/deploy/robots/g1_29dof
mkdir build
cd build
source $WORKSPACE/src/unitree_lowlevel/scripts/unitree_sdk_path.sh
cmake .. && make -j$(nproc)
./g1_ctrl $NetworkInterfaceReinforcement learning stack for Unitree robots based on MuJoCo, with C++ deployment code.
source src/unitree_lowlevel/scripts/setup.sh <network-interface> $ROS_DISTRO
cd $WORKSPACE/lib
git clone https://github.com/unitreerobotics/unitree_rl_mjlab.git
cd unitree_rl_mjlab/deploy/robots/g1
mkdir build
cd build
source $WORKSPACE/src/unitree_lowlevel/scripts/unitree_sdk_path.sh
cmake .. && make -j$(nproc)
./g1_ctrl $NetworkInterface