3. 刚体变换与位姿表示
做手眼标定,说白了就是在处理一个核心问题:怎么描述一个物体在空间里又转又挪。
我刚开始接触3D视觉时,觉得这东西就是数学公式堆砌。直到第一次在现场调标定,机器人死活抓不准工件,我才意识到——位姿表示选错了,后面全白干。
这一章,咱们就把刚体变换的几种“语言”彻底捋清楚。你会在HALCON里反复跟它们打交道。
3.1 刚体变换:空间里的“刚”道理
什么叫刚体?就是不会变形的物体。你推它、转它,它内部点与点的距离保持不变。
在3D视觉里,我们处理的工件、相机、机器人末端,都视为刚体。刚体变换只有两种运动:旋转和平移。
核心公式:
P' = R · P + t
其中 P 是原始点坐标,R 是旋转矩阵,t 是平移向量,P' 是变换后的点。
我在项目里见过有人把旋转和平移分开算,结果坐标系一多就乱套。记住:旋转是核心,平移是补充。
3.2 旋转矩阵:最直观,但最啰嗦
旋转矩阵是一个 3×3 的正交矩阵,行列式为 +1。它描述了三个坐标轴分别怎么转。
| 属性 | 说明 |
|---|---|
| 维度 | 3×3 |
| 自由度 | 3(9个元素,6个约束条件) |
| 正交性 | RTR = I |
| 行列式 | det(R) = +1 |
举个例子,绕Z轴转30°的旋转矩阵长这样:
R_z(30°) =
[ cos30° -sin30° 0 ]
[ sin30° cos30° 0 ]
[ 0 0 1 ]
我的习惯:在HALCON里,我几乎不用手写旋转矩阵。直接用 hom_mat3d_rotate 生成,省心又不出错。
3.3 平移向量:简单,但别搞反方向
平移向量就是一个 3×1 的列向量,表示沿X、Y、Z轴分别移动多少。
t = [tx, ty, tz]^T
这里有个坑:平移的方向取决于你从哪个坐标系看。我曾经在标定时把相机到机器人的平移方向搞反了,结果机器人差点撞到夹具。嗯,从那以后我每次都会画个坐标系草图再填数值。
3.4 齐次变换矩阵:把旋转和平移打包
旋转矩阵和平移向量分开写,在连续变换时很麻烦。齐次变换矩阵把它们合二为一:
T = [ R t ]
[ 0 1 ]
这是一个 4×4 的矩阵。用齐次坐标表示点 P = [x, y, z, 1]^T,变换就变成了矩阵乘法:
P' = T · P
这样做的好处是:多次变换可以连乘。比如从相机到机器人,中间经过工具坐标系:
T_cam_to_robot = T_tool_to_robot · T_cam_to_tool
HALCON实战:在HALCON里,齐次变换矩阵用 hom_mat3d 类型表示。创建方式:
create_pose(0, 0, 0, 0, 0, 0, 'Rp+T', 'gba', 'point', Pose)
hom_mat3d_identity(HomMat3D)
hom_mat3d_translate(HomMat3D, tx, ty, tz, HomMat3D)
hom_mat3d_rotate(HomMat3D, angle, 'x', 0, 0, 0, HomMat3D)
3.5 欧拉角:直观,但有万向锁
欧拉角用三个角度表示旋转:绕X轴(滚转)、绕Y轴(俯仰)、绕Z轴(偏航)。
| 表示方式 | 旋转顺序 | 常见场景 |
|---|---|---|
| ZYX | 先绕Z,再绕Y,最后绕X | 机器人末端姿态 |
| ZYZ | 先绕Z,再绕Y,再绕Z | HALCON默认方式 |
| XYZ | 先绕X,再绕Y,再绕Z | 相机姿态 |
避坑指南:我曾经在标定脚本里用了ZYX欧拉角,但HALCON默认是ZYZ。结果算出来的位姿全错。后来我统一用 pose_to_hom_mat3d 转换,再也不纠结顺序了。
欧拉角最大的问题是万向锁:当第二个旋转角为±90°时,第一个和第三个旋转轴重合,丢失一个自由度。你想想看,如果机器人正在抓取一个垂直放置的工件,突然姿态跳变——那画面太美我不敢看。
3.6 四元数:无奇点,但难直观
四元数用四个数表示旋转:q = [w, x, y, z],其中 w 是实部,x、y、z 是虚部。
它的好处:
- 无万向锁:任何姿态都能平滑表示
- 插值平滑:做轨迹规划时不会出现姿态突变
- 计算高效:比旋转矩阵少乘法
但缺点也很明显:不直观。你看到 [0.707, 0, 0.707, 0] 能想象出它代表绕Y轴转90°吗?反正我不能。
我的建议:在HALCON里,我习惯用齐次变换矩阵做计算,用欧拉角做调试显示,用四元数做轨迹插值。各取所长。
3.7 知识体系总览
下面这张图帮你理清这几种表示方法的关系:
3.8 在HALCON里怎么选?
我总结了一套自己的选择逻辑:
- 做标定计算:用齐次变换矩阵。HALCON的
hom_mat3d系列函数很完善。 - 看结果、调参数:用欧拉角。HALCON的
pose类型默认是ZYZ欧拉角。 - 做轨迹规划、插值:用四元数。HALCON有
quat_to_hom_mat3d等转换函数。 - 写文档、跟客户沟通:用旋转矩阵。虽然啰嗦,但每个元素都有明确几何意义。
核心转换函数速查:
| 功能 | HALCON函数 |
|---|---|
| 位姿 → 齐次变换矩阵 | pose_to_hom_mat3d |
| 齐次变换矩阵 → 位姿 | hom_mat3d_to_pose |
| 四元数 → 齐次变换矩阵 | quat_to_hom_mat3d |
| 齐次变换矩阵 → 四元数 | hom_mat3d_to_quat |
嗯,这一章的内容就到这里。记住:没有最好的表示方法,只有最适合当前场景的。你在项目里遇到位姿相关的坑,多半是表示方法没选对,或者转换时搞混了顺序。