3、DH参数建模:标准DH与改进DH的区别、连杆坐标系建立规则、参数表提取方法、代码实现DH变换矩阵
好,咱们进入第三章。DH参数建模,这可以说是机器人运动学的“通用语言”。不管你用啥机器人,UR、KUKA还是自己攒的六轴,想算逆解,第一步就是把机械臂的几何关系用数学描述清楚。
我个人习惯把DH参数比作“机械臂的身份证”。每个关节、每根连杆,都有四个固定参数。只要这四个数对了,末端位姿就能算出来。但这里有个坑——DH参数其实有两个流派:标准DH和改进DH。很多初学者在这上面栽跟头。
3.1 标准DH vs 改进DH:到底差在哪?
先看一张对比表,把核心区别说清楚。
| 对比项 | 标准DH (Classic DH) | 改进DH (Modified DH) |
|---|---|---|
| 坐标系附着位置 | 连杆i的坐标系固连在连杆i的首端(前一个关节) | 连杆i的坐标系固连在连杆i的末端(后一个关节) |
| 变换顺序 | 绕x轴旋转 → 沿x轴平移 → 绕z轴旋转 → 沿z轴平移 | 沿x轴平移 → 绕x轴旋转 → 沿z轴平移 → 绕z轴旋转 |
| 参数定义 | αi-1, ai-1, di, θi | αi-1, ai-1, di, θi(符号一样,但物理含义略有偏移) |
| 适用场景 | 串联机器人,树形结构 | 串联、并联、树形结构,尤其是闭环链 |
| 我的经验 | 早期教材多用,但容易在相邻关节轴线平行时出现奇异 | 现代机器人库(如ROS、Pinocchio)默认用改进DH,更鲁棒 |
你可能会问:“为啥要搞两套?” 说白了,标准DH是先绕x转再沿x移,改进DH是先沿x移再绕x转。顺序不同,导致坐标系附着位置不同。我在项目中遇到过,用标准DH建模一个六轴协作机器人,在关节5和关节6轴线平行时,参数突然跳变,调试了半天才发现是DH模型选错了。
3.2 连杆坐标系建立规则
不管用哪种DH,建立坐标系都有固定套路。我总结了一个“三步法”,你照着做基本不会错。
- 找关节轴: 画出所有关节的旋转轴(或移动轴)线。这些线是z轴的基础。
- 定z轴: 关节i的轴线就是坐标系{i}的zi轴。方向任意,但建议统一指向末端。
- 定x轴: 这是最容易出错的一步。xi轴是zi-1和zi的公垂线,方向从zi-1指向zi。如果两轴相交,xi垂直于两轴所在平面。
嗯,这里要注意:如果zi-1和zi平行,公垂线不唯一。这时候我习惯选一个让后续参数尽量简单的方向,比如让ai-1 = 0。
3.3 参数表提取方法
坐标系建好了,接下来就是填参数表。四个参数的定义如下:
- αi-1(连杆扭转角): 从zi-1绕xi-1旋转到zi的角度。右手定则。
- ai-1(连杆长度): 沿xi-1方向,从zi-1到zi的距离。永远是正值。
- di(连杆偏距): 沿zi方向,从xi-1到xi的距离。可正可负。
- θi(关节角): 从xi-1绕zi旋转到xi的角度。对于旋转关节,这是变量。
我一般会画一个表格,把每个关节的四个参数填进去。比如一个典型的六轴工业机器人,参数表长这样:
| 关节 i | αi-1 (rad) | ai-1 (mm) | di (mm) | θi (rad) |
|---|---|---|---|---|
| 1 | 0 | 0 | 0.3 | θ1 |
| 2 | -π/2 | 0.2 | 0 | θ2 |
| 3 | 0 | 0.8 | 0 | θ3 |
| 4 | -π/2 | 0.1 | 0.8 | θ4 |
| 5 | π/2 | 0 | 0 | θ5 |
| 6 | -π/2 | 0 | 0.1 | θ6 |
你想想看,有了这张表,机械臂的几何模型就完全确定了。剩下的就是矩阵乘法。
3.4 代码实现DH变换矩阵
理论说完了,上代码。我习惯用C语言在STM32上实现,因为效率高、可控性强。下面是一个标准的改进DH变换矩阵生成函数。
#include <math.h>
// 定义4x4齐次变换矩阵
typedef struct {
float data[4][4];
} Matrix4x4;
// 改进DH:根据四个参数生成变换矩阵 i-1T_i
Matrix4x4 dh_transform_mod(float alpha, float a, float d, float theta) {
Matrix4x4 T;
float ct = cosf(theta);
float st = sinf(theta);
float ca = cosf(alpha);
float sa = sinf(alpha);
// 行优先填充
T.data[0][0] = ct; T.data[0][1] = -st; T.data[0][2] = 0; T.data[0][3] = a;
T.data[1][0] = st*ca; T.data[1][1] = ct*ca; T.data[1][2] = -sa; T.data[1][3] = -sa*d;
T.data[2][0] = st*sa; T.data[2][1] = ct*sa; T.data[2][2] = ca; T.data[2][3] = ca*d;
T.data[3][0] = 0; T.data[3][1] = 0; T.data[3][2] = 0; T.data[3][3] = 1;
return T;
}
// 标准DH:变换矩阵略有不同
Matrix4x4 dh_transform_classic(float alpha, float a, float d, float theta) {
Matrix4x4 T;
float ct = cosf(theta);
float st = sinf(theta);
float ca = cosf(alpha);
float sa = sinf(alpha);
T.data[0][0] = ct; T.data[0][1] = -st*ca; T.data[0][2] = st*sa; T.data[0][3] = a*ct;
T.data[1][0] = st; T.data[1][1] = ct*ca; T.data[1][2] = -ct*sa; T.data[1][3] = a*st;
T.data[2][0] = 0; T.data[2][1] = sa; T.data[2][2] = ca; T.data[2][3] = d;
T.data[3][0] = 0; T.data[3][1] = 0; T.data[3][2] = 0; T.data[3][3] = 1;
return T;
}
有了单个变换矩阵,正解就是连乘:0T6 = 0T1 * 1T2 * ... * 5T6。代码实现就是循环调用矩阵乘法。
3.5 知识体系总览
最后,我用一张SVG图把本章的核心逻辑串起来。你一看就明白DH参数建模的全流程。
嗯,这张图把本章的脉络理清了。从选择DH类型开始,到建立坐标系、提取参数表,最后用代码生成变换矩阵。每一步都有坑,但只要你按这个流程走,就不会乱。
- 标准DH和改进DH的变换顺序不同,导致坐标系附着位置不同。选一种,用到底。
- 坐标系建立遵循“三步法”:找轴、定z、定x。平行轴时注意公垂线选择。
- 参数表是机械臂的“数学基因”,四个参数(α, a, d, θ)唯一确定相邻连杆关系。
- 代码实现时,注意三角函数精度和计算效率。STM32上建议优化数学库。