|
Download cpp_lowcmd_bridge/README.md from BAAI/PingPongRealWorldRL: direct link, hf CLI and curl.
- Browser
- Download file 4.22 kB
-
https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/cpp_lowcmd_bridge/README.md
- Command line
-
hf download hf://BAAI/PingPongRealWorldRL/cpp_lowcmd_bridge/README.md
-
curl -L -o README.md https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/cpp_lowcmd_bridge/README.md
4.22 kB
| # H2 ROS 2 LowCmd bridge | |
| This C++17 package connects Unitree `unitree_hg` ROS 2 messages to the Python controller through H2BR shared memory. It receives ROS `/lowstate` (native DDS `rt/lowstate`), mirrors `/wbc_racket_command`, and publishes ROS `/lowcmd` (native DDS `rt/lowcmd`) at 1000 Hz. | |
| Read [setup](../docs/SETUP.md) and complete site-specific hardware commissioning before a live launch. The bridge executable is a hardware control component; compilation or a passing contract check does not authorize robot operation. | |
| ## Build and inspect on Linux | |
| From the repository root, with ROS 2 Humble, the installed `unitree_hg` workspace, and the selected network interface configured: | |
| ```bash | |
| export H2_IF=enp4s0f0 | |
| export UNITREE_ROS2_ROOT="$HOME/unitree_ros2" | |
| source scripts/source_unitree_env.sh "$H2_IF" | |
| colcon build --packages-select cpp_lowcmd_bridge \ | |
| --cmake-args -DCMAKE_BUILD_TYPE=Release | |
| source install/setup.bash | |
| ros2 run cpp_lowcmd_bridge h2_lowcmd_shm_bridge --print-contract | |
| ros2 run cpp_lowcmd_bridge h2_lowcmd_shm_bridge \ | |
| --validate-network-only --network-interface "$H2_IF" | |
| ``` | |
| The expected contract is: | |
| ```text | |
| H2BR magic=0x48324252 version=7 bytes=1544 state_dof=31 lowcmd_slots=35 mode_pr=0 joint_map=unitree_sdk2@e02dc701-h2-cpp cmd_q=raw_learned_desired ros_lowstate=/lowstate ros_lowcmd=/lowcmd publish_hz=1000 | |
| ``` | |
| Network validation checks the local RMW/interface/CycloneDDS configuration only. The native LowState inspector and physical identity check are separate commissioning gates. Build outputs belong in `build/`, `install/`, and `log/` and are not release source. | |
| ## Admission and shared memory | |
| Live startup requires `--network-interface`. The interface must be UP and match `CYCLONEDDS_URI` generated by the environment script. The bridge publishes no command until it has valid H2 LowState in PR mode, no discovered competing LowCmd publisher, and a finite Python H2BR command carrying the validated MotionSwitcher attestation bit. It never changes AB mode into PR mode. | |
| The 1544-byte H2BR v7 interface uses 31 state/command slots and the audited C++ motor map. Waist IDs 12/13/14 are yaw/roll/pitch; wrist IDs are roll/pitch/yaw. Policy ordering is different and is mapped by name in the Python H2 contract. Shared-memory locks protect coherent snapshots and allow only one Python command writer. | |
| The production shared-memory name is `h2_pingpong_bridge`. The simulator uses a separate name and ownership contract; it must not attach to production memory. Before a runner starts, the [no-runner validation script](../scripts/validate_bridge_no_runner.sh) checks healthy/disarmed state, LowState update rate, exclusive ROS endpoint ownership, and absence of actual LowCmd samples. | |
| ## Command and stop semantics | |
| `cmd_q` contains the raw learned desired joint target. Immediately before each 1000 Hz publication, the bridge projects that target into the PD-effort interval computed from the latest valid joint position/velocity and actuator effort limits. This allows an out-of-range desired target to request saturated effort without first rewriting it to a mechanical angle boundary. Measured state and captured stop-hold poses remain subject to mechanical limits. | |
| Python supplies zero desired velocity and zero feed-forward torque. It also sets both raw head targets to zero; the effort-projected target can differ from zero when required by the actuator limit. Do not independently change action scaling, motor ordering, gains, or projection semantics. | |
| L1 latches the policy-start request. R1 latches stop and captures the last legal measured pose. The 100 ms watchdog, motor faults, invalid commands, competing publishers, and non-PR/invalid state also latch faults. Stale or invalid LowState inhibits LowCmd output; the bridge does not compute a hold from stale state. A recovered input does not clear a latch. Exit and restart through the full admission procedure. | |
| The bridge must stop last among the control processes during normal shutdown. Stale production shared memory is handled only with the guarded `--replace-stale-shm` path after verifying that no bridge process owns it. Software stop is not a substitute for an independent hardware emergency stop. | |