3. 正运动学:D-H参数法建模与连杆坐标系建立

正运动学,说白了就是:给定六个关节角度,算出末端在空间的位置和姿态。这是机器人控制的"基本功",也是后面做轨迹规划、动力学分析的基础。

我个人习惯用D-H参数法来做这件事。为什么?因为它把复杂的空间几何问题,变成了四个参数的矩阵连乘。你想想看,一个六轴机械臂,六个关节,每个关节四个参数,总共24个参数就能完整描述整个臂的几何关系——这比用欧拉角硬算要优雅得多。

3.1 连杆坐标系建立规则

先说说坐标系怎么建。我记得刚入行时,师傅跟我说:"坐标系建对了,后面全是矩阵乘法;建错了,调试三天都找不出问题。"这话一点不假。

D-H法建立连杆坐标系,有四个核心规则:

  1. Z轴:沿着关节轴线方向。旋转关节就是旋转轴,移动关节就是移动方向。
  2. X轴:沿着相邻两Z轴的公垂线,从当前关节指向下一个关节。
  3. Y轴:由右手定则确定,Z×X得到Y。
  4. 原点:Z轴与公垂线的交点。

关键点:坐标系{i}固定在连杆i上,随连杆i一起运动。坐标系{i}的原点位于关节i+1的轴线上。

嗯,这里要注意一个容易混淆的地方:坐标系编号和关节编号是错位的。关节i连接连杆i-1和连杆i,而坐标系{i}是固定在连杆i上的。我刚开始学的时候,这个错位让我画图画错了好几次。

3.2 D-H四参数定义

有了坐标系,接下来就是四个参数。每个参数都有明确的几何意义:

参数 符号 物理含义 我的理解
连杆长度 ai Zi到Zi+1沿Xi的距离 说白了就是"杆子有多长"
连杆扭角 αi Zi到Zi+1绕Xi的转角 "杆子拧了多少度"
关节距离 di Xi-1到Xi沿Zi的距离 "关节之间的偏置"
关节转角 θi Xi-1到Xi绕Zi的转角 "关节转了多少度"

对于旋转关节,θi是变量,其他三个是常量。对于移动关节,di是变量。六轴机械臂通常全是旋转关节,所以只有θ1到θ6是变量。

我的经验:参数a和α描述的是"杆子本身的几何",而d和θ描述的是"关节连接关系"。把这两个概念分开,参数就不容易搞混。

3.3 六轴机械臂D-H参数表

以典型的六轴工业机械臂为例(比如常见的ER系列),D-H参数表长这样:

关节i ai (mm) αi (°) di (mm) θi (°)
1 0 0 d1 θ1
2 a2 -90 0 θ2
3 a3 0 0 θ3
4 0 -90 d4 θ4
5 0 90 0 θ5
6 0 -90 d6 θ6

注意看,关节1的a1=0,α1=0,说明基座到第一个关节没有偏置。关节2的α2=-90°,表示第二个关节轴线相对于第一个关节扭转了90度——这就是为什么大多数六轴臂的"肩膀"是弯的。

避坑指南:我曾经在项目里把α的正负号搞反了,结果仿真时机械臂末端轨迹完全不对。后来花了整整一天排查,才发现是符号问题。记住:α的正负由右手定则决定,绕X轴逆时针为正。

3.4 正运动学方程推导

有了参数表,接下来就是矩阵连乘。每个关节对应一个齐次变换矩阵:

T_i = Rot(z, θ_i) * Trans(z, d_i) * Trans(x, a_i) * Rot(x, α_i)

展开成4×4矩阵形式:

T_i = [cosθ_i   -sinθ_i·cosα_i    sinθ_i·sinα_i    a_i·cosθ_i]
      [sinθ_i    cosθ_i·cosα_i   -cosθ_i·sinα_i    a_i·sinθ_i]
      [0         sinα_i           cosα_i            d_i       ]
      [0         0                0                 1         ]

这个矩阵就是相邻两个坐标系之间的变换关系。从基座到末端,总共六个矩阵连乘:

T_06 = T_01 * T_12 * T_23 * T_34 * T_45 * T_56

结果是一个4×4的齐次变换矩阵:

T_06 = [R_06    P_06]
       [0 0 0   1   ]

其中R_06是3×3的旋转矩阵,表示末端的姿态;P_06是3×1的位置向量,表示末端在基坐标系下的坐标。

你想想看,六个矩阵连乘,每个矩阵里都是sin和cos的组合,展开后会有几十项。手算?不现实。我一般用MATLAB的符号工具箱或者Python的SymPy来做符号推导,然后生成C代码烧到控制器里。

3.5 正运动学计算流程

实际工程中,正运动学的计算流程是这样的:

  1. 输入:六个关节角度θ1~θ6
  2. 查表:从D-H参数表中取出对应的ai、αi、di
  3. 构造矩阵:对每个关节,代入θi计算Ti-1,i
  4. 连乘:T_06 = T_01 × T_12 × T_23 × T_34 × T_45 × T_56
  5. 输出:从T_06中提取位置P_06和姿态R_06

工程实现要点:

  • 矩阵乘法用循环实现,不要手写6次乘法——容易出错且不好维护
  • sin/cos计算用查表或快速近似,减少实时计算开销
  • 结果矩阵的最后一列前三个元素就是末端位置,单位与D-H参数一致

3.6 正运动学验证

写完代码怎么验证对不对?我有个习惯:先做零位验证。把所有关节角度设为零,看末端位置是不是在机械臂的"零位姿态"。

比如,对于上面那张参数表,当所有θ=0时:

  • 关节1和关节2的轴线共面
  • 关节3水平伸出
  • 关节4、5、6形成一条直线

末端位置应该是:Px = a2 + a3 + d6,Py = 0,Pz = d1 - d4。如果算出来不对,那肯定是参数或者矩阵写错了。

我的调试技巧:先只算前三个关节(位置部分),验证末端位置对不对。位置对了再算后三个关节(姿态部分)。分步验证,问题定位快得多。

3.7 正运动学知识体系

下面这张图总结了正运动学的核心逻辑:

正运动学知识体系 输入:6个关节角度 核心:D-H参数表 + 矩阵连乘 D-H参数 矩阵连乘 输出:末端位姿矩阵 T_06 分解:位置 + 姿态 位置 (Px,Py,Pz) 姿态 (R 矩阵) 轨迹规划输入 逆运动学验证 正运动学是机器人控制的"正向通道" 所有控制算法都依赖它提供准确的末端位姿

从这张图可以看得很清楚:正运动学就是一条从"关节角度"到"末端位姿"的单向通道。输入是六个角度,经过D-H参数和矩阵连乘,输出位置和姿态。这个通道是确定的、唯一的——给定一组关节角度,末端位姿是唯一确定的。

这也是为什么正运动学比逆运动学简单。逆运动学可能有多个解、甚至无解,但正运动学永远只有一个答案。嗯,这就是它的"确定性"优势。

3.8 代码实现示例

最后,给出一段Python代码,实现六轴机械臂的正运动学计算。这段代码我在好几个项目里复用过,稍微改改参数表就能用:

import numpy as np

def dh_transform(a, alpha, d, theta):
    """计算单个关节的D-H变换矩阵"""
    ct = np.cos(theta)
    st = np.sin(theta)
    ca = np.cos(alpha)
    sa = np.sin(alpha)
    
    T = np.array([
        [ct, -st*ca,  st*sa,  a*ct],
        [st,  ct*ca, -ct*sa,  a*st],
        [0,   sa,     ca,     d   ],
        [0,   0,      0,      1   ]
    ])
    return T

def forward_kinematics(joint_angles, dh_params):
    """
    正运动学计算
    joint_angles: [θ1, θ2, θ3, θ4, θ5, θ6]
    dh_params: [[a1, α1, d1], [a2, α2, d2], ...]
    """
    T = np.eye(4)
    for i in range(6):
        a, alpha, d = dh_params[i]
        theta = joint_angles[i]
        T_i = dh_transform(a, alpha, d, theta)
        T = T @ T_i
    return T

# 示例:D-H参数表(a单位mm,α单位rad)
dh_params = [
    [0,   0,          d1],   # 关节1
    [a2,  -np.pi/2,   0 ],   # 关节2
    [a3,  0,          0 ],   # 关节3
    [0,   -np.pi/2,   d4],   # 关节4
    [0,   np.pi/2,    0 ],   # 关节5
    [0,   -np.pi/2,   d6]    # 关节6
]

# 零位验证
joints_zero = [0, 0, 0, 0, 0, 0]
T_06 = forward_kinematics(joints_zero, dh_params)
print("末端位置:", T_06[:3, 3])
print("末端姿态:\n", T_06[:3, :3])

这段代码的核心就两个函数:dh_transform构造单个关节的矩阵,forward_kinematics做连乘。你想想看,整个正运动学,本质上就是这么简单——24个参数,6次矩阵乘法,搞定。

但简单归简单,实际工程中坑不少。比如角度单位是弧度还是度?D-H参数是标准型还是改进型?这些细节不注意,算出来的结果就是错的。我建议你拿到一个机械臂,先用零位验证把代码跑通,再去做轨迹规划。