第三章 机器人运动学基础:位姿、变换与坐标系

做手眼标定,说白了就是让机器人的眼睛(相机)和手(机械臂)能对上话。但对话之前,你得先懂机器人的“语言”——运动学。这一章,我就带你把这些基础概念捋清楚。

3.1 机器人位姿表示:X, Y, Z, Rx, Ry, Rz

机器人在空间里,不光要知道它在哪(位置),还得知道它脸朝哪(姿态)。合起来就叫“位姿”。

位置很好理解,就是三维空间里的 (X, Y, Z) 坐标。姿态呢?我们常用绕三个轴的旋转角度来表示:Rx(绕X轴转,也叫翻滚 Roll)、Ry(绕Y轴转,也叫俯仰 Pitch)、Rz(绕Z轴转,也叫偏航 Yaw)。

这六个值,就是机器人最常用的位姿描述方式。我刚开始接触时,总搞混旋转顺序。后来发现,大部分工业机器人默认是 Z-Y-X 的旋转顺序,也就是先转 Rz,再转 Ry,最后转 Rx。顺序不同,结果天差地别。

核心概念: 位姿 = 位置 (X, Y, Z) + 姿态 (Rx, Ry, Rz)。六个自由度,决定了末端在空间里的唯一状态。

3.2 齐次变换矩阵:把位姿算清楚

光有六个值还不够,计算机算起来不方便。所以,我们引入了齐次变换矩阵。它是一个 4x4 的矩阵,把旋转和平移整合在一起。

结构长这样:

| R11 R12 R13 Tx |
| R21 R22 R23 Ty |
| R31 R32 R33 Tz |
| 0   0   0   1  |

左上角 3x3 是旋转矩阵,右上角 3x1 是平移向量。最后一行永远是 [0, 0, 0, 1]。为什么加这一行?为了把连续的坐标变换写成矩阵乘法,方便计算机批量计算。

举个例子,从机器人基座到末端的变换,可以写成:

Base_T_Tool = Base_T_J1 * J1_T_J2 * ... * J6_T_Tool

每个关节的变换矩阵乘起来,就是末端位姿。这就是正运动学的核心。

我的习惯: 在 HALCON 里,我常用 pose_to_hom_mat3d 把位姿转成齐次矩阵,再用 hom_mat3d_compose 做连续变换。比手算快多了。

3.3 正运动学与逆运动学

这两个概念,你肯定听过。我简单说说我的理解。

  • 正运动学: 知道每个关节的角度,求末端位姿。这是确定的,一个输入对应一个输出。
  • 逆运动学: 知道末端位姿,反推每个关节的角度。这是多解的,同一个位姿可能有多种“姿势”到达。

我在项目里遇到过一个问题:标定完手眼关系后,机器人怎么都走不到目标点。后来发现,是逆运动学选了解析解里最远的那组关节角,导致机器人差点撞到工作台。从那以后,我每次做逆解,都会检查所有可行解,选最安全的那组。

避坑指南: 逆运动学有奇异点。当机器人处于某些特殊姿态(比如手腕伸直),逆解会失效或产生巨大关节速度。我曾经在调试时没注意,机器人直接飞了出去……嗯,从那以后,我每次运动前都会做奇异点检测。

3.4 工具坐标系与工件坐标系

这两个坐标系,是手眼标定的关键。

  • 工具坐标系 (Tool Frame): 固定在机器人末端执行器(比如夹爪、焊枪)上的坐标系。它的原点,通常是工具的有效工作点(TCP, Tool Center Point)。
  • 工件坐标系 (Work Object Frame): 固定在待加工工件上的坐标系。程序里写的点位,都是相对于这个坐标系的。

为什么要区分?因为机器人移动的是工具,而我们要操作的是工件。标定的目的,就是让相机看到的工件位置,能准确映射到机器人工具的运动轨迹上。

举个例子:你让机器人去抓一个螺丝。相机告诉你螺丝在 (100, 200, 50) 毫米处。但这个坐标是相对于相机坐标系的。你需要通过手眼标定矩阵,把它转换到机器人基坐标系下,再结合工具坐标系,算出每个关节该转多少度。

一句话总结: 工具坐标系告诉机器人“我的手在哪”,工件坐标系告诉机器人“我的活在哪”。手眼标定就是搭一座桥,让这两个坐标系能互相理解。

3.5 知识结构图:坐标系与变换关系

下面这张图,是我自己总结的坐标系变换链路。你看完应该能明白,各个坐标系之间是怎么串起来的。

机器人坐标系与变换关系图 坐标系与变换链路 基座坐标系 关节1..6 变换 工具坐标系 正运动学 末端位姿 相机坐标系 手眼标定矩阵 工件坐标系 相机位姿 工件位姿 机器人位姿 说明: 1. 基座→关节→工具:正运动学链路,已知关节角求末端位姿。 2. 相机→手眼矩阵→工件:视觉测量链路,相机看到工件,通过标定矩阵转换到机器人坐标系。 3. 虚线表示:机器人位姿(基座到工具)与手眼矩阵共同决定工件在机器人基座下的位置。

3.6 本章小结

这一章,我们聊了机器人的“语言”——位姿、齐次变换矩阵、正逆运动学,还有工具和工件坐标系。这些都是手眼标定的地基。你想想看,如果连坐标系都搞混,标定出来的矩阵肯定不准。