KurisiTOMA's picture
chore: publish H2 real-world RL system
d8290eb verified
|
Raw History Blame Contribute Delete
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 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:

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:

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 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.