4. 手眼标定数学原理:AX=XB方程推导、Tsai法与Park法对比、HALCON中hand_eye_calibration算子详解
好,咱们进入第四章。这一章是手眼标定的“硬核”部分——数学原理。很多工程师一看到公式就头疼,我当年也一样。但说实话,搞懂AX=XB这个方程,你才算真正入了手眼标定的门。
别怕,我会用最直白的方式讲清楚。咱们不搞纯数学推导,而是结合工程实践,告诉你每个公式背后的物理意义。
4.1 AX=XB方程:到底在解什么?
先看这个方程长什么样:AX = XB。
这里A、B、X都是4x4的齐次变换矩阵。A和B是已知量,X是我们要求的未知量——也就是相机到机器人基座(眼在手外)或相机到机器人末端(眼在手上)的变换矩阵。
我刚开始接触这个方程时,总觉得它很抽象。后来在产线上调试一个视觉引导抓取项目时,才真正理解了它的物理含义。
咱们拆开来看:
- A:机器人末端在基座坐标系下的位姿变化量(从位置1到位置2)
- B:标定板在相机坐标系下的位姿变化量(从位置1到位置2)
- X:相机到机器人基座的固定变换(眼在手外)
方程AX=XB描述的是一个闭环关系:
“机器人从位姿1移动到2,通过X变换到相机坐标系,再通过B变换到标定板,应该等于通过A变换到机器人基座再通过X变换到相机坐标系。”
说白了,就是同一个物理运动,用不同坐标系描述,结果必须一致。
核心理解:AX=XB的本质是“运动一致性约束”。你移动机器人,相机看到标定板位置变了,这两个变化量之间必须满足一个固定的变换关系——这就是X。
4.2 Tsai法与Park法:两种主流解法
知道了要解什么,接下来就是怎么解。目前主流方法有两种:Tsai法和Park法。我在项目中两种都用过,各有优劣。
| 对比项 | Tsai法(两步法) | Park法(单步法) |
|---|---|---|
| 核心思路 | 先解旋转,再解平移 | 旋转和平移同时求解 |
| 数学工具 | 四元数 + 最小二乘 | 李群李代数 + SVD |
| 精度 | 旋转精度高,平移受旋转误差影响 | 整体精度均衡 |
| 鲁棒性 | 对噪声敏感,需要较多数据点 | 对噪声相对鲁棒 |
| 计算速度 | 快 | 稍慢 |
| 适用场景 | 高精度旋转标定 | 一般工业场景 |
Tsai法:我习惯叫它“两步走”。先解旋转矩阵R,再用R去解平移向量t。优点是旋转精度高,但有个坑——如果旋转解偏了,平移误差会被放大。我曾经在一个精密装配项目里吃过这个亏,后来加了数据筛选才稳住。
Park法:用李代数把旋转和平移放在一个框架里解。说白了就是“一步到位”。它对噪声的容忍度更好,适合现场环境不太理想的场景。我建议新手优先用Park法,容错率高。
我的建议:如果现场标定板摆放规范、数据质量高,用Tsai法能得到更精确的旋转。如果现场干扰多、数据有噪声,用Park法更稳。HALCON默认用的是Park法的改进版本。
4.3 HALCON中hand_eye_calibration算子详解
好,理论讲完了,咱们看看HALCON里怎么落地。核心算子就一个:hand_eye_calibration。
这个算子封装了AX=XB的求解过程。你不需要自己写矩阵运算,但必须理解它的输入输出。
4.3.1 算子原型
hand_eye_calibration( : : CalibDataID, EstimationAlgorithm : Errors)
参数说明:
- CalibDataID:标定数据句柄,通过
create_calib_data创建 - EstimationAlgorithm:估计算法选择,可选值:
'nonlinear'、'linear' - Errors:输出误差,用于评估标定质量
4.3.2 算法选择
我一般这样选:
- 'linear':对应Park法,速度快,适合初步标定
- 'nonlinear':非线性优化,精度更高,但需要好的初值
我的习惯是:先用'linear'跑一遍,看看误差大概多少。如果误差在可接受范围内,再用'nonlinear'精调。这样既快又准。
注意:'nonlinear'算法对初始值敏感。如果初始值偏差太大,可能收敛到局部最优。我建议先用'linear'的结果作为初值,再跑'nonlinear'。
4.3.3 完整标定流程
下面是我在项目中常用的标定代码框架:
* 创建标定数据对象
create_calib_data ('hand_eye_moving_camera', 'calibration_object', CalibDataID)
* 设置相机内参
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', CamParam)
* 设置标定板描述
set_calib_data_calib_object (CalibDataID, 0, CalibObjDescr)
* 循环添加标定数据
for i := 1 to NumPoses by 1
* 读取机器人位姿(从机器人控制器获取)
* 读取标定板位姿(通过find_calib_object获取)
set_calib_data_observ_points (CalibDataID, 0, 0, i, CalibObjPose, RobotPose)
endfor
* 执行标定
hand_eye_calibration (CalibDataID, 'nonlinear', Errors)
* 获取结果
get_calib_data (CalibDataID, 'camera', 0, 'pose', CameraPose)
这段代码我用了不下百次。有几个关键点:
- 机器人位姿和标定板位姿必须一一对应
- 数据量建议10-15组,太少解不稳定,太多计算慢
- 标定过程中机器人姿态变化要足够大,否则旋转解不唯一
4.4 知识结构图
下面这张图总结了本章的核心逻辑:
4.5 避坑指南
最后,分享几个我踩过的坑:
- 数据质量比数量重要:我曾经采集了30组数据,结果因为机器人姿态变化太小,解出来的X误差很大。后来改成15组,但姿态覆盖了工作空间各个角落,效果反而更好。
- 标定板不要太小:标定板在图像中至少占1/3以上,否则位姿解算精度不够。
- 机器人位姿要精确:机器人本身的定位误差会直接传递到标定结果。如果机器人精度不够,标定精度也会受限。
- 检查Errors输出:HALCON的Errors输出包含了旋转误差和平移误差。我一般要求旋转误差小于0.5度,平移误差小于1mm。如果超出这个范围,我会重新采集数据。
我曾经踩过的坑:有一次标定结果一直不好,误差很大。折腾了两天,最后发现是机器人坐标系定义和HALCON默认的坐标系不一致。记住:HALCON用的是右手坐标系,机器人可能用的是左手坐标系。一定要先对齐坐标系定义!
嗯,这一章内容不少。AX=XB方程是手眼标定的核心,理解了它,后面的实操就顺理成章了。Tsai法和Park法各有千秋,HALCON的hand_eye_calibration算子封装得很好,但前提是你得知道它在干什么。