# Unitree H1_2 并联机构控制 [English](README.md) | 简体中文 ## 并联机构控制接口 Unitree H1_2 机器人并联机构涉及机器人的左右腿的脚踝。因左右脚踝对称,故下面以 H1_2 左脚踝关节为例:

硬件上,H1_2 左脚踝关节采用并联机构,包括四个关节: * 并联关节:A 关节、B 关节 * 串联关节:Pitch 关节 (简称 P 关节)、Roll 关节 (简称 R 关) 其中只有 A、B 关节是可被电机直接驱动的关节,P、R 关节不能被直接控制。而机器人 URDF 模型和运动控制算法通常只考虑 P、R 串联关节。为了实现对 P、R 关节的控制,我们通过控制 A、B 关节从而间接实现对 P、R 关节的控制。具体到软件上,我们为用户提供了等价的串联关节控制接口,即 `PR 模式`,让用户能直接控制 P、R 关节。与普通关节控制方法一样,`PR 模式` 下每个串联关节接收以下指令: | 指令名称 | 变量 | | ---------- | ----- | | 前馈力矩 | `tau` | | 目标角度 | `q` | | 目标角速度 | `dq` | | 关节刚度 | `kp` | | 关节阻尼 | `kd` | 最终串联关节执行总的力矩为 `T = kp * (q - q_m) + kd * (dq - dq_m) + tau`。为了提高串联关节控制精度,H1_2 机器人内部根据运动学和动力学关系,把 P、R 关节的前馈力矩、目标角度、目标角速度、关节刚度和关节阻尼指令转换为 A、B 实际关节执行单元。 ## 串联关节跟踪实验 为测试 H1_2 脚踝 `PR 模式` 控制效果,我们让脚踝 P、R 关节跟踪正弦曲线,参考[测试例程](https://github.com/unitreerobotics/unitree_sdk2/blob/main/example/h1/low_level/h1_2_ankle_track.cpp)。核心代码段如下: **启用 PR 模式并生成正弦曲线** ```c++ // [Stage 2]: swing ankle's PR mode_ = PR; // Enable PR mode // generate sin/cos trajectory double max_P = 0.25; // [rad] double max_R = 0.25; // [rad] double t = time_ - duration_; double L_P_des = max_P * std::cos(2.0 * M_PI * t); double L_R_des = max_R * std::sin(2.0 * M_PI * t); double R_P_des = max_P * std::cos(2.0 * M_PI * t); double R_R_des = -max_R * std::sin(2.0 * M_PI * t); ``` **设置踝关节指令** ```c++ // update ankle joint position targets float Kp_Pitch = 80; float Kd_Pitch = 1; float Kp_Roll = 80; float Kd_Roll = 1; dds_low_command.motor_cmd().at(4).q() = L_P_des; // 4: LeftAnklePitch dds_low_command.motor_cmd().at(4).dq() = 0; dds_low_command.motor_cmd().at(4).kp() = Kp_Pitch; dds_low_command.motor_cmd().at(4).kd() = Kd_Pitch; dds_low_command.motor_cmd().at(4).tau() = 0; dds_low_command.motor_cmd().at(5).q() = L_R_des; // 5: LeftAnkleRoll dds_low_command.motor_cmd().at(5).dq() = 0; dds_low_command.motor_cmd().at(5).kp() = Kp_Roll; dds_low_command.motor_cmd().at(5).kd() = Kd_Roll; dds_low_command.motor_cmd().at(5).tau() = 0; dds_low_command.motor_cmd().at(10).q() = R_P_des; // 10: RightAnklePitch dds_low_command.motor_cmd().at(10).dq() = 0; dds_low_command.motor_cmd().at(10).kp() = Kp_Pitch; dds_low_command.motor_cmd().at(10).kd() = Kd_Pitch; dds_low_command.motor_cmd().at(10).tau() = 0; dds_low_command.motor_cmd().at(11).q() = R_R_des; // 11: RightAnkleRoll dds_low_command.motor_cmd().at(11).dq() = 0; dds_low_command.motor_cmd().at(11).kp() = Kp_Roll; dds_low_command.motor_cmd().at(11).kd() = Kd_Roll; dds_low_command.motor_cmd().at(11).tau() = 0; ``` **打印期望值和测量值到终端** ```c++ float L_P_m = low_state_.motor_state().at(4).q(); float L_R_m = low_state_.motor_state().at(5).q(); float R_P_m = low_state_.motor_state().at(10).q(); float R_R_m = low_state_.motor_state().at(11).q(); printf("%f,%f,%f,%f,%f,%f,%f,%f\n", L_P_des, L_P_m, L_R_des, L_R_m, R_P_des, R_P_m, R_R_des, R_R_m); ``` | L_P_des | L_P_m | L_R_des | L_R_m | R_P_des | R_P_m | R_R_des | R_R_m | | ----------------- | ----------------- | ---------------- | ---------------- | ----------------- | ----------------- | ---------------- | ---------------- | | 左脚 Pitch 期望值 | 左脚 Pitch 测量值 | 左脚 Roll 期望值 | 左脚 Roll 测量值 | 右脚 Pitch 期望值 | 右脚 Pitch 测量值 | 右脚 Roll 期望值 | 右脚 Roll 测量值 | 安装并编译 [unitree_sdk2](https://github.com/unitreerobotics/unitree_sdk2),务必先把机器人**悬挂起来**,然后终端运行测试例程: ```bash h1_2_ankle_track network_interface ``` 启动后,机器人会先恢复到零位,然后周期性摆动脚踝,并打印左右踝关节期望值和测量值,其位置跟踪效果如图:

图中符号定义: * `L_Pitch_d`:左脚踝 P 关节期望值 * `L_Pitch_m`:左脚踝 P 关节测量值 * `L_Roll_d`:左脚踝 R 关节期望值 * `L_Roll_m`:左脚踝 R 关节测量值 左图表示串联 Pitch、Roll 关节能较准确地跟踪正弦曲线目标位置指令;右图表示串联关节在相空间中的跟踪效果。