第四章:逆运动学——解析法与数值法的对决
逆运动学,说白了就是“已知手要抓到哪儿,算出每个关节该转多少度”。
这玩意儿是机器人控制里最让人头疼的环节之一。我当年刚入行时,花了两周时间死磕一个六轴臂的逆解,最后发现是坐标系建反了……嗯,从那以后我养成了一个习惯:先画坐标系,再写代码。
4.1 逆运动学到底难在哪?
正运动学很简单:给一组关节角,算出手爪的位姿。这是唯一解,闭着眼睛都能算。
但逆运动学不一样。同一个手爪位置,可能对应好几组关节角。甚至有些位置,压根儿就没有解。
举个例子:你让机械臂去抓桌子上的杯子,如果杯子离底座太远,臂长不够,那就无解。如果杯子在臂长范围内,可能有2种、4种甚至8种不同的“弯腰姿势”都能抓到。
这就是逆运动学的核心挑战:多解性和存在性。
核心要点:逆运动学不是“算一个数”,而是“在多个可行解中选一个最合理的”。
4.2 解析法 vs 数值法——两条路
解决逆运动学,主流有两条路:解析法和数值法。我两种都用过,各有各的脾气。
| 对比项 | 解析法 | 数值法 |
|---|---|---|
| 求解速度 | 极快(微秒级) | 较慢(毫秒级,迭代次数不定) |
| 精度 | 理论精确解 | 受迭代终止条件影响 |
| 适用条件 | 需要满足Pieper准则 | 通用,任意构型 |
| 多解处理 | 显式给出所有解 | 只能得到一个解(依赖初值) |
| 实现难度 | 数学推导复杂 | 编程简单,但调参麻烦 |
我个人习惯:能用解析法就用解析法。为什么?因为快、准、稳。数值法虽然通用,但迭代过程中可能发散,尤其当雅可比矩阵奇异时,直接崩给你看。
我的经验:在工业机器人上,90%以上的六轴臂都满足Pieper准则。所以解析法是首选。数值法更多用在冗余自由度或特殊构型上。
4.3 Pieper准则——解析法的“入场券”
Pieper准则是个啥?说白了就是:如果机器人的最后三个关节的轴线交于一点,或者最后三个关节都是旋转关节且轴线平行,那么逆运动学就有解析解。
为什么会这样?你想想看,最后三个关节交于一点,意味着手腕可以看作一个“球关节”。这样一来,前三个关节决定手腕中心的位置,后三个关节决定手腕的姿态。位置和姿态就解耦了。
我在项目中遇到过一台老式六轴臂,它的第四、五、六轴轴线并不严格交于一点,差了2毫米。结果用解析法算出来的逆解,末端精度总是差那么一点点。后来我改用数值法,才把精度调回来。所以,Pieper准则是一个理论条件,实际中要留点余量。
注意:如果机器人不满足Pieper准则,解析法基本不可行。这时候别硬上,老老实实用数值法。
4.4 腕部分离法——六轴臂逆解的标准套路
对于满足Pieper准则的六轴臂,最经典的解法就是腕部分离法。这个方法把六轴臂拆成两部分:
- 前三个关节(肩、大臂、小臂):决定手腕中心的位置
- 后三个关节(腕部):决定末端执行器的姿态
具体步骤是这样的:
- 求手腕中心位置:已知末端位姿矩阵 T,以及腕部偏移量 d6,可以算出腕部中心点 P_w = P - d6 * Z_axis
- 解前三个关节:根据 P_w 的位置,用几何法或代数法求出 θ1、θ2、θ3。这一步通常有2-4组解(比如“肘部向上”和“肘部向下”)
- 解后三个关节:已知前三个关节的角度,可以算出从基座到腕部的旋转矩阵 R_03。再结合末端姿态 R_06,就能求出腕部旋转矩阵 R_36 = R_03^T * R_06。然后从 R_36 中解出 θ4、θ5、θ6
- 筛选最优解:从所有可能的组合中,选一个最符合当前运动约束的解(比如关节限位、避障、最小能耗等)
下面这张图展示了腕部分离法的核心逻辑:
4.5 一个具体的例子:六轴臂逆解代码片段
下面是我写的一个简化版逆解函数,用Python实现。它假设机器人满足Pieper准则,且腕部偏移量已知。
import numpy as np
def inverse_kinematics(T, d6, a2, a3, d1, d4):
"""
六轴臂逆运动学(腕部分离法)
T: 4x4 末端位姿矩阵
d6: 腕部偏移量
a2, a3: 连杆长度
d1, d4: 连杆偏距
返回:所有可能的关节角组合(列表)
"""
# 1. 提取末端位置和姿态
R = T[:3, :3]
p = T[:3, 3]
# 2. 计算手腕中心位置
z_axis = R[:, 2] # 末端Z轴
pw = p - d6 * z_axis
# 3. 解 θ1(两个可能解)
theta1_candidates = []
r = np.sqrt(pw[0]**2 + pw[1]**2)
if r < 1e-6:
theta1_candidates = [0.0] # 奇异情况
else:
phi = np.arctan2(pw[1], pw[0])
theta1_candidates = [phi, phi + np.pi]
solutions = []
for theta1 in theta1_candidates:
# 4. 解 θ3(利用余弦定理)
x = pw[0]*np.cos(theta1) + pw[1]*np.sin(theta1) - a2
y = pw[2] - d1
D = (x**2 + y**2 - a3**2 - d4**2) / (2*a3)
if abs(D) > 1:
continue # 无解
theta3_1 = np.arctan2(np.sqrt(1 - D**2), D)
theta3_2 = np.arctan2(-np.sqrt(1 - D**2), D)
for theta3 in [theta3_1, theta3_2]:
# 5. 解 θ2
s3 = np.sin(theta3)
c3 = np.cos(theta3)
theta2 = np.arctan2(-a3*c3 - d4*s3 + y,
a3*s3 - d4*c3 + x)
# 6. 解 θ4, θ5, θ6(从旋转矩阵中提取)
# 这里省略具体推导,直接调用子函数
R03 = compute_R03(theta1, theta2, theta3)
R36 = R03.T @ R
theta4, theta5, theta6 = extract_euler_angles(R36)
solutions.append([theta1, theta2, theta3,
theta4, theta5, theta6])
return solutions
避坑指南:我曾经在解θ3时忘了检查D的绝对值是否大于1。结果程序跑起来,遇到不可达位置直接报错。后来加了个continue跳过,稳得很。
4.6 解析法 vs 数值法——什么时候用哪个?
我个人的选择原则很简单:
- 工业六轴臂(满足Pieper):无脑解析法。速度快,精度高,还能显式处理多解。
- 协作机器人或冗余臂:数值法更灵活。比如7轴臂,解析法基本没戏,数值法配合优化目标(比如避障、最小关节运动)反而更好用。
- 实时性要求极高(1kHz以上):解析法。数值法迭代次数不确定,容易超时。
- 调试阶段:我建议先用数值法快速验证运动学模型,再换成解析法做最终部署。
一句话总结:解析法适合“结构规整、要求高速”的场景;数值法适合“构型特殊、需要灵活”的场景。两者不是替代关系,是互补关系。
4.7 本章小结
逆运动学是机器人控制的“硬骨头”。但掌握了腕部分离法,你会发现大部分六轴臂的逆解其实有套路可循。Pieper准则给了我们一把钥匙,解析法给了我们一把快刀。
下一章我们会深入具体的逆解推导,包括每个关节角的显式公式。到时候我会手把手带你推一遍,保证你以后看到逆运动学方程,心里不慌。
公众号:蓝海资料掘金营,微信deep3321