Unitree Go2高层运动控制:接口实战与代码指南
Go2的高层运动控制基于Unitree SDK2构建,通过C++例程封装了各类运动接口,开发者可通过修改配置参数或二次开发,实现对机器人的精细化运动控制。其核心设计逻辑是:通过枚举test_mode指定运动模式,由对象调用SDK接口执行动作,同时通过回调函数实时获取机器人运动状态,形成"指令下发-状态反馈"的闭环控制。Unitree Go2的高层运动控制接口通过SDK2封装了丰富的运动功能,兼具易
在四足机器人开发中,高层运动控制是实现灵活动作与自主移动的核心环节。Unitree Go2机器人基于SDK2提供了丰富的高层运动控制接口,涵盖基础姿态控制、速度控制、轨迹跟踪及特色动作执行等功能,为开发者提供了便捷的二次开发入口。本文将从运动模式分类、例程结构、代码解析、实战操作等维度,全方位拆解Go2高层运动控制的技术细节,助力开发者快速实现机器人运动功能定制。
一、高层运动控制概述:核心定位与适用场景
1. 核心架构
Go2的高层运动控制基于Unitree SDK2构建,通过C++例程封装了各类运动接口,开发者可通过修改配置参数或二次开发,实现对机器人的精细化运动控制。其核心设计逻辑是:通过枚举test_mode指定运动模式,由sport_client对象调用SDK接口执行动作,同时通过回调函数实时获取机器人运动状态,形成"指令下发-状态反馈"的闭环控制。
2. 适用场景
该套控制接口适用于教育科研、机器人演示、动作编程等场景,支持基础运动调试、特殊动作编排、轨迹跟踪等开发需求。使用前需注意:
- 场地要求:执行运动(尤其是特殊动作)时需保证场地空旷,无障碍物干扰
- 操作前提:需通过遥控器让Go2进入运动模式,避免硬件冲突
- 开发环境:需安装Unitree SDK2,支持C++编译环境(兼容ROS生态)
二、运动模式全解析:基础运动与特殊动作
Go2的高层运动模式分为基础运动控制和特殊动作两大类,共包含19种具体模式,通过枚举test_mode定义,开发者可修改TEST_MODE变量指定运行模式。
1. 基础运动控制:核心功能与参数说明
基础运动涵盖机器人核心姿态与移动控制,支持持续运行或状态切换,是机器人运动的基础能力。
| 运动模式 | 功能说明 | 关键参数/特性 |
|---|---|---|
| normal_stand | 正常站立 | 关节锁定,保持固定站高,为默认基础状态 |
| balance_stand | 平衡站立 | 站立时维持机体姿态平衡,支持欧拉角与机身高度调节 |
| velocity_move | 速度控制 | 按指定x、y、yaw速度移动,参考坐标系为机体坐标系 |
| trajectory_follow | 轨迹跟踪控制 | 跟踪预设参考轨迹,参考坐标系为绝对坐标系(程序启动位置为原点) |
| stand_down | 趴下 | 关节锁定,机体贴合地面 |
| stand_up | 站高 | 关节锁定,提升机体高度至默认值(0.33m) |
| damp | 阻尼模式 | 所有电机进入阻尼状态,优先级最高,相当于"软急停" |
| recovery_stand | 恢复站立 | 从翻倒或趴下状态自动恢复至站立状态 |
| stop_move | 停止运动 | 终止所有当前执行的运动指令,回归 idle 状态 |
关键参数限制(平衡站立模式):
- 欧拉角范围:roll(横滚)[-0.75, 0.75]、pitch(俯仰)[-0.75, 0.75]、yaw(偏航)[-0.6, 0.6](单位:rad)
- 机身高度:相对于默认状态(0.33m)的调节范围为[-0.18, 0.03](负值降低高度,正值升高高度)
2. 特殊动作:特色功能与执行规则
特殊动作是Go2的亮点功能,涵盖仿生动作、互动动作等,需注意:所有特殊动作在短时间内仅能执行一次,需通过标志位flag控制执行状态。
| 特殊动作 | 功能说明 | 执行特性 |
|---|---|---|
| sit | 坐下 | 仿生坐姿,执行后维持该姿态 |
| rise_sit | 坐姿恢复 | 从坐下状态恢复至之前的运动状态 |
| stretch | 伸懒腰 | 机体舒展动作,增强互动性 |
| wallow | 打滚 | 机身绕轴线翻滚,需足够场地空间 |
| content | 开心 | 仿生开心动作(如摆尾、机身晃动) |
| pose | 摆姿势 | 预设造型动作,参数true指定动作类型 |
| scrape | 拜年作揖 | 仿生作揖动作,适用于演示场景 |
| front_flip | 前空翻 | 高危动作,需确保场地空旷无遮挡 |
| front_jump | 前跳 | 向前短距离跳跃,跳跃高度与距离固定 |
| front_pounce | 向前扑人 | 仿生扑击动作,移动速度较快 |
三、例程快速上手:环境准备与编译运行
1. 核心文件与依赖
- 例程路径:
unitree_sdk2/example/go2/go2_sport_client.cpp - 依赖环境:Unitree SDK2(需提前安装配置)、C++编译器(支持C++11及以上)、CMake构建工具
2. 编译与运行步骤
(1)选择运动模式
修改例程中TEST_MODE变量,指定需测试的运动模式,例如测试速度控制:
const int TEST_MODE = velocity_move; // 枚举值对应目标运动模式
(2)编译例程
在SDK目录下执行编译指令:
# 进入例程目录(根据实际路径调整)
cd unitree_sdk2/example/go2
# 创建编译目录
mkdir build && cd build
# 构建工程
cmake ..
# 编译生成可执行文件
make
(3)运行测试程序
- 通过遥控器让Go2进入运动模式,放置于空旷场地
- 在终端执行运行指令(指定网卡名称,如
eth0或wlan0):./sportmode_test [网卡名称] - 程序启动后等待1秒(获取稳定初始状态),机器人将执行指定动作
- 按
Ctrl+C终止程序,机器人停止运动
四、核心代码解析:例程架构与控制逻辑
Go2高层运动控制例程的核心架构分为初始化模块、状态回调模块、运动控制模块和主程序模块,各模块协同实现运动指令的下发与状态反馈。
1. 初始化模块:Custom类构造函数
Custom类封装了运动控制的核心逻辑,构造函数完成sport_client初始化与状态订阅:
Custom()
{
// 初始化运动客户端,设置请求超时时间(10秒)
sport_client.SetTimeout(10.0f);
sport_client.Init();
// 订阅高层状态话题(TOPIC_HIGHSTATE),绑定回调函数获取机器人状态
suber.reset(new unitree::robot::ChannelSubscriber<unitree_go::msg::dds_::SportModeState_>(TOPIC_HIGHSTATE));
suber->InitChannel(std::bind(&Custom::HighStateHandler, this, std::placeholders::_1), 1);
};
2. 状态回调模块:实时获取运动状态
HighStateHandler为状态回调函数,实时接收机器人的运动状态数据(如位置、IMU信息)并存储到state变量,供控制逻辑调用:
void HighStateHandler(const void *message)
{
// 将接收的消息转换为运动状态类型
state = *(unitree_go::msg::dds_::SportModeState_ *)message;
// 打印位置信息(x, y, z)
std::cout << "Position: " << state.position()[0] << ", " << state.position()[1] << ", " << state.position()[2] << std::endl;
// 打印IMU欧拉角(roll, pitch, yaw)
std::cout << "IMU rpy: " << state.imu_state().rpy()[0] << ", " << state.imu_state().rpy()[1] << ", " << state.imu_state().rpy()[2] << std::endl;
};
3. 初始状态获取:统一坐标系原点
GetInitState函数获取程序启动时机器人的位置(px0, py0)和偏航角(yaw0),作为绝对坐标系的原点,确保轨迹跟踪等功能的准确性:
void GetInitState()
{
px0 = state.position()[0]; // 初始x坐标
py0 = state.position()[1]; // 初始y坐标
yaw0 = state.imu_state().rpy()[2]; // 初始偏航角
std::cout << "initial position: x0: " << px0 << ", y0: " << py0 << ", yaw0: " << yaw0 << std::endl;
};
4. 主程序流程:启动控制线程
主程序完成网卡初始化、等待状态稳定、启动运动控制线程,实现持续运动控制:
int main(int argc, char **argv)
{
// 检查参数(需传入网卡名称)
if (argc < 2)
{
std::cout << "Usage: " << argv[0] << " networkInterface" << std::endl;
exit(-1);
}
// 初始化通道工厂(指定网卡)
unitree::robot::ChannelFactory::Instance()->Init(0, argv[1]);
Custom custom;
sleep(1); // 等待1秒,获取稳定的初始状态
custom.GetInitState(); // 记录初始状态
// 创建循环线程,按固定周期(dt)调用RobotControl执行运动控制
unitree::common::ThreadPtr threadPtr = unitree::common::CreateRecurrentThread(custom.dt * 1000000, std::bind(&Custom::RobotControl, &custom));
// 保持程序运行
while (1)
{
sleep(10);
}
return 0;
}
五、关键运动模式实战:代码解析与参数配置
1. 基础运动:平衡站立与速度控制
(1)平衡站立(balance_stand)
支持欧拉角与机身高度调节,适用于姿态校准场景:
case balance_stand:
// 设置欧拉角(roll=0.1rad, pitch=0.2rad, yaw=0.3rad)
sport_client.Euler(0.1, 0.2, 0.3);
// 设置机身相对高度(0对应默认0.33m,可在[-0.18, 0.03]范围内调整)
sport_client.BodyHeight(0.0);
// 启动平衡站立
sport_client.BalanceStand();
break;
(2)速度控制(velocity_move)
按指定速度移动,参数分别为x轴速度、y轴速度、yaw角速度(机体坐标系):
case velocity_move:
// 示例:x轴速度0.3m/s,y轴速度0,yaw角速度0.3rad/s(顺时针旋转)
sport_client.Move(0.3, 0, 0.3);
break;
2. 高级运动:轨迹跟踪控制(trajectory_follow)
实现圆形轨迹跟踪,核心逻辑是生成局部坐标系下的圆轨迹点,转换为绝对坐标系后下发:
case trajectory_follow:
time_seg = 0.2; // 轨迹时间步长(0.2秒/点)
time_temp = ct - time_seg;
// 生成30个轨迹点(覆盖6秒轨迹)
for (int i = 0; i < 30; i++)
{
time_temp += time_seg;
// 局部坐标系(程序启动原点)下的圆轨迹参数
px_local = 0.5 * sin(0.5 * time_temp); // 圆半径0.5m
py_local = 0.5 * cos(0.5 * time_temp) - 1;
yaw_local = 0; // 偏航角保持0
// 局部速度参数
vx_local = 0.25 * cos(0.5 * time_temp);
vy_local = -0.25 * sin(0.5 * time_temp);
vyaw_local = 0;
// 转换为绝对坐标系(基于初始位置和偏航角)
path_point_tmp.timeFromStart = i * time_seg;
path_point_tmp.x = px_local * cos(yaw0) - py_local * sin(yaw0) + px0;
path_point_tmp.y = px_local * sin(yaw0) + py_local * cos(yaw0) + py0;
path_point_tmp.yaw = yaw_local + yaw0;
path_point_tmp.vx = vx_local * cos(yaw0) - vy_local * sin(yaw0);
path_point_tmp.vy = vx_local * sin(yaw0) + vy_local * cos(yaw0);
path_point_tmp.vyaw = vyaw_local;
path.push_back(path_point_tmp);
}
// 下发轨迹跟踪指令
sport_client.TrajectoryFollow(path);
break;
3. 特殊动作:前空翻与拜年作揖
特殊动作通过标志位flag控制单次执行,避免重复触发:
(1)前空翻(front_flip)
case front_flip:
if (flag == 0) // flag=0表示未执行过
{
sport_client.FrontFlip(); // 调用前空翻接口
flag = 1; // 置1锁定,避免重复执行
}
break;
(2)拜年作揖(scrape)
case scrape:
if (flag == 0)
{
sport_client.Scrape(); // 调用作揖接口
flag = 1;
}
break;
六、运动状态获取:关键参数与调用示例
通过state变量可获取机器人的实时运动状态,涵盖位置、姿态、速度、障碍物信息等,支持运动闭环控制与故障排查。
1. 核心状态参数
| 状态参数 | 数据类型 | 功能说明 |
|---|---|---|
| position() | std::array<float, 3> | 三维位置(x, y, z) |
| imu_state().rpy() | std::array<float, 3> | IMU欧拉角(roll, pitch, yaw) |
| mode() | uint8_t | 运动模式(0=idle, 1=balanceStand等,见文档枚举) |
| gaitType() | uint8_t | 步态类型(0=idle, 1=trot, 2=run等) |
| velocity() | std::array<float, 3> | 三维速度(x, y, z) |
| rangeObstacle() | std::array<float, 4> | 障碍物距离(四个方向) |
| footForce() | std::array<int16_t, 4> | 四足端力反馈 |
2. 状态调用示例
// 打印机器人当前位置
std::cout << "Current Position: " << custom.state.position()[0] << ", " << custom.state.position()[1] << std::endl;
// 打印当前运动模式(需映射为对应名称)
uint8_t currentMode = custom.state.mode();
std::cout << "Current Motion Mode: " << currentMode << std::endl;
// 打印障碍物距离(四个方向)
std::cout << "Obstacle Distance: " << custom.state.rangeObstacle()[0] << ", " << custom.state.rangeObstacle()[1] << std::endl;
七、注意事项与常见问题排查
1. 关键注意事项
- 安全第一:执行前空翻、打滚等动作时,必须确保场地空旷,避免机器人碰撞损坏
- 模式冲突:特殊动作单次执行后需重置
flag才能再次触发,否则无法重复运行 - 坐标系区分:速度控制基于机体坐标系,轨迹跟踪基于绝对坐标系,开发时需避免混淆
- 状态稳定:程序启动后需等待1秒获取初始状态,否则可能导致轨迹跟踪偏差
2. 常见问题排查
- 程序无法运行:检查网卡名称是否正确,SDK是否安装配置完成
- 机器人无响应:确认遥控器已切换至运动模式,场地是否满足动作执行要求
- 动作执行异常:检查
TEST_MODE枚举值是否正确,参数是否超出限制(如欧拉角范围) - 状态获取失败:排查话题订阅是否成功,回调函数是否绑定正确
总结
Unitree Go2的高层运动控制接口通过SDK2封装了丰富的运动功能,兼具易用性与灵活性,既支持新手快速上手测试预设动作,也为进阶开发者提供了二次开发的空间。本文通过对运动模式、例程架构、代码逻辑的深度解析,为开发者提供了完整的技术指南。
在实际开发中,建议先通过预设例程测试基础运动,熟悉坐标系与参数规则后,再进行轨迹跟踪或特殊动作的定制开发。同时,需重点关注运动安全与状态反馈,确保机器人运动的稳定性与可靠性。对于复杂场景的运动控制,可基于该接口扩展路径规划、障碍物避障等功能,进一步提升机器人的自主运动能力。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)