Capture and replay accurate, high frequency timestamped Unitree Go2 data for analysis and visualization using MuJoCo — compatible with NumPy and ROS2 bags. Topics are matched and merged with different data sources, like Vicon for base estimation.
Note
Data is only recorded when commands are received, either from the remote control or via ROS topic.
- ROS2 bag compatible (tested on Humble)
- Synchronized recording across topics
- Per-step timestamps
- Live MuJoCo visualization
- NumPy (.npy) output format
- Supports Unitree SportStateMode, Vicon, and go2_odometry for base estimation
Supported base estimators
- Unitree SportStateMode
- Vicon (a camera based motion capture system).
Note
Sport state mode is not available when the robot is in low state mode (e. g. if you want to record policy data). Vicon offers the highest accuracy. For vicon, you find more information in thedocsfolder.
The following data is stored: Low cmd:
- q - motor positions (12)
- dq - motor velocities (12)
- tau - torques (12)
- kp position gains (12)
- kd derivative gains (12)
Low state:
- quaternion (4)
- gyroscope (3)
- d - motor positions (12)
- dq - motor velocities (12)
- tau_est - estimated torques (12)
- q_raw (12)
- dq_raw (12)
Base estimation:
- base position
- base velocity (not implemented for vicon)
Install the following dependencies:
- unitree_ros2: Only tested with Humble!
- unitree_sdk2
- mujoco (version 3.2.7)
- cnpy
sudo apt install libglfw3-dev libxinerama-dev libxcursor-dev libxi-dev libspdlog-dev- gum
- Vicon
Important
You must build MuJoCo from source, it is not enough to install the precompiled version!
Before compiling anything, make sure you source the setup.sh from unitree_ros2. Also source the setup script in its installation folder.
source ~/unitree_ros2/setup.sh
source ~/unitree_ros2/install/setup.shFor accurate time measurement, install and set up the timed_topics ROS package on the Unitree Go2's internal Nvidia Jetson. You only need unitree_ros2, but be sure to follow the steps from the previous section.
cd timed_topics
colcon build --packages-select timed_topicsYou also need to build the timed_topics package on your workstation for building the Go2Recorder itself, see next capture.
Start the node only on the Nvidia Jetson:
ros2 run timed_topics republish_node Alternatively, you can start it on your workstation, but timestamp accuracy may be affected by system load. In this case, you should extend your python environment to also use the system packages.
python3.10 -m venv .venv --system-site-packages
uv pip install catkin_pkg "empy<4" larkThis is confusing at this point, continue reading, until capture Python Installation.
Important
For time synchronization, especially when using Vicon, synchronize the Nvidia Jetson and your workstation. I used chrony for this.
Make sure all dependencies are installed and available in your system path. Then build the project with:
mkdir build && cd build
cmake .. && make** Note** If you see any errors, make sure your ROS environment is properly sourced. The
timed_topicspackage must be compiled and sourced first.
Set the path to your Unitree ROS2 workspace by adding the following to your shell startup file (e.g. ~/.zshrc or ~/.bashrc):
export GO2_ROS="$HOME/unitree_ros2"Reload your shell configuration:
source ~/.zshrc # or: source ~/.bashrcTo start the recorder, run
./setup.shin the project root (interactive), or run the built executable in build:
./go2_recorder --mode <high|vicon> --model <model_path> --storage <storage_path>The recording is always stored within the output folder in the project root, a simple name suffices, e. g., test.npy.
Note
When recording simulation data only, the recorder expects Unitree MuJoCo as virtual robot. This is already part of this repo as a submodule. Build it, start ./mujoco.sh and create a ROS node which sends commands to the environment.
If required, the created .npy file in the storage directory can be rendered using Python.
See renderer/play.py for an example of how to use the recording.
Install all Python dependencies using uv or a package manager of your liking:
uv syncAnd don't forget to activate the environment:
source .venv/bin/activateFor timestamp inspection run:
python debugging/latency.pyTo create a video from your recording, use:
python debugging/render.pyStart the interactive setup script:
setup.shThe script helps you checking your setup, including the network.
To save your recording, just close the MuJoCo window or press Ctrl+C in the terminal.
Note
Setting up the vicon network requires you to changesetup.sh.
At the top, insert your data:
VICON_ETH_INTERFACE="enx34298f722bdf"
VICON_IP="10.0.0.20"In the lab, I used a direct ethernet link to the vicon system. Make sure, the network interface for vicon is unmanaged, otherwise it may be removed by the network manager.
The recorder also supports ROS2 bags. To record, run:
ros2 bag record /lowstate /lowcmd /sportmodestate -o myrecordingThen start the Go2Recorder and play the bag:
ros2 bag play myrecordingNote
Make sure, that you use in both shells the same ROS domain.
Important
This applies only to SportStateMode. Vicon does not publish ROS2 topics.
You will notice that the recording contains a different number of messages for each relevant topic. This requires a synchronization strategy. I chose to use the topic with the most messages, which is /lowstate, as the reference. The program always takes the closest /lowcmd message in the buffer and searches for the closest messages from the other topics. For Vicon data, interpolation is used: the algorithm finds the two nearest measurements (one older, one newer) and interpolates position, velocity, and rotation (using slerp for orientation).
Note that the timestamps here are based on the (rather inaccurate) PC time, since there are no timestamps available in /lowcmd and /lowstate.
This project is based on a heavily rewritten version of the work from unitree_mujoco. The XML model is also adapted from that repository.