feat(go2): low-level wholebody control#2361
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR adds low-level whole-body control for the Unitree Go2 quadruped: a new
Confidence Score: 4/5Safe to merge for single-robot deployments; the DDS initialization path can fail if another SDK module has already called ChannelFactoryInitialize in the same process. The motor-command write and safe-stop paths are correctly guarded. The one gap is in start(): ChannelFactoryInitialize is called without any exception handling, unlike the G1 module which catches and silently continues on the already-initialized case. In a process that also runs G1WholeBodyConnection or any other SDK consumer, Go2 start() will throw an uncaught exception from the SDK rather than logging and continuing. dimos/robot/unitree/go2/wholebody_connection.py — specifically the DDS initialization block in start(). Important Files Changed
Sequence DiagramsequenceDiagram
participant Op as Operator
participant Blueprint as unitree_go2_wholebody_coordinator
participant Conn as Go2WholeBodyConnection
participant DDS as Unitree DDS (rt/lowstate / rt/lowcmd)
participant Coord as ControlCoordinator
participant LCM as LCM Transport
Op->>Blueprint: dimos run
Blueprint->>Conn: start()
Conn->>DDS: ChannelFactoryInitialize
Conn->>DDS: ChannelPublisher("rt/lowcmd").Init()
Conn->>DDS: ChannelSubscriber("rt/lowstate").Init(None,0)
Conn->>Conn: _release_sport_mode() [up to 30s]
Conn->>DDS: Read() — wait for first LowState
DDS-->>Conn: LowState frame
Conn->>Conn: start publish_loop thread (500 Hz)
loop 500 Hz publish loop
Conn->>DDS: Read() → _low_state
Conn->>LCM: motor_states (JointState)
Conn->>LCM: imu (Imu)
end
LCM->>Coord: joint_state
Coord->>LCM: joint_command (JointState)
LCM->>Conn: motor_command (MotorCommandArray)
Conn->>Conn: _on_motor_command [inside _lock]
Conn->>DDS: publisher.Write(LowCmd_) [inside _lock]
Op->>Blueprint: stop()
Blueprint->>Conn: stop()
Conn->>DDS: "Write safe-stop LowCmd_ (mode=0x00)"
Conn->>DDS: subscriber.Close() / publisher.Close()
Reviews (3): Last reviewed commit: "fix: write low_cmd inside the lock" | Re-trigger Greptile |
| motor_command: In[MotorCommandArray] | ||
| motor_states: Out[JointState] | ||
| imu: Out[Imu] |
There was a problem hiding this comment.
We should also get Camera and Lidar streams as out using the Connection Module.
| self._low_cmd = unitree_go_msg_dds__LowCmd_() | ||
| self._low_cmd.head[0] = 0xFE | ||
| self._low_cmd.head[1] = 0xEF | ||
| self._low_cmd.level_flag = 0xFF | ||
| self._low_cmd.gpio = 0 | ||
| self._reset_motor_cmd_slots(_MOTOR_MODE_ENABLE) |
There was a problem hiding this comment.
We should codify these magic bytes in docstrings for better dev experience
Problem
Feature: go2 low level controls
Closes DIM-753
Solution
Add Go2 wholebody (low-level) control:
How to Test
Contributor License Agreement