机械臂坐标系变换:从旋转矩阵到DH参数与正运动学
2026/9/15 0:38:39 网站建设 项目流程

第一次在实验室里调机械臂的时候,我盯着示教器上那一排位姿数据看了很久——x、y、z、rx、ry、rz,看着很简单,但机械臂就是不走我想要的轨迹。后来自己动手写了一次正运动学代码,从基座标系一路变换到末端执行器,才真正意识到,机器人干的所有事情,本质上都是一台机器在不停地做坐标系变换。

坐标系变换不是某个高深的分支,它是整个机械臂运动学的底座。你如果想把末端执行器移动到某个空间点,或者让视觉系统告诉机械臂“工件在这里”,中间隔着的一定是一串坐标系的换算。不理解这一层,后面学雅可比、动力学、轨迹规划、手眼标定都会觉得虚。这篇是我自己学习过程中整理的笔记,围绕“坐标系变换”这个主题,把旋转矩阵、齐次变换矩阵、DH参数、正运动学这些内容串起来讲一遍,顺便把我踩过的坑也写出来,希望对刚开始接触机械臂的读者有点帮助。

1. 坐标系变换到底在解决什么问题

1.1 机械臂里的“位置”和“姿态”是两件事

很多人上手机械臂时,第一次听到“位姿”这个词,就以为它指的是位置。其实位姿是“位置 + 姿态”的合称,英文叫Pose,Position and Orientation。位置好理解,就是三维空间里那个点,用(x, y, z)描述;姿态描述的是这个坐标系相对于参考坐标系“怎么摆”,是正着放还是歪着放。

举个生活化的例子。你去超市拿货架上的酱油瓶,你的手要移动到酱油瓶的位置,光有位置还不够,你还得让手掌的朝向正好能握住瓶身,该正握还是侧握,这个“朝向”就是姿态。机械臂也一样,焊接时焊枪要垂直于焊缝,喷涂时喷头要对准曲面,这都关系到姿态。

在数学上,描述一个坐标系相对于另一个坐标系的关系,就是坐标系变换的核心任务。我们知道,空间中任何一个刚体,都可以用一个坐标系固定在上面,然后用这个坐标系相对于参考坐标系的位置和姿态,来完整描述刚体在空间中的状态。对于机械臂来说,末端执行器就是一个刚体,基座是另一个刚体(通常固定在世界上),它们之间就是基坐标系和末端坐标系之间的变换关系。一旦这个关系清楚了,机械臂末端的位姿就是确定的。

1.2 为什么所有上位机都藏着矩阵运算

如果你看过机械臂的上位机软件,或者读过一些开源的控制代码,会发现里面密密麻麻都是矩阵。这不是程序员故意写得难懂,而是矩阵天然适合做坐标变换。

最直观的原因是:三维空间中的一次旋转可以用一个3×3矩阵表示,一次平移可以用一个3×1向量表示,两者组合起来就是一次刚体变换。而机械臂有多个关节,从基座到末端,每个关节就是一个坐标系,相邻两个坐标系之间都有一个变换。整条链上依次做变换,就是多个矩阵连乘。矩阵乘法天然支持这种“链式”操作,而且计算过程是线性的、确定的,非常适合编程实现和实时计算。

换句话说,坐标系变换给了我们一套统一的语言:不管机械臂有几个关节,也不管关节类型是旋转还是移动,都可以通过一系列坐标变换,最终算出一个从基坐标系到末端坐标系的复合变换矩阵。这就是后面正运动学的数学根。

2. 从旋转矩阵到齐次变换矩阵

2.1 旋转矩阵是怎么来的

先说姿态。如果有一个坐标系B相对于参考坐标系A发生了旋转,那么我们想描述B的x轴、y轴、z轴在A坐标系下的方向。这九个方向余弦,就组成了一个3×3的旋转矩阵。

实际用的时候,不需要去记那些复杂的推导,记住旋转矩阵的几个性质,写代码和做计算会顺手很多。旋转矩阵的每一列是单位向量,所以它是正交矩阵,即有R的转置等于R的逆。它的行列式等于1,说明它只改变方向,不改变长度,也不产生镜像。旋转矩阵的自由度其实只有3个,因为9个元素之间有关联约束,这也是为什么工程上会用欧拉角、轴角和四元数来存储姿态,本质都是为了压缩存储和方便插值。

具体到绕单轴的旋转矩阵,最重要的就是绕x轴、绕y轴、绕z轴三个基本矩阵。比如绕z轴旋转θ,矩阵是:

[cosθ -sinθ 0] [sinθ cosθ 0] [ 0 0 1]

这三个基础矩阵是构成任意旋转的积木。实际机械臂关节大多是旋转关节,每个关节角θ对应一个绕当前关节轴旋转的矩阵,这个基本变换会在DH参数模型中反复出现。

2.2 把平移和旋转统一成齐次矩阵

旋转矩阵只能描述方向变化,但坐标系变换还有平移。平移就是一个三维向量。有人就想,能不能把旋转和平移放在同一个框架里,这样一次运算就能同时处理姿态和位置。

于是就有了齐次变换矩阵。它是一个4×4矩阵,左上角是3×3旋转矩阵,右上角是3×1平移向量,下面一行是[0 0 0 1]。这样可以用一个矩阵表示一次完整的刚体变换:

[R t] [0 1]

使用齐次矩阵还有个额外的好处,就是可以用一个4×1的齐次坐标点来表示空间中的点,然后直接左乘变换矩阵,得到变换后的点坐标。这样旋转和平移就统一成了矩阵乘法,不需要分开写两步。这个思路在计算链式变换时特别方便,因为多个关节就是多个4×4矩阵连乘。

2.3 两个坐标系连续变换时,乘法的顺序不能乱

实际机械臂从基座到末端通常有6个关节,意味着要做6次变换。每次变换对应一个齐次矩阵,记为T_01、T_12、T_23……这里下标表示从前一个坐标系变换到后一个坐标系。那么从基坐标系0到末端坐标系6的总变换是:

T_06 = T_01 × T_12 × T_23 × T_34 × T_45 × T_56

整个式子是从左到右依次把坐标系一个个叠加上去。这里有一个特别容易犯错的地方:矩阵乘法不满足交换律,顺序一旦错了,姿态就会完全不对。比如你先绕z轴转90度再沿x轴平移,和先平移再绕z轴转90度,结果往往不一样。很多初学者在写正运动学时,总变换矩阵算出来不对,大概率就是某个关节的变换顺序或者左右乘搞反了。

我在实际写代码时有一个习惯:每算一步变换,就把当前坐标系相对于基坐标系的位姿打印出来,沿着轨迹每个关节角都验证一遍,确认无误后再继续下一步。这样做虽然麻烦一点,但能非常快地定位是哪一个环节出了问题。

3. 一张DH参数表串起整个机械臂

3.1 为什么要用DH参数

如果手动去定义每个关节坐标系之间的旋转和平移,6个关节就要写6组矩阵,而且这些矩阵的物理意义不够直观。1955年Denavit和Hartenberg提出了一种标准化的建模方法,用4个参数来描述相邻两个关节坐标系之间的关系,这就是DH参数。

这4个参数分别是:关节角θ、关节距离d、连杆长度a、连杆扭转角α。每一种机械臂,都可以用一张DH参数表唯一描述。换句话讲,只要这张表给出来,机械臂的几何结构就是确定的。

初次接触DH参数时,最难的是理解这4个参数到底对应什么。我当时的理解方法是:把它当作“从上一个坐标系,经过两个旋转、两个平移,到达下一个坐标系”的路线图。先绕当前z轴转θ,再沿z轴平移d,然后沿新x轴平移a,最后绕新x轴转α。每一步都有明确的几何意义:θ和d描述的是关节沿z轴的旋转和平移,a和α描述的是连杆自身的长度和扭转。这样一来,每一个关节的变换矩阵都有一个统一的公式形式,把DH参数代进去,就能得到相邻坐标系的齐次变换矩阵。

3.2 标准DH和改进DH别混用

做机械臂的人一定会遇到两种DH模型:标准DH(SDH)和改进DH(MDH)。标准DH是把坐标系固定在连杆前端,变换顺序是“先绕z转θ,再沿z平移d,再沿x平移a,再绕x转α”;改进DH则是把坐标系固定在连杆后端,变换顺序是“先绕x转α,再沿x平移a,再绕z转θ,再沿z平移d”。

这两种模型各有各的适用范围。很多工业机械臂的官方文档用的是标准DH,但一些开源库(比如ROS的urdf)在处理树状结构或多分支结构时更喜欢改进DH。同一个机械臂,用标准DH和改进DH得到的DH参数表是不同的,所以参考别人的数据时,一定要注意对方用的是哪一套,否则直接代入公式,出来的运动学结果很容易是错的。

UR5机械臂是比较经典的例子,它的DH参数表在很多教材里都能找到。表中有六个关节的θ、d、a、α,前三个参数相对固定,θ是关节变量。实际计算时,直接把每个关节当前的关节角代入矩阵公式,把6个矩阵相乘,就得到了末端相对于基座的位姿。这就是一个标准的正运动学过程。

3.3 数值实例:从关节角到位姿矩阵

为了更直观,我以UR5的一个简化示例来说。假设某个时刻六个关节角分别是q1、q2、q3、q4、q5、q6,然后从DH参数表查出每个连杆对应的d和a以及α,逐个关节构造变换矩阵。六个矩阵相乘之后,得到T_06。这个4×4矩阵的左上角3×3就是末端姿态,右上角3×1就是末端位置。

把矩阵展开来看,末端位置并不是某个关节角直接决定的,而是所有关节角共同作用的结果。末端姿态则更复杂,它受到各个旋转矩阵连乘的影响,因此各个轴的朝向会随着机器人形态而变化。这也是为什么有时候你以为某个关节转90度末端就会朝某个方向,结果完全不是那样——因为它是复合变换的结果。

在学习阶段,我强烈建议读者不要只看公式,可以用Python或者MATLAB写一个简单的正运动学函数,输入六个关节角,输出末端位姿。这样你对公式的理解、对矩阵连乘顺序的理解都会深刻很多。我在自己的学习过程中就是用这种方法,把UR5的正运动学从零写了一遍,整个过程大约只花了一个下午,但对坐标系变换的感觉完全不一样了。

4. 正运动学与逆运动学:坐标系变换的两种用法

4.1 正运动学:关节空间到笛卡尔空间的单向通道

正运动学是已知各个关节角,求末端位姿。这个问题在数学上是确定且唯一的:给一组关节角,末端的位姿是确定的。正运动学并不难,难点在于建立正确的DH参数模型并把矩阵连乘写对。

正运动学在实际中是干什么的呢?最常见的就是在仿真环境中显示机械臂的状态。你在示教器上看到机械臂当前末端的位姿,就是控制器实时做了一遍正运动学算出来的。另一个场景是轨迹规划:规划器规划的是末端在笛卡尔空间中的轨迹,但控制器需要知道每个时刻对应的关节角。这就要靠逆运动学把末端位姿换算成关节角。

我在调试机械臂时经常用正运动学做代码验证。比如手动转动某个关节,观察末端位置的变化方向是否与直觉一致;或者在每次运动之前,用正运动学算出当前末端的位姿,然后再和目标位姿做差,判断当前状态与目标状态的偏差。这比自己盯着关节角去想象末端位置要直观得多。

4.2 逆运动学:从末端位姿反推关节角

逆运动学的任务正好相反:已知末端期望的位姿,求各个关节角。这是一个比正运动学复杂得多的问题。原因很好理解:正运动学是一对一的映射,而逆运动学往往是多对一的映射。同一个末端位姿,机械臂可能有多个关节角组合都能达到;极端情况下可能没有解,或者因为关节限位导致某些数学解不可达。

逆运动学的求解方法大体分两类:解析法和数值法。对于6自由度的机械臂,如果它的后三个关节轴交于一点(球形腕),就可以用解析法求出显式解。UR5就是这样,所以能用piker等库求解。数值法则更通用,思路是给定一个初始关节角猜测,通过迭代优化(比如雅可比矩阵的伪逆)逐步逼近满足末端位姿的关节角。

在学习坐标系变换的阶段,逆运动学不用太早深入,但需要理解它的基本逻辑:先建立末端位姿与基坐标系之间的变换矩阵,然后通过几何或数值方法反解。理解了正运动学的坐标系变换链,再去学逆运动学,就不会觉得公式来得莫名其妙了。

4.3 工具坐标系:机械臂真正干活的坐标系

坐标系变换还有一个非常实用的扩展,就是工具坐标系。基坐标系和末端坐标系描述的是机械臂本体的状态,但机械臂末端通常还装着一个工具,比如焊枪、夹爪、吸盘。这个工具的尖端,才是真正与工件接触的位置。工具中心点(TCP)相对于末端坐标系有一个固定的偏移和旋转,这就是工具坐标系。

控制器在做运动规划时,你可以选择让末端坐标系对齐目标,也可以让工具坐标系对齐目标。默认情况下,示教器上显示的位姿很多是TCP的位姿。这意味着,如果你想调整工具的方向,只要标定好TCP相对于末端坐标系的变换,剩下的矩阵运算就会自动处理。

实际操作中,TCP标定是很常见的事。更换一个夹爪或焊枪,都需要重新测量工具中心点相对于末端法兰的偏移,然后输入控制器。控制器在内部会把TCP值作为固定偏移矩阵T_tool去参与运算。整个过程其实就是坐标系变换在工程中的一次典型应用。

5. 实操中的坑和我的排查建议

5.1 矩阵左乘右乘顺序之坑

我说过矩阵顺序不能乱,但实际踩坑时,哪怕我理论上知道,写代码时还是经常搞反。尤其是在拼接多个变换矩阵时,究竟是应该左乘还是右乘,需要结合自己定义的坐标系传递方向来定。

我自己现则的方法是:每写一行矩阵乘法,就注释一行“当前坐标系相对于哪个坐标系的变换”。比如T_01表示“坐标系1相对于坐标系0”,那么链式传递时就是T_01 × T_12,下标中间的1是连接的桥梁。一旦下标顺序接不上,就说明有地方写错了。这个方法帮助我至少避免了好几次低级错误。

5.2 万向锁与姿态插值问题

姿态除了用旋转矩阵表示,还经常用欧拉角表示。但欧拉角有一个著名的缺陷:万向锁。当某个轴旋转到±90度时,会丢失一个自由度,导致姿态出现奇异。如果在这种状态下对欧拉角做插值,机械臂末端姿态就会变得很诡异,甚至出现突然翻转。

所以,在做姿态插值或轨迹规划时,我更推荐用四元数而不是欧拉角。四元数没有万向锁问题,而且插值平滑。很多控制器内部也默认用四元数存储姿态。你在示教器上看到的是欧拉角,但底层运算大概率是四元数或旋转矩阵。理解坐标系变换时,要意识到姿态的表示方式有很多种,关键是要知道它们之间如何互相转换。

5.3 手眼标定里的坐标系串联

另一个很常被问到的坑是手眼标定。视觉系统给机械臂一个目标位置,但这个位置是在相机坐标系下描述的,机械臂要动,就必须把它转换到基坐标系下。这就涉及到相机固定在某处(眼在手外)还是相机装在机械臂末端(眼在手上)的区别。

不管是哪种情况,本质上都是在求解一系列坐标系变换矩阵之间的约束方程。比如眼在手外,目标物体在相机坐标系中的坐标要变成基坐标系坐标,中间需要知道相机在基座标系中的位姿。这个位姿未知,所以要通过多次移动机械臂并拍摄标定板来求解。理解了坐标系变换的链式关系,手眼标定的原理就清楚了一大半。剩下的就是标定采样时注意覆盖足够多的位姿,避免算法退化。

5.4 常见问题速查表

问题现象可能原因排查建议
正运动学算出的末端位置与实机示教器不一致DH参数选错(标准DH与改进DH混用)、d或a符号不对核对DH参数表来源,打印每一步变换矩阵
末端姿态与预期方向偏差较大矩阵乘法顺序写反检查下标顺序是否连续,逐步验证
欧拉角插值时末端姿态突然翻转万向锁奇异改用四元数插值
路径规划时末端位置可达但姿态不可达逆运动学无解或关节限位检查目标姿态是否超出关节工作空间
工具尖端实际位置与示教器显示不一致工具坐标系标定错误重新标定TCP,检查偏移量正负号

这张表是根据我自己调试经验和与同行交流整理的,不代表覆盖所有情况,但覆盖了我遇到的大部分问题。如果遇到类似现象,可以优先按这个思路排查。

6. 后续扩展:这只是一个起点

坐标系变换这个主题,往下延伸至少有四个方向值得继续深入。第一个是雅可比矩阵,它描述关节速度与末端速度之间的线性映射,是分析机械臂奇异位形和做速度规划的基础。第二个是动力学,机械臂的惯性力、科氏力、重力项都依赖坐标系变换建立运动方程。第三个是轨迹规划,笛卡尔空间和关节空间的切换,本质上就是坐标变换在时间维度上的扩展。第四个是视觉伺服,把相机图像中的像素坐标转换为机械臂基坐标系中的三维坐标,靠的还是变换链。

我在学完坐标系变换之后,最大的体会是:机械臂控制再花哨,底层都是这些矩阵在流转。你在上位机里看到的一个个数值,内部都是经过层层变换算出来的。搞懂了坐标系变换,很多看似复杂的功能,其实都能拆成一串矩阵乘积。

如果你正在学机械臂,我建议先不要急着碰控制算法,老老实实把坐标系变换这块啃下来。找一个公开的机械臂DH参数,去网上找一个现成的正运动学代码,自己敲一遍,然后对着示教器验证一次。这个过程会刷新你对机械臂的认知。

我个人在后期做项目时,每次遇到奇怪的位姿问题,第一反应就是回到坐标变换去检查:是哪两个坐标系之间的关系搞错了,是哪个参数标定偏了。坐标系变换就是这么一种基础而又常用的工具,它不炫技,但你真的离不开它。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询