中文 | English
PlotJuggler Unitree SDK2 Plugin.
This repository provides two plugins:
Unitree SDK2 DDS: a DataStreamer plugin that subscribes to DDS topics throughunitree_sdk2and flattens strongly typed messages into numeric PlotJuggler series.Unitree Robot View: a Toolbox plugin that renders Unitree robot posture fromlowstateIMU and motor position series already loaded into PlotJuggler.
Download the Linux x86_64 bundle from GitHub Releases:
plotjuggler-unitree-sdk2-<version>-linux-x86_64.tar.gz
Extract it to any directory, for example:
mkdir -p ~/plotjuggler_plugins
tar -xzf plotjuggler-unitree-sdk2-<version>-linux-x86_64.tar.gz \
-C ~/plotjuggler_pluginsThe extracted directory is the plugin folder that PlotJuggler should load:
~/plotjuggler_plugins/plotjuggler-unitree-sdk2-<version>-linux-x86_64/
Open PlotJuggler, open Preferences, select the Plugins tab, click Add in the Plugin folders list, choose the extracted directory, confirm, and restart PlotJuggler.
After restart, you should see:
Unitree SDK2 DDSin the Streaming panelUnitree Robot Viewin theToolsmenu
You can also load the plugin folder temporarily from the command line without changing Preferences:
plotjuggler --plugin_folders "$HOME/plotjuggler_plugins/plotjuggler-unitree-sdk2-<version>-linux-x86_64"In the PlotJuggler Streaming panel, select Unitree SDK2 DDS. Use the gear button to configure DDS network interface, domain id, queue length, joystick field mode, and data enhancement.
Press Start to scan DDS publications and select topics from the discovered list. Supported types are sorted first and selected by default. If the robot or DDS publisher starts later, press Refresh to scan again. After confirmation, the plugin subscribes to the selected topics and writes PlotJuggler series.
Joystick fields defaults to Parsed structure. In this mode, Unitree joystick data is decoded into fields such as wireless_remote/buttons/*, wireless_remote/axes/*, joystick/buttons/*, and joystick/axes/* instead of only exposing raw bytes or key bitmasks.
Data enhancement provides three independent checkboxes:
PD torque (tau_des): checked by default. CombinesLowCmdandLowStateto calculate total torque and its P/D terms.Flatten: unchecked by default. Retains originalmotor_stateandmotor_cmdfields and adds field-first series under the top-levelmotorstate*andmotorcmd*groups, such aslowstate/motor_state/00/q→motorstate*/q/00andlowcmd/motor_cmd/00/kp→motorcmd*/kp/00. Values, timestamps, and motor indices are preserved. Nested arrays such asmotor_state/00/temperature/1becomemotorstate*/temperature/00/1.Joint power (des, est): unchecked by default. Calculates desired and estimated power for each joint (signed mechanical power in watts), independently of the PD torque output option.
With PD torque checked and both LowCmd and LowState subscribed, three series are appended per motor:
lowstate/motor_state/NN/tau_des_p* = kp * (q_cmd - q_state)
lowstate/motor_state/NN/tau_des_d* = kd * (dq_cmd - dq_state)
lowstate/motor_state/NN/tau_des* = tau_cmd + tau_des_p + tau_des_d
The trailing * marks calculated torque fields. Checking PD torque and Flatten also adds motorstate*/tau_des*/00, motorstate*/tau_des_p*/00, and motorstate*/tau_des_d*/00. Each state sample produces one set of torques, preferring the sibling lowcmd topic; when it is absent, a single unambiguous command topic is used.
Go2 and HG messages are paired by SDK family, topic namespace, and motor index. Series use the actual state topic path under motor_state/NN/. LowState drives sampling: after the first LowCmd arrives, torques are computed only on each LowState, using that state's local receive time. LowCmd uses a zero-order hold: the latest received command is reused until replaced. Command updates only refresh the cache; they do not append torque samples or recompute past states. Calculations requiring a paired command pause if multiple LowState topics arrive in one namespace; HG mode_pr values must also match. Like joystick parsing, all three checkboxes are saved independently in default settings and layout XML and take effect during streaming. The legacy data enhancement setting restores the PD torque choice. Disabling any option stops appending its data and retains existing curves. Re-enabling calculations after both PD torque and joint power were off, or restarting the stream, clears the command pairing cache and waits for fresh commands.
With joint power checked, each LowState produces power using its measured velocity:
lowstate/motor_state/NN/power_des* = tau_des * dq_state
lowstate/motor_state/NN/power_est* = tau_est * dq_state
tau_des includes feed-forward, P, and D terms, computed internally even with PD torque output unchecked. It uses the held LowCmd and the existing pairing rules. power_est* depends only on LowState, without waiting for a command. Both powers use the state's timestamp and retain their sign rather than taking an absolute value; stationary joints have zero mechanical power. Checking Flatten also adds the top-level motorstate*/power_des*/NN and motorstate*/power_est*/NN series.
Leading unitree/ and rt/ topic path components are removed from series names, for example:
lowstate/imu_state/rpy/0
lowstate/motor_state/00/q
sportmodestate/velocity/0
The time axis is local elapsed seconds from the moment streaming starts.
First stream lowstate data with Unitree SDK2 DDS, then open Tools / Unitree Robot View. Robot View does not subscribe to DDS by itself; it consumes the time series already loaded into PlotJuggler.
Input series:
lowstate/imu_state/rpy/*orlowstate/imu_state/quaternion/*lowstate/motor_state/NN/q
Controls:
- Drag with the left mouse button to rotate the camera.
- Use the mouse wheel to zoom.
- Double-click to reset the camera.
- Click the top-right axis icon to align the view to an axis.
- Keep
Livechecked to follow the latest data, or uncheck it and drag the timeline to replay older posture data.
Topic support is determined by DDS type, not by fixed topic names. Built-in support covers top-level Unitree SDK2 IDL message types under:
unitree_gounitree_hgunitree_hg_doubleimu- ROS2-style
std_msgs,geometry_msgs,sensor_msgs, andnav_msgs
Numeric fields are flattened recursively. Strings are exported as /length; if a string contains valid JSON, numeric and boolean JSON leaves are also exported under /json/.... Large variable-length sequences such as images, point clouds, and maps are size-limited to avoid flooding PlotJuggler.
To add new message types, update:
include/plotjuggler_unitree_sdk2/unitree_message_flatten.h
Motor order follows Unitree SDK2 LowState.motor_state[], not URDF joint order. Go2 example:
FR_hip, FR_thigh, FR_calf,
FL_hip, FL_thigh, FL_calf,
RR_hip, RR_thigh, RR_calf,
RL_hip, RL_thigh, RL_calf
The current bundle supports A1, Aliengo, B1, B2, B2W, Go1, Go2, Go2W, G1 23DOF, G1 29DOF, G1-D, H1, H1-2, H2, R1, and R1 AIR.
The repository tracks project source, CI configuration, and required dependency declarations only. Build trees, install trees, generated bundles, deb caches, local sysroots, and PlotJuggler source checkouts are ignored.
Required dependencies:
third_party/unitree_sdk2: Git submodule for Unitree SDK2, DDS type definitions, and DDS runtime libraries.third_party/unitree_ros_assets: Git submodule for Robot View URDF and mesh assets.- Qt: system development package dependency.
- PlotJuggler: build-time development prefix dependency. It must provide
plotjugglerConfig.cmakeandplotjuggler_base; it is not a repository submodule.
On Ubuntu 22.04/24.04:
scripts/install_ubuntu_deps.shThis installs CMake, Ninja, Qt5, PlotJuggler build dependencies, and the base development packages used by CI.
git submodule update --init --depth 1 \
third_party/unitree_sdk2 \
third_party/unitree_ros_assetsIf the Snap PlotJuggler package is available, reuse its development prefix:
export PLOTJUGGLER_PREFIX=/snap/plotjuggler/current/usr/localIf no development prefix is available, build PlotJuggler 3.17.2 into .deps/plotjuggler-3.17.2:
scripts/build_plotjuggler_dev.sh
export PLOTJUGGLER_PREFIX="$PWD/.deps/plotjuggler-3.17.2"Recommended local build:
scripts/build_local_bundle.shEquivalent CMake preset commands:
cmake --preset dev
cmake --build --preset dev --parallel 4
ctest --preset devBuild only the message flattener smoke test, without Qt or PlotJuggler:
cmake --preset smoke
cmake --build --preset smoke --parallel 4
ctest --preset smokeUNITREE_SDK2_ROOT=/path/to/unitree_sdk2: override the default submodule.PJ_UNITREE_BUNDLE_DIRECTORY=/path/to/bundle: choose the runtime bundle output directory.PJ_UNITREE_BUILD_BUNDLE=OFF: build the shared libraries only, without copying the runtime bundle.PJ_UNITREE_COPY_ROBOT_ASSETS=OFF: skip URDF/mesh copying, useful when working only on the DDS plugin.PJ_PLUGIN_INSTALL_DIRECTORY=/path/to/plugin_dir: install plugins to a specific PlotJuggler plugin directory withcmake --install.
Raw build outputs:
build/dev/libplotjuggler_unitree_sdk2.so
build/dev/libplotjuggler_unitree_robot_view.so
Default runtime bundle:
bundle/plotjuggler_unitree_sdk2/
libplotjuggler_unitree_sdk2.so
libplotjuggler_unitree_robot_view.so
libddsc.so
libddsc.so.0
libddscxx.so
libddscxx.so.0
assets/robots/
licenses/
The bundle uses $ORIGIN RPATH for the DDS runtime libraries copied from Unitree SDK2. Qt and PlotJuggler libraries are intentionally not bundled; runtime users should rely on their installed PlotJuggler distribution.
Create a release package after building:
scripts/package_bundle.sh 0.1.0Outputs:
dist/plotjuggler-unitree-sdk2-0.1.0-linux-x86_64.tar.gz
dist/plotjuggler-unitree-sdk2-0.1.0-linux-x86_64.tar.gz.sha256
GitHub Actions:
.github/workflows/ci.yml: builds with thecipreset, runs tests, and uploads a bundle artifact. CI uses a Release build and 2 parallel compile jobs to match the standardubuntu-22.04GitHub-hosted runner resource profile..github/workflows/release.yml: builds and publishes a GitHub Release when av*tag is pushed.
Release:
git tag v0.1.0
git push origin v0.1.0Project source code is licensed under the permissive MIT License; see LICENSE. It allows copying, modification, redistribution, and commercial use, provided that the copyright and license notice are retained.
Unitree SDK2 and Unitree ROS assets are BSD-3-Clause licensed. The release bundle copies:
licenses/unitree_sdk2_LICENSElicenses/unitree_sdk2_thirdparty/licenses/unitree_ros_LICENSE

