状态:草稿 (2026-10-18),实测。 数据是通过笔记本电脑 (Apple M1 Max, macOS 26.5) 上的 Python 3.9.6 和 numpy 2.0.2 直接计算得出的。 时间为 7 次重复计算的中位数(舍弃第一次),数值解的时间是 300 个成功求解的中位数。原始数据与代码:工作目录
measure/robot-arm-basics/的arm.py,m04_ik.py,out/m04_ik.json. 示例手臂为第 3 篇中的虚拟设计,没有硬件实测数据。 参考资料查阅于 2026-10-18。编写规则:以实测数据为基础,未能测量的标记为「未实测」,无法确认的标记为「未确认」。
目录
1. 直觉:抓杯子的手臂姿态有多种
抓取桌上的杯子时,手肘可以向外张开,也可以贴近身体。手的位置和方向相同,但手臂的姿态不同。相反,桌子边缘之外的杯子无论用什么姿态都无法抓到。逆运动学(inverse kinematics, IK)的这三个情况全都包含在这里了:
- 解可能是 多个。
- 可能 无解 。
- 即使有解,在某些姿态附近,关节需要发生极大的运动才能使球拍产生微小的位移(奇异点).
在乒乓球机器人中,逆运动学需要在每次击球时以及修正预测时重新求解。必须产出速度快、总能收敛且在上一个姿态基础上不会突变的解。
2. 图解:相同的目标,两个解
3. 计算
3.1 两连杆手臂:余弦定理
设从肩膀到目标的距离为 r,则两个连杆与 r 构成一个三角形。通过余弦定理即可求出肘部关节角。
def ik2(x, y, elbow=+1):
c = (x*x + y*y - L1*L1 - L2*L2) / (2*L1*L2)
if abs(c) > 1:
return None # 닿지 않는 목표
q2 = elbow * acos(c) # +: 팔꿈치 아래, -: 팔꿈치 위
q1 = atan2(y, x) - atan2(L2*sin(q2), L1 + L2*cos(q2))
return q1, q2
acos 会给出正负两个值,因此有两个解。如果 |c| > 1,则无法构成三角形,因而无解。判定只需一行代码,这是解析解的一大优势。
3.2 六轴手臂:腕部解耦
第 3 篇中的示例手臂,其腕部三轴交于一点。因此可以将 6 个未知数分为两个阶段求解:
- 位置 3 个。 从球拍姿态求出腕部中心 p_c = p − d6·R[:, 2]。第 1 个关节为从上方俯视 p_c 的方向 atan2(y_c, x_c) 或其反向(+π)。然后第 2 和第 3 个关节转化为 3.1 节的两连杆问题,从而得出肘部上方和下方的两个解。
- 方向 3 个。 一旦确定了第 1、2、3 个关节,就可以求出 R₀₃,腕部需要完成的剩余旋转为 R₃₆ = R₀₃ᵀ·R。这种腕部结构与 ZYZ 欧拉角形式相同,因此通过 θ5 = atan2(±√(r13² + r23²), r33) 可以得到两个解(腕部翻转)。
2 × 2 × 2 = 共 8 个解。如果 θ5 = 0,则第 4 轴和第 6 轴在同一直线上,此时只能确定 θ4 + θ6 的和。这就是腕部奇异点。
3.3 数值解:牛顿法与阻尼最小二乘
对于腕部不交于一点的手臂或 7 轴及以上的手臂,往往没有闭式解或者闭式解过于复杂。此时仅利用正运动学和雅可比矩阵(第 5 篇)进行迭代求解。求出减小姿态误差 e(3 个位置 + 3 个方向)的关节改变量 Δq 的方法主要有三种。
유사역행렬(뉴턴-랩슨): Δq = J⁺ e
감쇠 최소제곱(DLS): Δq = Jᵀ (J Jᵀ + λ² I)⁻¹ e ‖J Δq − e‖² + λ²‖Δq‖² 를 최소화
야코비안 전치: Δq = α Jᵀ e, α = ⟨e, J Jᵀ e⟩ / ‖J Jᵀ e‖²
Modern Robotics 6.2.1 节总结了牛顿-拉普森方法,Buss 的教程则将三种方法进行了综合。DLS 也被称为列文伯格-马夸尔特(Levenberg–Marquardt)算法。从奇异值的角度来看,DLS 将各个方向的增益修改为 σ/(σ² + λ²)。当 σ 大于 λ 时,它等同于伪逆矩阵;当 σ 趋近于 0 时,增益也趋近于 0。这是一种防止在奇异点附近关节发生暴走的机制。
for it in range(max_iter):
e = pose_error(fk_dh(q), T_goal) # 위치 오차 3 + 축-각 방향 오차 3
if norm(e[:3]) < 1e-5 and norm(e[3:]) < 1e-4: # 0.01 mm, 0.006°
return q, True
J = jacobian(q)
dq = J.T @ np.linalg.solve(J @ J.T + lam**2 * np.eye(6), e)
q = q + dq
3.4 两轴直角龙门架:逆运动学为加法结构的系统
如果将球拍安装在两轴直角龙门架(横向 x,纵向 z)上,并在其末端配置偏航-俯仰两轴腕部,其逆运动学极为简单:
손목 요 ψ = atan2(n_x, n_y) (n 은 원하는 라켓 법선)
손목 피치 φ = atan2(n_z, √(n_x² + n_y²))
손목 중심 = 라켓 중심 − d · n
갠트리 x = 손목 중심 x, 갠트리 z = 손목 중심 z
只有一个解,且龙门架轴的雅可比矩阵为常数(单位矩阵),因此不存在奇异点。球拍的速度也与姿态无关,直接等于轴的速度。不过,由于腕部中心必须位于龙门架平面上,球拍中心的 y 坐标(乒乓球台长度方向)被绑定在「龙门架平面 + d·n_y」上。也就是说, 击球点几乎固定在一个平面上。Koç 等人 (2018) 曾报道称,这种固定的虚拟击球平面限制了轨迹,从而降低了回球率(实际测试中固定平面约 10~40%,同时优化击球时间与位置的方式约 40~60%)。因此,便诞生了类似 Google 系统那样,在龙门架上方搭载六轴手臂以结合两者优势的设计方案。
4. 实测
4.1 解析解:精度与时间
| 问题 | 样本 | 最大位置误差 | 最大方向误差 | 单次耗时 |
|---|---|---|---|---|
| 两连杆平面(两个解) | 100,000 个目标 | 6.9×10⁻¹⁶ m | - | 0.59 µs |
| 六轴腕部解耦(8 个解) | 10,000 个姿态 | 1.1×10⁻¹⁵ m | 9.4×10⁻¹⁴ rad | 58 µs |
| 两轴龙门架 + 两轴腕部 | - | (按定义精确) | - | 0.61 µs |
在全部 10,000 个六轴姿态中均算出了 8 个解,并将这 8 个解全部代入正运动学中,确认能够重新还原出原始姿态。由于姿态是由随机关节角生成的,初始关节角也总是能回到 8 个解中的某一个(最大差值 6.7×10⁻¹² rad)。
4.2 数值解:各方法的成功率与时间
通过随机关节角生成 300 个目标姿态,并从两种初始起点进行求解。「附近」是指在正确关节角上加上标准差 0.3 rad 噪声的起点,「预备姿态」是指针对所有目标采用相同的固定姿态。最大重复 200 次,成功标准为位置 0.01 mm、方向 10⁻⁴ rad。
| 方法 | 起点 | 成功率 | 迭代次数 中位数/95% | 时间中位数 | 单步最大值(中位数) |
|---|---|---|---|---|---|
| 伪逆矩阵 | 附近 | 99.7% | 4 / 23 | 0.77 ms | 0.92 rad |
| 伪逆矩阵 | 预备姿态 | 99.3% | 16 / 45 | 2.5 ms | 61 rad |
| 伪逆矩阵 + 步长 0.3 rad 限制 | 预备姿态 | 99.7% | 23 / 41 | 3.8 ms | 0.3 rad |
| DLS λ=0.01 | 预备姿态 | 95.7% | 16 / 41 | 2.3 ms | 16 rad |
| DLS λ=0.05 | 预备姿态 | 86.7% | 16 / 87 | 2.6 ms | 8.6 rad |
| DLS λ=0.1 | 预备姿态 | 80.0% | 23 / 146 | 3.5 ms | 5.5 rad |
| DLS λ=0.01 + 步长限制 | 预备姿态 | 97.7% | 24 / 46 | 3.5 ms | 0.3 rad |
| 雅可比转置 | 预备姿态 | 1.3% | 130 / 184 | 17 ms | 1.3 rad |
有两个结果出乎意料:
- 阻尼系数设得越大,成功率反而越低。 当 λ 较大时,虽然在奇异点处很安全,但在正常姿态下步长也会缩短,导致在 200 次内未能达到 0.01 mm 精度的情形增加。我们推测,将位置 (m) 和方向 (rad) 混入同一个向量并共用一个 λ 也是原因之一。Buss 也只是提到 λ 应当大到足以在奇异点处撑住、小到不至于让收敛变慢,但并未给出具体数值。
- 伪逆矩阵虽然最终大多能收敛,但在过程中单步跳跃竟高达 61 rad。 计算本身没有问题,但如果直接将这个中间值发送给电机就会引发事故。实际应用中,要么限制步长(表格中的「步长限制」),要么仅将收敛后的最终解传递给轨迹生成器(第 8 篇)。
雅可比转置计算成本最低,但收敛极其缓慢,在 200 次内几乎无法完成。解析解 (58 µs) 比从预备姿态出发的数值解 (2.3 ms 以上) 快大约 40 倍,比从正解附近出发的数值解 (0.7 ms) 也快 12 倍。还必须记住的一点是,数值解根据起点的不同, 最终会走向哪一个解是无法预知的。在机器人应用中,通常会从当前的关节角出发使其走向最近的解;如果存在解析解,则在 8 个解中选择距离当前姿态最近的一个。
4.3 奇异点附近的单步表现
对比了旨在修正姿态误差(位置约 1 mm,方向约 0.01 rad)的 单步大小在不同姿态下的差异。
| 姿态 | 最小奇异值 σ_min | 条件数 | 伪逆矩阵步长 | DLS λ=0.05 步长 | DLS 步长之后的剩余误差 |
|---|---|---|---|---|---|
| 普通姿态 | 0.055 | 35 | 0.042 rad | 0.030 rad | 0.0009 |
| 腕部 θ5 = 0.01 rad | 0.0020 | 977 | 1.77 rad | 0.034 rad | 0.0036 |
| 腕部 θ5 = 0.001 rad | 0.0002 | 9,768 | 17.6 rad | 0.034 rad | 0.0036 |
| 肘部接近伸直 (θ3 = π/2 + 0.001) | 0.00015 | 13,041 | 12.9 rad | 0.023 rad | 0.0019 |
在奇异点附近,为了修正 0.01 的误差,伪逆矩阵会要求关节旋转两三圈。而 DLS 通过将步长限制在 0.03 rad,代价是放弃了一部分误差(如上表中的剩余误差)。这是在「精确对准」与「平稳运动」之间作出的权衡,实际机器人几乎总是选择后者。
4.4 无法触及的目标
向两连杆手臂(触及极限 0.0.75 m)设定了 0.85 m 以外的目标并重复 50 次。可能达到的最近距离为 0.10 m。
| 方法 | 最终距离 | 曾达到过的最近距离 | 最大步长 | 最后五步 |
|---|---|---|---|---|
| 伪逆矩阵 | 0.139 m | 0.100 m | 33.7 rad | 1.2, 2.6, 1.6, 1.3, 1.4 rad(持续振荡) |
| DLS λ=0.05 | 0.145 m | 0.104 m | 1.10 rad | 每次 1.05 rad(原地往返) |
| DLS λ=0.2 | 0.100 m | 0.100 m | 0.36 rad | 10⁻¹⁰ rad(停止) |
当无解时,伪逆矩阵会无休止地振荡,采用较小 λ 的 DLS 也同样会在两个姿态之间反复横跳。增大 λ 则能使之平稳地停在「最近的姿态」上。Buss 曾指出,在这种情况下,如果将误差向量的大小裁剪为连杆长度的一半左右,那么即使较小的 λ 也能减小振动。由于在乒乓球机器人中,「球落入工作空间外」是非常常见的情况,因此 能够优先判定无解的解析解显得尤为珍贵。
5. 局限性
- 未在逆运动学中处理关节角极限(例如 ±170°)与自碰撞问题。仅在第 5 篇选择解时施加了关节极限限制。
- DLS 的 λ 仅进行了固定值比较。根据 σ_min 改变 λ 的方法以及对齐位置与方向误差单位的权重未进行测量(未实测)。
- 数值解耗时的大部分原因在于在 Python 中每次迭代时重新计算正向运动学和雅可比矩阵的开销。C++ 实现的耗时未实测。
6. 总结
- 2 连杆通过余弦定理,6 轴球面手腕机械臂通过手腕分离获得解析解。解析解可以一次性告知解的数量和“无解”状态。
- 数值解适用于任何机械臂,但会根据起点导向不同的解,并且在中间可能会产生较大的步长。因此需要步长限制和阻尼。
- 在奇异点附近,DLS 会牺牲一点精度来防止关节暴走。对于无法触及的目标,足够大的 λ 会使机械臂停在最近的姿态。
- 龙门架的逆运动学只是加法且没有奇异点,但打击点被限制在一个平面上。
Titi 的小结。 打同一个球的机械臂姿势竟然有八种之多。其中的诀窍是从中选择最接近当前姿势的一个,如果是够不着的球,就不要勉强去追,而应该停在最近的地方!
参考资料
所有资料均于 2026-10-18 查阅。
- Lynch, Park, Modern Robotics, 2017, 公开预印本,第 6 章(6.1 解析解 IK,6.2.1 Newton–Raphson)。
- Buss, S. R., Introduction to Inverse Kinematics with Jacobian Transpose, Pseudoinverse and Damped Least Squares methods(PDF 标注 2009-10-07),第 3~6 节。
- Koç, Maeda, Peters, Online optimal trajectory generation for robot table tennis, RAS 105 (2018), 作者公开版,图 2 和图 11。
- D'Ambrosio 等人, arXiv:2408.03906,II-A 节。