3. 机器人学基础(下)

好,咱们接着聊。上一章我们把机器人的位姿描述、坐标变换这些基础打牢了。这一章,我们要真正让机器人“动”起来。

说白了,运动学就是研究机器人怎么动,而不关心它为什么动(那是动力学的事)。我们只需要知道:给定关节角度,末端在哪儿?(正解)和 想让末端到某个位置,关节该怎么转?(逆解)。

我在做抓取项目时,最头疼的往往不是视觉算法,而是标定完发现机器人就是抓不准。后来排查下来,十有八九是运动学模型没建对。所以,这一章的内容,是后续所有工作的基石。

本章核心: 掌握DH参数建模,理解正逆运动学求解逻辑,并能用Python做简单仿真验证。

3.1 正运动学:从关节到末端

正运动学,就是已知机器人每个关节的角度(或位移),求末端执行器在基坐标系下的位姿。这个过程是唯一的,也是确定的。

怎么求?核心就是齐次变换矩阵的连乘。

想象一下,从基座开始,经过关节1的变换到连杆1,再经过关节2的变换到连杆2……一直乘到末端。用公式表达就是:

T_0^n = T_0^1 * T_1^2 * ... * T_{n-1}^n

这里的 T_{i-1}^i 就是相邻坐标系之间的变换矩阵。每个矩阵里都包含了当前关节的变量(θ 或 d)。

我个人习惯,在写代码前,一定会先在纸上把坐标系画出来,把DH参数表列清楚。这一步偷懒,后面Debug会非常痛苦。

3.2 逆运动学:从末端到关节

逆运动学就麻烦多了。已知末端位姿,反求关节角度。这通常是一个多解、甚至无解的问题。

为什么难?

  • 多解性: 同一个末端位置,机器人可能有多种“姿势”能达到(比如“肘部朝上”和“肘部朝下”)。
  • 奇异性: 在某些位姿下,机器人会失去某个方向的自由度,导致逆解无解或解不连续。
  • 非线性: 方程里充满了三角函数,求解复杂。

求解方法主要有两种:

  1. 解析法(封闭解): 通过代数或几何方法直接推导出公式。速度快,但只适用于满足Pieper准则的机器人(比如后三个关节轴线交于一点)。工业机器人大多满足这个条件。
  2. 数值法(迭代法): 比如牛顿-拉夫森法。通用性强,但速度慢,且依赖初始值。我一般在做离线规划时用数值法做校验。

我的经验: 在实际抓取项目中,我们通常不会实时求解逆运动学。而是预先离线计算好一系列路径点,再让机器人去执行。这样可以避免奇异点,也能保证运动平滑。

3.3 机器人连杆参数(DH模型)

要让上面的计算能进行,我们得有一套标准的方法来描述相邻连杆之间的关系。这就是DH参数法。

Denavit和Hartenberg这两位大佬,在1955年提出了这套方法。它用4个参数就能唯一确定相邻坐标系间的变换关系:

参数 符号 物理含义 变量类型
连杆长度 ai-1 从Zi-1到Zi沿Xi-1的距离 常数
连杆扭角 αi-1 从Zi-1到Zi绕Xi-1的转角 常数
连杆偏距 di 从Xi-1到Xi沿Zi的距离 关节变量(移动关节)
关节转角 θi 从Xi-1到Xi绕Zi的转角 关节变量(转动关节)

建立DH坐标系时,有个口诀:“Z轴是关节轴,X轴是公垂线”。具体步骤:

  1. 确定各关节的Z轴方向。
  2. 确定相邻Z轴之间的公垂线,方向为X轴。
  3. Y轴由右手定则确定。

我曾经在标定一个协作机器人时,因为把相邻关节的Z轴方向搞反了,导致仿真里机器人乱跑。查了两天才发现是DH参数表里α的符号错了。所以,建系时一定要仔细核对每个参数的正负号。

3.4 运动学仿真基础(Python + Robotics Toolbox)

理论讲完了,得上手试试。我推荐用Python的robotics-toolbox-python库,它封装了大部分运动学功能,非常适合快速验证。

安装很简单:

pip install roboticstoolbox-python

下面,我们以经典的六轴工业机器人为例,演示如何用DH参数建模,并计算正逆运动学。

3.4.1 定义机器人模型

我们先用标准DH参数定义一个简单的6R机器人。假设其DH参数表如下:

关节 i ai-1 (mm) αi-1 (rad) di (mm) θi (rad)
1 0 0 0.3 q1
2 0.5 -π/2 0 q2
3 0.4 0 0 q3
4 0 -π/2 0.5 q4
5 0 π/2 0 q5
6 0 -π/2 0.2 q6

对应的Python代码如下:

import roboticstoolbox as rtb
import numpy as np
from spatialmath import SE3

# 定义机器人,使用标准DH (MDH)
robot = rtb.DHRobot(
    [
        rtb.RevoluteMDH(a=0, alpha=0, d=0.3, offset=0),   # 关节1
        rtb.RevoluteMDH(a=0.5, alpha=-np.pi/2, d=0, offset=0), # 关节2
        rtb.RevoluteMDH(a=0.4, alpha=0, d=0, offset=0),   # 关节3
        rtb.RevoluteMDH(a=0, alpha=-np.pi/2, d=0.5, offset=0), # 关节4
        rtb.RevoluteMDH(a=0, alpha=np.pi/2, d=0, offset=0),  # 关节5
        rtb.RevoluteMDH(a=0, alpha=-np.pi/2, d=0.2, offset=0) # 关节6
    ],
    name="My_6R_Robot"
)

print(robot)

3.4.2 正运动学求解

定义好机器人后,正解就是一行代码的事:

# 设定一组关节角度 (单位: rad)
q = np.array([0.2, -0.5, 0.8, 0.1, 0.3, 0.0])

# 计算末端位姿
T_end = robot.fkine(q)
print("末端位姿矩阵:\n", T_end)

# 提取位置和姿态
position = T_end.t
orientation = T_end.R
print("位置 (x, y, z):", position)
print("旋转矩阵:\n", orientation)

输出结果是一个4x4的齐次变换矩阵。你可以把它跟手算的结果对比,验证模型是否正确。

3.4.3 逆运动学求解

逆解稍微复杂一点,但工具箱也提供了接口。这里我们使用数值法(迭代法)求解:

# 假设我们想要达到的末端位姿
T_goal = SE3(0.6, 0.2, 0.5) * SE3.RPY(0.1, 0.2, 0.3)

# 提供一个初始关节角猜测
q_guess = np.array([0, 0, 0, 0, 0, 0])

# 求解逆运动学
sol = robot.ikine_LM(T_goal, q0=q_guess)

if sol.success:
    print("逆解成功!")
    print("关节角度 (rad):", sol.q)
else:
    print("逆解失败,请检查目标位姿是否可达或调整初始值。")

注意: 数值法逆解依赖于初始值 q0。如果初始值离真实解太远,或者目标位姿在奇异点附近,求解可能会失败。我的做法是:先用解析法(如果机器人满足条件)求一个解,再用数值法做局部优化。

3.5 本章知识体系

为了让你更直观地理解本章内容的结构,我画了一张图:

第3章 知识体系结构图 第3章:机器人运动学基础与DH模型 正运动学 DH参数建模 逆运动学 齐次变换矩阵连乘 T_0^n = T_0^1 * ... * T_{n-1}^n 4个参数: a, α, d, θ 坐标系建立规则 解析法 vs 数值法 多解、奇异点问题 Python + Robotics Toolbox 仿真验证 核心逻辑:建立模型 → 参数化描述 → 正解验证 → 逆解求解 → 仿真验证

这张图把本章的核心逻辑串起来了。你可以看到,DH参数是连接正运动学和逆运动学的桥梁。没有准确的模型,后面的计算都是空中楼阁。

3.6 本章小结与避坑指南

好了,我们来快速回顾一下本章的重点:

  • 正运动学:矩阵连乘,唯一解。是验证机器人模型是否正确的第一步。
  • 逆运动学:多解、奇异点。实际工程中要提前规避。
  • DH参数:4个参数定天下。建系时务必小心符号。
  • 仿真工具:Python + Robotics Toolbox 是利器,能帮你快速验证算法。

我曾经踩过的坑: 在做手眼标定时,我直接用厂家给的URDF文件里的DH参数,结果标定出来的外参怎么都对不上。后来我手动测量了机器人的实际尺寸,重新建立了DH模型,问题才解决。所以,永远不要完全相信纸面参数,动手验证才是王道。

运动学是机器人学的“内功”。内功练好了,后面学视觉、学规划,才能事半功倍。希望你能跟着代码亲自跑一遍,把每个矩阵都算清楚。