第9章 坐标系间变换链

码枢沄社 · 嵌入式体系化教程平台
进阶 👤 已理解单个坐标变换,需要串联使用的开发者 🔧 将机器人各部件位姿统一到同一参考系进行计算
本章你将学到
  • 理解变换链的构成与串联原理
  • 掌握变换链的矩阵乘法顺序规则
  • 学会从变换链中提取特定坐标关系
核心概念变换链串联变换

想象一下你在一个陌生的多层商场里问路,保安告诉你:“从你现在的位置(A点),先上到三楼(变换1),然后往东走到底(变换2),再坐扶梯下一层(变换3),就能看到餐厅(B点)。” 这一系列连续的指引,就是一个典型的“变换链”。在机器人中,我们同样需要将多个坐标变换串联起来,才能描述一个部件(如机械臂末端)相对于另一个遥远参考系(如世界地图)的位置。

什么是坐标系变换链?

变换链是指将多个已知的、相邻坐标系之间的变换关系,通过数学运算串联起来,从而得到两个非直接相邻坐标系之间变换关系的过程。它是机器人学中解决“A相对于C在哪里”这类问题的核心工具。

9.1 变换链的构成与表示

一个变换链由一系列已知的齐次变换矩阵组成。每个矩阵描述了一个坐标系相对于其前一个坐标系的位姿。我们用符号 T_A^B 表示从坐标系 A 到坐标系 B 的变换矩阵。

世界 {W}
机器人基座 {B}
机械臂关节 {J}
末端工具 {T}
变换矩阵 T_W^B
变换矩阵 T_B^J
变换矩阵 T_J^T

上图中,我们已知机器人基座在世界中的位姿 T_W^B,机械臂关节相对于基座的位姿 T_B^J,以及末端工具相对于关节的位姿 T_J^T。那么,要计算末端工具在世界坐标系中的位姿 T_W^T,就需要将这些变换串联起来。

9.2 串联变换:矩阵乘法规则

变换链的串联通过矩阵乘法实现,但顺序至关重要。规则是:从目标坐标系出发,沿着链“往回”乘到参考坐标系

对于上图的例子,要得到 T_W^T(工具相对于世界),计算顺序如下:

T_W^B
×
T_B^J
×
T_J^T

用数学公式表示:

// 计算末端工具在世界坐标系中的位姿
Eigen::Matrix4f T_W_T = T_W_B * T_B_J * T_J_T;

⚠️ 常见误区:乘法顺序错误

  • 顺序颠倒:写成 T_J^T * T_B^J * T_W^B。这会导致完全错误的结果,因为矩阵乘法不满足交换律。
  • 混淆“左乘”与“右乘”:在一些图形库或旧教材中,变换矩阵可能采用列向量右乘(p' = M * p)的约定,此时链式乘法顺序恰好相反(从右往左)。ROS的TF2、Eigen等现代库普遍采用左乘约定,本章也基于此。实际开发中,务必确认你所使用库的约定。
  • 忽略变换的“相对性”T_A^B 意味着“从A看B”,如果你有 T_B^A(B相对于A),需要先求逆才能参与链式乘法。

我在一个机械臂抓取项目中踩过这个坑。代码里把基座到世界的变换和关节到基座的变换顺序写反了,导致仿真中机械臂动作看起来一切正常(因为运动是相对的),但一旦要求它去抓取一个在世界坐标系中指定位置的物体,爪子总是跑到莫名其妙的地方去。调试了半天才发现是变换链的乘法顺序错了。

9.3 从变换链中提取关系

更常见的情况是,我们拥有一个复杂的变换链,但需要计算其中任意两个坐标系之间的关系,而不仅仅是首尾两端。

已知完整链,求中间关系

  • 问题:已知 T_W^B, T_B^J, T_J^T,求 T_B^T(工具相对于基座)。
  • 解法:从目标(B)乘到参考(T)的路径:T_B^T = T_B^J * T_J^T

已知部分链,求逆关系

  • 问题:已知 T_W^B(基座在世界中),求 T_B^W(世界在基座中)。
  • 解法:对变换矩阵求逆:T_B^W = (T_W^B).inverse()

组合与分解

  • 问题:已知 T_W^AT_W^B,求 T_A^B
  • 解法:利用链式法则和逆变换:T_A^B = (T_W^A).inverse() * T_W^B

为了更清晰地展示不同需求下的计算路径,可以参考下表:

已知变换目标变换计算公式(左乘约定)生活类比
T_A^B, T_B^CT_A^CT_A^C = T_A^B * T_B^C知道家到地铁站、地铁站到公司,求家到公司。
T_A^BT_B^AT_B^A = (T_A^B).inverse()知道家相对于公司的方位,求公司相对于家的方位。
T_W^A, T_W^BT_A^BT_A^B = (T_W^A).inverse() * T_W^B知道家和公司各自在地图上的位置,求从家看公司的方向。
T_A^B, T_A^CT_B^CT_B^C = (T_A^B).inverse() * T_A^C知道家到公司、家到超市,求公司到超市。

编者提示:性能与数值稳定性
在实际的机器人控制循环中(如每秒100次),频繁进行矩阵乘法和求逆会消耗大量CPU资源。对于固定的变换链部分(如机器人基座与相机之间的刚性连接),应在初始化时预计算好最终的变换矩阵,避免在循环内重复计算。另外,直接对变换矩阵求逆在数学上等价于转置旋转部分并取反平移向量,手动实现这个操作通常比调用通用的矩阵求逆函数更快、数值更稳定。

9.4 机器人中的典型变换链实例

让我们看一个移动机器人搭载机械臂的完整例子。假设我们有以下坐标系:

现在,任务是将物体在相机坐标系中的坐标 p_Camera,转换到世界坐标系 p_World,以便规划机器人的移动和抓取。

首先,我们需要建立从 {World}{Object} 的变换链:

World
Base
Arm_Base
Arm_End
Camera
Object

对应的变换矩阵乘法为:

// 已知各个相邻坐标系间的变换
Eigen::Matrix4f T_W_B; // 来自机器人里程计或定位系统
Eigen::Matrix4f T_B_ArmB; // 机械臂基座安装偏移,固定值
Eigen::Matrix4f T_ArmB_ArmE; // 机械臂正向运动学结果,随关节角变化
Eigen::Matrix4f T_ArmE_Cam; // 手眼标定结果,固定值
Eigen::Matrix4f T_Cam_Obj; // 由视觉算法得出,物体相对于相机

// 计算物体在世界坐标系中的位姿
Eigen::Matrix4f T_W_Obj = T_W_B * T_B_ArmB * T_ArmB_ArmE * T_ArmE_Cam * T_Cam_Obj;

// 如果已知物体在相机坐标系中的坐标点 p_camera
Eigen::Vector4f p_camera(x, y, z, 1.0);
Eigen::Vector4f p_world = T_W_Obj * p_camera; // 注意:这里T_W_Obj已将物体坐标系对齐到世界,所以直接乘p_camera即可得到p_world
// 更准确地说,应该是:p_world = T_W_Cam * p_camera,其中 T_W_Cam = T_W_B * ... * T_ArmE_Cam
// 而 p_camera 本身是 T_Cam_Obj 的平移部分,或者由 T_Cam_Obj 变换零向量得到。

关键点:理解“变换点”与“变换坐标系”
在上面的代码注释中有一个精妙之处。我们通常说“用变换矩阵 T_A^B 将点从坐标系 A 变换到坐标系 B”,公式为 p_B = T_A^B * p_A。但在变换链末端,当我们有 T_Cam_Obj 时,它表示物体坐标系相对于相机坐标系的位姿。物体本身的坐标在其自己的坐标系中原点是 (0,0,0)。所以,物体在世界中的位置,其实就是 T_W_Obj 这个矩阵的平移向量部分。如果视觉算法直接给出了物体在相机坐标系中的三维坐标点 p_camera,那么它应该是由 T_Cam_Obj 变换零向量得到的,即 p_camera = T_Cam_Obj * [0,0,0,1]^T 的平移部分。这时,用 T_W_Cam 去乘 p_camera 才是正确的。实际开发中,一定要厘清你手中的数据是“一个位姿变换矩阵”还是一个“在某个坐标系下的三维点”。

这个例子展示了变换链如何将感知(相机看到的物体)、控制(机械臂关节角度)和状态估计(机器人在地图中的位置)融合到一个统一的数学框架中。如果其中任何一个变换不准确,最终计算出的物体世界位姿就会出错,导致抓取失败。

动手试一试

假设你有一个简单的机器人系统,已知以下固定变换(单位:米,角度为绕Z轴旋转):

  • T_Base_Laser: 激光雷达安装在机器人基座前方0.2米,正前方,无旋转。平移为 (0.2, 0, 0)。
  • T_Base_Camera: 相机安装在基座上方0.1米,后方0.05米,绕X轴向下倾斜30度(即俯仰角-30度)。

现在,激光雷达检测到正前方1米处有一个障碍物,点在激光雷达坐标系中的坐标为 (1.0, 0, 0)。

  1. 请计算这个障碍物点在机器人基座坐标系(Base)中的坐标。
  2. 请计算这个障碍物点在相机坐标系(Camera)中的坐标。(提示:你需要用到从Base到Camera的变换,注意它是T_Base_Camera的逆)
  3. 尝试用Eigen库或你熟悉的数学库编写代码验证你的计算。思考:如果相机图像中也看到了这个障碍物,你如何验证激光雷达和相机的数据是否对齐?

检验你的理解

  1. 判断题:已知变换矩阵 T_A^BT_B^C,要计算点p在坐标系C中的坐标,正确的计算顺序是 p_C = T_B^C * T_A^B * p_A
  2. 选择题:你拥有机器人基座到世界(T_W^B)和机械臂末端到基座(T_B^E)的变换矩阵。现在需要计算机械臂末端在世界坐标系中的位置,你应该:
    • A. 计算 T_W^E = T_W^B * T_B^E
    • B. 计算 T_W^E = T_B^E * T_W^B
    • C. 计算 T_W^E = (T_W^B).inverse() * T_B^E
    • D. 计算 T_W^E = (T_B^E).inverse() * T_W^B
  3. 判断题:对于两个坐标系A和B,变换矩阵 T_A^BT_B^A 是相等的。

本章小结

  • 变换链的本质:通过串联相邻坐标变换,求解非相邻坐标系间关系的数学工具,核心是矩阵乘法。
  • 核心规则:采用左乘约定时,从目标坐标系开始,沿变换链“向左”连续乘到参考坐标系。顺序错误是导致bug的常见原因。
  • 关键操作:除了串联乘法,还包括对变换矩阵求逆以获得反向关系,以及组合已知的世界坐标变换来求解相对关系。
  • 应用模式:机器人系统中,典型的变换链融合了定位(世界-基座)、运动学(基座-末端)、标定(末端-传感器)和感知(传感器-物体)信息。
  • 实践要点:务必分清手中数据是“位姿变换矩阵”还是“在某一坐标系下的点坐标”,这是正确应用变换链的前提。
← 上一章 返回目录 下一章 →