3. 坐标系与变换链:机器人基座、工具、相机、标定板之间的坐标变换关系
手眼标定,说白了就是搞清楚几个坐标系之间到底怎么转的。你想想看,机器人要抓一个东西,它得知道自己的手在哪儿,相机得知道看到的东西在哪儿,这两者之间得有个“翻译官”。这个翻译官,就是坐标变换链。
我刚开始做标定的时候,总觉得不就是几个矩阵相乘嘛,有什么难的?结果第一次现场调试,机器人撞了夹具,相机拍了半天找不到点。后来才发现,坐标系定义错了,整个变换链都是乱的。嗯,从那以后,我每次做标定前,都会先把坐标系图画出来。
3.1 四个核心坐标系
手眼系统里,我们主要跟四个坐标系打交道。记住它们的定义,后面就不会乱。
| 坐标系 | 符号 | 描述 | 典型原点 |
|---|---|---|---|
| 机器人基座坐标系 | {B} | 机器人的世界原点,所有运动都基于它 | 机器人底座安装面中心 |
| 工具坐标系 | {T} | 机器人末端执行器的位姿 | 法兰盘中心或工具尖端 |
| 相机坐标系 | {C} | 相机光心为原点,Z轴指向拍摄方向 | 相机光心 |
| 标定板坐标系 | {P} | 标定板上的特征点定义的世界 | 棋盘格左上角或中心 |
关键点:这四个坐标系不是孤立的。它们通过刚体变换(旋转+平移)连接在一起,形成一个闭环。任何一个环节定义错了,标定结果就是错的。
3.2 变换链的数学表达
我们用一个4x4的齐次变换矩阵来表示两个坐标系之间的关系。比如,BTT 表示从工具坐标系 {T} 到基座坐标系 {B} 的变换。
整个手眼系统的变换链可以写成:
B_T_P = B_T_T * T_T_C * C_T_P
其中:
- B_T_P:标定板在机器人基座坐标系下的位姿(已知,由机器人运动学算出)
- B_T_T:工具在基座坐标系下的位姿(从机器人控制器读取)
- T_T_C:相机在工具坐标系下的位姿(这就是我们要标定的手眼矩阵!)
- C_T_P:标定板在相机坐标系下的位姿(由相机拍摄标定板图像算出)
我的习惯:每次写代码前,我会在纸上把变换链画出来,标清楚每个矩阵的上下标。比如 B_T_T 的“B”是目标坐标系,“T”是源坐标系。这样写代码时不容易搞反。
3.3 两种典型配置:眼在手上 vs 眼在手外
根据相机安装位置,手眼系统分两种。我见过不少新手在这上面栽跟头。
3.3.1 眼在手上(Eye-in-Hand)
相机固定在机器人末端,跟着工具一起动。这是最常见的配置。
- 变换链:B_T_P = B_T_T * T_T_C * C_T_P
- 标定目标:求 T_T_C(相机相对于工具的位姿)
- 特点:相机视野随机器人移动,适合大范围作业
3.3.2 眼在手外(Eye-to-Hand)
相机固定在工作台上,不随机器人移动。
- 变换链:B_T_P = B_T_C * C_T_P
- 标定目标:求 B_T_C(相机相对于机器人基座的位姿)
- 特点:相机视野固定,适合小范围高精度作业
我曾经踩过的坑:有一次做眼在手外标定,我直接把眼在手上的代码拿过来改,结果变换链写反了。标定出来的矩阵,机器人抓东西差了5厘米。后来花了半天时间排查,才发现是 T_T_C 和 B_T_C 搞混了。所以,配置不同,变换链完全不同,千万别偷懒。
3.4 变换链的误差传递
为什么标定精度上不去?很多时候不是算法问题,是变换链里的误差在累积。
每个变换矩阵都有误差:
- B_T_T 的误差:来自机器人运动学参数(连杆长度、关节零点等)
- C_T_P 的误差:来自相机内参标定、角点检测精度
- T_T_C 的误差:来自标定算法本身的数值稳定性
这些误差通过矩阵乘法一层层传递。最终标定结果的误差,是各个环节误差的叠加。我做过一个实验:
| 误差来源 | 典型误差量 | 对标定结果的影响 |
|---|---|---|
| 机器人运动学 | 0.1-0.5 mm | 平移误差直接叠加 |
| 相机内参 | 0.1-0.3 像素 | 旋转误差放大 |
| 角点检测 | 0.05-0.2 像素 | 随机噪声 |
| 标定算法 | 0.01-0.1 mm | 数值稳定性 |
结论:想提高标定精度,不能只盯着算法。你得先看看机器人本身准不准,相机标定做没做好。我曾经在一个项目里,花了两周优化标定算法,精度只提升了0.1mm。后来发现是机器人末端重复定位精度就有0.3mm,算法再怎么优化也没用。
3.5 坐标系与变换链的SVG结构图
下面这张图,是我每次做标定前都会画的。它把四个坐标系和变换关系一目了然地展示出来。
3.6 实际项目中的变换链检查清单
每次做标定前,我会按这个清单过一遍。你可以直接拿去用。
- 确认坐标系定义:机器人基座原点在哪?工具坐标系是法兰盘还是工具尖端?
- 确认相机安装方式:眼在手上还是眼在手外?变换链公式选对了没?
- 确认标定板方向:标定板坐标系的原点和轴方向,跟算法里定义的是否一致?
- 验证单个变换:每个变换矩阵单独验证一下,比如 B_T_T 读出来的值跟机器人示教器上显示的是否一致?
- 闭环验证:用标定结果反算一个已知点,看看误差有多大。
一个小技巧:我习惯在标定前,先让机器人走几个固定姿态,用相机拍标定板,然后手动算一下变换链。如果算出来的结果跟预期差太多,说明某个环节定义错了。别急着跑标定算法,先排查问题。
3.7 常见坐标系定义错误
我整理了几个最常见的错误,你遇到了可以对照排查。
| 错误类型 | 现象 | 后果 |
|---|---|---|
| 基座坐标系方向搞反 | 机器人运动方向跟预期相反 | 标定结果旋转误差大 |
| 工具坐标系未更新 | 换了工具没重新标定TCP | 平移误差可达数厘米 |
| 相机坐标系轴定义不一致 | OpenCV的坐标系跟机器人坐标系不同 | 旋转矩阵完全错误 |
| 标定板原点选错 | 棋盘格左上角和右下角搞混 | 平移误差固定偏移 |
特别提醒:不同品牌的机器人,坐标系定义可能不一样。比如ABB的基座坐标系Z轴向上,而发那科的Z轴可能指向不同方向。做标定前,一定要看机器人手册,确认坐标系定义。我曾经因为没看手册,直接用默认配置,结果标定出来的矩阵在另一台机器人上完全不能用。
坐标系和变换链,是手眼标定的地基。地基没打好,上面盖的房子再漂亮也没用。我建议你每次做标定前,花10分钟把变换链画清楚,把每个矩阵的物理意义想明白。这10分钟,能帮你省下后面几小时的排查时间。