unitree_ros2 SportClient详解:用请求响应机制让四足机器人站立、行走与后空翻
unitree_ros2 SportClient详解:用请求响应机制让四足机器人站立、行走与后空翻
本文详解开源项目 unitree_ros2 中的 SportClient 类:它基于 DDS 的请求/响应机制,让你用几行代码就能让 Unitree 四足机器人(Go2、B2 等)站立、行走,甚至完成前空翻与后空翻动作。即使你是 ROS2 新手,也能跟着本文从零跑通第一个运动控制指令。
什么是 SportClient:Unitree 四足机器人运动模式控制的核心
unitree_ros2 是 Unitree 机器人官方的 ROS2 通信框架。它的核心思路是:Unitree 机器人底层本身使用 CycloneDDS 作为通信中间件,而 ROS2 同样以 DDS 为底层,因此两者可以直接互通——你无需再封装任何 SDK 接口,用标准的 ros2 命令和消息就能直接控制机器人 🤖。
项目支持 Go2、B2、B2-W、H1、H1-2、G1、H2 等型号,整体结构分为两部分:
| 目录 | 作用 |
|---|---|
| cyclonedds_ws/ | 存放机器人通信消息定义,如 unitree_go(Go2/B2 消息)和 unitree_api/(通用请求/响应消息) |
| example/ | 各类官方示例源码,包括本文主角 SportClient 及其调用示例 |
控制 Unitree 机器人有两层抽象:
- 运动模式(SportMode):机器人自带的高层行为,站立、行走、坐下、空翻等都已内置,开发者只需"发指令"。
- 底层控制(LowCmd):直接控制每个关节电机,用于自定义步态等进阶场景。
SportClient 正是运动模式控制的核心封装类,源码位于 ros2_sport_client.cpp,头文件在 ros2_sport_client.h。它把几十个"机器人动作"封装成同名 C++ 方法:StandUp() 站立、Move() 行走、FrontFlip() 前空翻……调用哪个方法,机器人就做出哪个动作。
请求/响应机制:一条 DDS 消息如何驱动机器人
SportClient 的妙处在于它完全复用了 ROS2 的发布者/订阅者模型,没有引入任何私有协议。
工作机制只有 4 步:
- SportClient 构造时,向主题
/api/sport/request创建一个发布者; - 调用某个方法(如
Move)时,往Request消息里写入对应的api_id和 JSON 参数; - 机器人收到请求后执行动作,并向
/api/sport/response发布Response消息; - 若需要返回值(如
AutoRecoveryGet),Call()模板函数会订阅响应主题,按api_id匹配后把 JSON 结果解析返回。
请求消息 Request 的结构定义在 Request.msg,核心字段只有三个:
RequestHeader header # 含 identity.api_id,标识要调用哪个接口
string parameter # JSON 参数,例如 {"x":0.3,"y":0,"z":0}
uint8[] binary # 二进制数据(一般用不到)
响应消息 Response 的结构见 Response.msg,其中 data 字段同样是一段 JSON 字符串。
以"以 0.3 m/s 前进"为例,Move 方法内部做的事情一目了然:
void SportClient::Move(unitree_api::msg::Request &req, float vx, float vy, float vyaw) {
nlohmann::json js;
js["x"] = vx; js["y"] = vy; js["z"] = vyaw;
req.parameter = js.dump();
req.header.identity.api_id = ROBOT_SPORT_API_ID_MOVE; // 1008
req_puber_->publish(req);
}
每个动作都对应一个唯一的 api_id 编号,这是理解整套机制的关键。常用接口一览:
| 动作 | 方法 | api_id | 动作 | 方法 | api_id |
|---|---|---|---|---|---|
| 阻尼(瘫软) | Damp |
1001 | 前空翻 | FrontFlip |
1030 |
| 平衡站立 | BalanceStand |
1002 | 前跳 | FrontJump |
1031 |
| 停止运动 | StopMove |
1003 | 后空翻 | BackFlip |
2043 |
| 站起 | StandUp |
1004 | 手倒立 | HandStand |
2044 |
| 坐下 | StandDown |
1005 | 自由行走 | FreeWalk |
2045 |
| 恢复站立 | RecoveryStand |
1006 | 经典步态行走 | ClassicWalk |
2049 |
| 调姿(欧拉角) | Euler |
1007 | 自动恢复设置 | AutoRecoverySet |
2054 |
| 速度控制 | Move |
1008 | 自由避障开关 | FreeAvoid |
2048 |
| 坐 / 起身 | Sit / RiseSit |
1009/1010 | 打招呼 / 比心 | Hello / Heart |
1016/1036 |
| 舞蹈 | Dance1 / Dance2 |
1022/1023 | 速度档位 | SpeedLevel |
1015 |
完整编号表可以在 ros2_sport_client.h 开头的常量定义中查到。
三步跑通 go2_sport_client 示例:环境配置与连接验证
项目自带了最完整的 SportClient 调用示例 go2_sport_client.cpp,内置 11 种测试模式(站立、行走、坐下、空翻……),只需一个命令行参数即可切换。
第一步:克隆并编译
git clone https://gitcode.com/gh_mirrors/uni/unitree_ros2
cd unitree_ros2/cyclonedds_ws
colcon build # Humble 环境可跳过 cyclonedds 重编译
cd ~/unitree_ros2/example
colcon build
系统要求:Ubuntu 22.04 + ROS2 Humble(推荐)或 Ubuntu 20.04 + Foxy,详见 README.md。
第二步:配置网络与环境
用网线连接电脑与机器人(机器人网段 192.168.123.x),然后把电脑网卡设为 192.168.123.99。打开 setup.sh,把其中的网卡名改为你实际连接机器人的接口,然后:
source ~/unitree_ros2/setup.sh # 加载 ROS2 + CycloneDDS 环境
ros2 topic list # 能看到 /sportmodestate 等主题即连接成功
没有真机想做仿真时,可以改用 setup_local.sh(走本地回环)或 setup_default.sh。
第三步:发送指令,看机器人动起来
./install/unitree_ros2_example/bin/go2_sport_client <模式号>
| 模式号 | 动作 | 模式号 | 动作 |
|---|---|---|---|
| 0 | NORMAL_STAND 站立 | 5 | DAMP 阻尼 |
| 1 | BALANCE_STAND 平衡站立 | 6 | RECOVERY_STAND 恢复站立 |
| 2 | VELOCITY_MOVE 速度移动 | 7 | SIT 坐下 |
| 3 | STAND_DOWN 坐下(站姿) | 8 | RISE_SIT 起身 |
| 4 | STAND_UP 站起 | 9 | MOVE 直线行走 |
| 10 | STOP_MOVE 停止 |
以"让机器人前向+侧向移动"为例,示例中对应的一行就是:
sport_client_.Move(req_, 0.3, 0, 0.3); // vx=0.3, vy=0, vyaw=0.3
go2_sport_client 还会同时订阅 lf/sportmodestate 主题,把机器人的位置和 IMU 姿态实时打印到终端,方便你确认指令是否生效。
闭环控制:实时读取机器人运动状态
只发指令不读状态,就像"闭着眼开车"。unitree_ros2 把机器人状态也做成了标准 ROS2 话题,常用的是:
/sportmodestate(unitree_go::msg::SportModeState):位置、速度、IMU 姿态、步态类型(trot/run)、足端位置与速度、当前运动模式(idle/locomotion/lieDown/sit/frontFlip 等);/lowstate:电机位置/速度/扭矩、电池、足端受力等底层状态;/wirelesscontroller:遥控器摇杆与按键状态,适合做手动遥控。
完整的状态读取示例是 read_motion_state.cpp,运行后会持续输出:
Position -- x: 0.567083; y: 0.213920; z: 0.052338; body height: 0.320000
Velocity -- vx: -0.008966; vy: -0.001431; ...
Gait state -- gait type: 1; raise height: 0.090000
消息字段定义可以直接看 SportModeState。把"SportClient 发指令 + 订阅 sportmodestate 收状态"组合起来,就构成了完整的闭环控制框架——这正是大多数 Go2 应用(遥控、导航、动作编排)的标准玩法。
用 RViz2 可视化 Unitree 机器人数据
想"眼见为实"?项目文档演示了如何用 RViz2 可视化 Go2 的雷达数据:
ros2 topic list找到点云话题/utlidar/cloud;ros2 topic echo --no-arr /utlidar/cloud确认frame_id为utlidar_lidar;- 启动
ros2 run rviz2 rviz2,添加 PointCloud2 显示,把 Fixed Frame 改为utlidar_lidar,即可看到机器人周围环境的实时点云。
总结:新手上手路线
- 认识机制:SportClient = 一组
api_id+ 一条发布到/api/sport/request的 DDS 消息,请求/响应机制让它像调用函数一样简单; - 跑通示例:
go2_sport_client一个参数切换 11 种动作,是理解整套流程的最佳起点; - 建立闭环:订阅
sportmodestate拿到实时位姿,再叠加 RViz2 可视化,调试效率倍增; - 进阶方向:想要自定义步态或全身控制,可以继续探索 low_level_ctrl.cpp 等底层控制示例。
所有示例的目标名与构建规则集中在 CMakeLists.txt,版本历史可参考 CHANGELOG.md。动手试试吧,让你的 Go2 也来一个帅气的后空翻 🎉


