4、运动学基础(二):正运动学建模与逆运动学求解

好,咱们接着聊运动学。上一章我把坐标变换和旋转矩阵的底子给你打好了,这一章咱们直接上硬菜——正运动学建模和逆运动学求解。说白了,就是回答两个问题:“我的腿现在到底在哪儿?” 和 “我想让脚踩到那个点,关节得转多少度?”

这两个问题搞不定,人形机器人别说走路了,站都站不稳。我当年刚入行时,在仿真里把一条腿拧成了麻花,就是因为正运动学算错了符号。嗯,咱们今天就把这个坑填平。

4.1 正运动学建模:D-H 参数法

正运动学,就是已知关节角度,求末端位姿。对于人形机器人的腿部,我们通常把每条腿看作一个开链机构,从髋关节到脚底。

我个人习惯用 改进型 D-H 参数法(也叫 Craig 版本)。为啥?因为它的坐标系定义更直观,尤其适合树形结构的人形机器人。

4.1.1 D-H 参数的四个核心量

每个关节连杆,只需要四个参数就能唯一确定坐标系变换关系:

参数 符号 物理含义 我的经验
连杆长度 ai-1 沿 Xi-1 轴,从 Zi-1 到 Zi 的距离 大腿/小腿长度,直接量机械图纸
连杆扭角 αi-1 绕 Xi-1 轴,从 Zi-1 到 Zi 的转角 髋关节偏置角,最容易搞错符号
连杆偏距 di 沿 Zi 轴,从 Xi-1 到 Xi 的距离 髋关节宽度,左右腿对称但符号相反
关节角 θi 绕 Zi 轴,从 Xi-1 到 Xi 的转角 就是我们控制的电机角度
小技巧: 我每次建完模型,都会先让所有关节归零,看看末端是不是在预期的初始位置。如果差得远,八成是扭角 α 的符号反了。

4.1.2 人形机器人腿部 D-H 建模实例

以常见的 6-DOF 腿部为例(髋关节 3 个 + 膝关节 1 个 + 踝关节 2 个),我习惯把坐标系这样安排:

  • 基坐标系 {0}:骨盆中心,Z 轴向上
  • 髋关节 {1}~{3}:分别对应髋关节的偏航、俯仰、翻滚
  • 膝关节 {4}:只有一个俯仰自由度
  • 踝关节 {5}~{6}:俯仰 + 翻滚
  • 末端坐标系 {7}:脚底中心

对应的 D-H 参数表大概长这样(以左腿为例):

i ai-1 αi-1 di θi
1 0 0 Lhip_width θ1
2 0 -90° 0 θ2 - 90°
3 0 90° Lthigh θ3
4 0 -90° 0 θ4
5 0 90° Lshank θ5
6 0 -90° 0 θ6

有了这张表,你只需要把每个连杆的变换矩阵 i-1Ti 连乘起来,就能得到脚底相对于骨盆的位姿了。代码实现也很直接:

// 改进型 D-H 变换矩阵
Eigen::Matrix4f dh_transform(float a, float alpha, float d, float theta) {
    Eigen::Matrix4f T;
    T <<  cos(theta),       -sin(theta),       0,          a,
            sin(theta)*cos(alpha),  cos(theta)*cos(alpha), -sin(alpha), -d*sin(alpha),
            sin(theta)*sin(alpha),  cos(theta)*sin(alpha),  cos(alpha),  d*cos(alpha),
            0, 0, 0, 1;
    return T;
}

// 正运动学:6个关节角 -> 脚底位姿
Eigen::Matrix4f forward_kinematics(const float q[6]) {
    Eigen::Matrix4f T = Eigen::Matrix4f::Identity();
    // 依次乘上每个关节的变换
    T = T * dh_transform(0, 0, L_hip_width, q[0]);
    T = T * dh_transform(0, -M_PI/2, 0, q[1] - M_PI/2);
    // ... 后续关节
    return T;
}
注意: 人形机器人左右腿的 D-H 参数不是完全对称的!右腿的髋关节偏距 d1 是负值,扭角符号也可能需要取反。我见过有人直接复制左腿参数给右腿,结果机器人原地劈叉。

4.2 逆运动学求解:解析法与数值法

正运动学是“给角度求位置”,逆运动学反过来——“给脚底目标位姿,求六个关节角”。这才是真正头疼的地方。

为什么头疼?因为逆运动学通常有多解、无解、甚至奇异解。你想想看,一个点在空中,我的腿可以弯着膝盖够到,也可以伸直了够到,到底选哪个?

4.2.1 解析法(几何法)

对于人形机器人腿部这种 6-DOF 且满足 Pieper 准则(相邻三个关节轴交于一点)的结构,解析法是首选。速度快,精度高,适合实时控制。

我一般把腿部逆解拆成两步:

  1. 位置解耦:先根据脚底位置,解出髋关节和膝关节的角度(决定脚在哪儿)
  2. 姿态解耦:再根据脚底姿态,解出踝关节的角度(决定脚掌朝向)

以膝关节为例,已知大腿长度 L1、小腿长度 L2,以及髋关节到脚底的直线距离 d,膝关节角度 θknee 可以用余弦定理直接算:

// 几何法求膝关节角度
float solve_knee_angle(float d) {
    // 余弦定理:d^2 = L1^2 + L2^2 - 2*L1*L2*cos(pi - theta_knee)
    float cos_theta = (L1*L1 + L2*L2 - d*d) / (2*L1*L2);
    // 防止数值误差导致 acos 越界
    cos_theta = std::clamp(cos_theta, -1.0f, 1.0f);
    return M_PI - acos(cos_theta);
}
解析法的优势: 计算量极小,一个周期内可以跑几千次。我在实际项目中,解析法单次求解耗时不到 5 微秒,而数值法至少 50 微秒起步。

4.2.2 数值法(迭代法)

如果机器人腿部的结构不满足 Pieper 准则(比如髋关节有特殊偏置),或者你需要考虑关节限位、避障等约束,那就得上数值法了。

最常用的是 雅可比矩阵的伪逆法(也叫 DLS,阻尼最小二乘法)。核心思路是:

  • 先给一组初始关节角
  • 计算当前末端位姿与目标位姿的误差
  • 用雅可比矩阵的伪逆,把误差映射回关节空间
  • 迭代直到误差收敛

代码骨架大概这样:

// 数值法逆运动学(伪逆法)
bool inverse_kinematics_numerical(
    const Eigen::Matrix4f& T_target,
    float q_init[6], float q_out[6]) {
    
    float q[6] = {q_init[0], q_init[1], ...};
    for (int iter = 0; iter < 100; iter++) {
        // 1. 正运动学求当前位姿
        Eigen::Matrix4f T_curr = forward_kinematics(q);
        
        // 2. 计算位姿误差(位置 + 姿态)
        Eigen::VectorXf error = compute_error(T_target, T_curr);
        if (error.norm() < 1e-6) break;
        
        // 3. 计算雅可比矩阵
        Eigen::MatrixXf J = compute_jacobian(q);
        
        // 4. 伪逆迭代:dq = J^+ * error
        Eigen::MatrixXf J_pinv = J.completeOrthogonalDecomposition().pseudoInverse();
        Eigen::VectorXf dq = J_pinv * error;
        
        // 5. 更新关节角
        for (int j = 0; j < 6; j++) q[j] += dq[j];
    }
    // 输出结果
    memcpy(q_out, q, 6 * sizeof(float));
    return true;
}
避坑指南: 数值法在奇异位形附近会“抽风”——雅可比矩阵接近奇异,伪逆算出来的关节速度会非常大。我曾经在调试时没加阻尼项,结果仿真里的机器人腿直接飞出去了。一定要加 DLS 阻尼,或者用 SVD 分解截断小奇异值。

4.3 人形机器人腿部运动学特点

跟工业机械臂不同,人形机器人的腿部运动学有几个特别的地方,我单独拎出来说说。

4.3.1 闭链约束

人形机器人走路时,两条腿和地面构成了一个 闭链。一条腿摆动时,另一条腿必须支撑。这意味着你不能独立解每条腿的逆运动学,必须考虑躯干的位姿变化。

我的做法是:先固定支撑腿的脚底,解出躯干的运动轨迹,再反过来解摆动腿的关节角。这叫 “支撑腿优先” 策略。

4.3.2 奇异位形规避

人形机器人最怕两种奇异:

  • 膝关节打直:腿完全伸直时,膝关节失去一个自由度,踝关节很难补偿
  • 髋关节内收极限:两条腿交叉时,髋关节容易卡住

我一般在逆运动学求解后,加一个 关节限位检查 和 可操作度(manipulability)计算。如果可操作度低于阈值,就调整步态参数,避免进入奇异区域。

4.3.3 足底姿态约束

人形机器人的脚底必须 始终与地面平行或按规划角度接触。你不能让脚掌在空中乱转。所以逆运动学求解时,脚底的翻滚角和俯仰角通常是固定的(或者按步态规划变化)。

这其实降低了逆运动学的难度——6 个自由度里,脚底姿态占了 3 个,剩下 3 个位置自由度刚好对应髋关节和膝关节的 3 个主要驱动关节。

4.4 本章小结

正运动学是基础,D-H 参数法是标准工具,建好模型后一劳永逸。逆运动学是实战,解析法快但适用范围窄,数值法灵活但要注意奇异和收敛问题。

我个人建议:能用解析法就用解析法,实在搞不定再上数值法。毕竟在机器人控制里,实时性就是生命线。下一章咱们会把这些运动学知识用到实际的步态规划里去,到时候你就知道今天这些推导有多重要了。

第4章 运动学基础(二)知识体系 腿部运动学 正运动学(D-H法) 4参数:a, α, d, θ 6-DOF腿部建模实例 变换矩阵连乘 → 末端位姿 逆运动学求解 解析法 数值法 几何解耦 雅可比伪逆 快速、精确 灵活、通用 人形机器人腿部运动学特点 闭链约束 奇异位形规避 足底姿态约束 核心:关节角 ↔ 末端位姿