2、正运动学求解:基于DH参数的连杆变换推导、MATLAB/Python符号计算实现

正运动学,说白了就是:给定关节角度,算出末端位姿

我刚开始接触机器人时,觉得这玩意儿挺玄乎。后来做项目多了才发现,它其实就是一串矩阵乘法。你给每个关节一个变换矩阵,乘起来就完了。嗯,道理是这么个道理,但真正落地时,坑也不少。

2.1 DH参数:机器人建模的“通用语言”

DH参数法,全称Denavit-Hartenberg参数法。它用四个参数来描述相邻两个连杆之间的相对位置和姿态。

我个人习惯把DH参数分成两类:

  • 标准DH(Standard DH):坐标系建在连杆的前一个关节上。用得最多,但容易搞混。
  • 改进DH(Modified DH):坐标系建在连杆的后一个关节上。我个人觉得更直观,尤其在处理树形结构时。

不管哪种,四个参数都是:

参数 符号 含义
连杆长度 ai-1 沿Xi-1轴,从Zi-1到Zi的距离
连杆扭角 αi-1 绕Xi-1轴,从Zi-1到Zi的转角
连杆偏距 di 沿Zi轴,从Xi-1到Xi的距离
关节转角 θi 绕Zi轴,从Xi-1到Xi的转角
我的小技巧: 画图时,先把Z轴画出来(关节轴线方向),再画X轴(公垂线方向)。Y轴用右手定则补上。这样不容易乱。

2.2 连杆变换矩阵:从关节到末端的“传送带”

有了DH参数,相邻连杆的变换矩阵就是固定的。标准DH的变换矩阵长这样:

i-1T_i = Rot_x(α_{i-1}) · Trans_x(a_{i-1}) · Rot_z(θ_i) · Trans_z(d_i)

展开成4x4矩阵:

| cosθ_i   -sinθ_i   0     a_{i-1} |
| sinθ_i·cosα_{i-1}  cosθ_i·cosα_{i-1}  -sinα_{i-1}  -d_i·sinα_{i-1} |
| sinθ_i·sinα_{i-1}  cosθ_i·sinα_{i-1}   cosα_{i-1}   d_i·cosα_{i-1} |
| 0          0           0        1       |

你想想看,这个矩阵里只有θi是变量(旋转关节),其他都是常数。所以正运动学本质上就是:把每个关节的θi代进去,然后连乘

注意: 矩阵乘法不满足交换律!顺序错了,结果全错。我曾经在调试一个六轴机器人时,把第3和第4关节的变换顺序搞反了,末端位置差了十几厘米。查了整整两天才找到问题。

2.3 符号计算:让MATLAB和Python帮你干活

手算6个关节的矩阵乘法?别傻了。我建议你用符号计算工具。

2.3.1 MATLAB实现

MATLAB的Symbolic Math Toolbox很好用。我个人习惯用syms定义符号变量,然后用simplify化简。

% 定义符号变量
syms theta1 theta2 theta3 theta4 theta5 theta6
syms a1 a2 a3 a4 a5 a6 d1 d2 d3 d4 d5 d6 alpha1 alpha2 alpha3 alpha4 alpha5 alpha6

% 定义DH变换函数
function T = dh_transform(a, alpha, d, theta)
    T = [cos(theta), -sin(theta)*cos(alpha),  sin(theta)*sin(alpha), a*cos(theta);
         sin(theta),  cos(theta)*cos(alpha), -cos(theta)*sin(alpha), a*sin(theta);
         0,           sin(alpha),             cos(alpha),            d;
         0,           0,                      0,                     1];
end

% 计算各连杆变换
T01 = dh_transform(a1, alpha1, d1, theta1);
T12 = dh_transform(a2, alpha2, d2, theta2);
T23 = dh_transform(a3, alpha3, d3, theta3);
T34 = dh_transform(a4, alpha4, d4, theta4);
T45 = dh_transform(a5, alpha5, d5, theta5);
T56 = dh_transform(a6, alpha6, d6, theta6);

% 正运动学:末端位姿
T06 = T01 * T12 * T23 * T34 * T45 * T56;
T06_simplified = simplify(T06);

% 提取位置和姿态
position = T06_simplified(1:3, 4);
rotation = T06_simplified(1:3, 1:3);
关键点:simplify化简后,表达式会短很多。但有时候化简过头反而看不懂,我一般会保留中间结果,方便调试。

2.3.2 Python实现

Python里我用SymPy库。语法和MATLAB很像,但更灵活。

import sympy as sp

# 定义符号变量
theta1, theta2, theta3 = sp.symbols('theta1 theta2 theta3')
a1, a2, a3 = sp.symbols('a1 a2 a3')
d1, d2, d3 = sp.symbols('d1 d2 d3')
alpha1, alpha2, alpha3 = sp.symbols('alpha1 alpha2 alpha3')

def dh_transform(a, alpha, d, theta):
    return sp.Matrix([
        [sp.cos(theta), -sp.sin(theta)*sp.cos(alpha),  sp.sin(theta)*sp.sin(alpha), a*sp.cos(theta)],
        [sp.sin(theta),  sp.cos(theta)*sp.cos(alpha), -sp.cos(theta)*sp.sin(alpha), a*sp.sin(theta)],
        [0,              sp.sin(alpha),                 sp.cos(alpha),              d],
        [0,              0,                             0,                          1]
    ])

# 计算变换矩阵
T01 = dh_transform(a1, alpha1, d1, theta1)
T12 = dh_transform(a2, alpha2, d2, theta2)
T23 = dh_transform(a3, alpha3, d3, theta3)

# 正运动学
T03 = T01 * T12 * T23
sp.simplify(T03)
避坑指南: 我曾经用Python算一个7自由度机器人的正运动学,结果表达式长达几十页。后来发现是没做trigsimp(三角化简)。加上之后,表达式缩到了半页。记住:符号计算一定要化简

2.4 实战:一个六轴机器人的正运动学

拿一个典型的六轴工业机器人举例。它的DH参数表如下:

关节i ai-1 (mm) αi-1 (rad) di (mm) θi (变量)
1 0 0 400 θ1
2 250 -π/2 0 θ2
3 900 0 0 θ3
4 150 -π/2 900 θ4
5 0 π/2 0 θ5
6 0 -π/2 200 θ6

代入符号计算,得到末端位置:

px = cos(θ1)*(a2*cos(θ2) + a3*cos(θ2+θ3) + d4*sin(θ2+θ3) + d6*(sin(θ5)*sin(θ2+θ3) + cos(θ5)*cos(θ2+θ3)*cos(θ4)))
py = sin(θ1)*(a2*cos(θ2) + a3*cos(θ2+θ3) + d4*sin(θ2+θ3) + d6*(sin(θ5)*sin(θ2+θ3) + cos(θ5)*cos(θ2+θ3)*cos(θ4)))
pz = d1 - a2*sin(θ2) - a3*sin(θ2+θ3) + d4*cos(θ2+θ3) + d6*(sin(θ5)*cos(θ2+θ3) - cos(θ5)*sin(θ2+θ3)*cos(θ4))

看着挺长,对吧?但这就是正运动学的核心。你给一组关节角度,就能算出末端位置。

我的经验: 实际项目中,我不会每次都从头算符号表达式。我会把符号计算的结果保存成函数,然后直接调用。这样既快又不容易出错。

2.5 验证:用数值算例检查

算完了怎么知道对不对?拿一组已知的关节角度,手算一个简单情况来验证。

比如,让所有关节角度为0:

θ1=0, θ2=0, θ3=0, θ4=0, θ5=0, θ6=0

代入上面的表达式,得到:

px = a2 + a3 + d6
py = 0
pz = d1 + d4

这个结果符合直觉:机器人完全伸直,末端在X轴正方向,Z轴高度为d1+d4。

注意: 如果验证结果不对,先检查DH参数表。我遇到过好几次,参数表抄错了,导致后面全白算。记住:Garbage in, garbage out

2.6 总结

正运动学不难,就是矩阵乘法。但要做好,得注意三点:

  • DH参数要准:画图、标参数、反复核对。
  • 符号计算要化简:不然表达式长得吓人。
  • 数值验证不能省:一组简单的关节角度,手算验证。

下一章,我们聊逆运动学。那才是真正让人头疼的地方。不过别担心,先把正运动学吃透,后面就好办了。