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 知识体系总览

下面这张图帮你理清这几种表示方法的关系:

刚体变换与位姿表示知识体系 刚体变换与位姿表示 刚体变换 旋转 平移 旋转矩阵 欧拉角 四元数 齐次变换矩阵 HALCON推荐路径 计算用齐次变换矩阵 调试用欧拉角 插值用四元数

3.8 在HALCON里怎么选?

我总结了一套自己的选择逻辑:

  1. 做标定计算:用齐次变换矩阵。HALCON的 hom_mat3d 系列函数很完善。
  2. 看结果、调参数:用欧拉角。HALCON的 pose 类型默认是ZYZ欧拉角。
  3. 做轨迹规划、插值:用四元数。HALCON有 quat_to_hom_mat3d 等转换函数。
  4. 写文档、跟客户沟通:用旋转矩阵。虽然啰嗦,但每个元素都有明确几何意义。

核心转换函数速查:

功能 HALCON函数
位姿 → 齐次变换矩阵 pose_to_hom_mat3d
齐次变换矩阵 → 位姿 hom_mat3d_to_pose
四元数 → 齐次变换矩阵 quat_to_hom_mat3d
齐次变换矩阵 → 四元数 hom_mat3d_to_quat

嗯,这一章的内容就到这里。记住:没有最好的表示方法,只有最适合当前场景的。你在项目里遇到位姿相关的坑,多半是表示方法没选对,或者转换时搞混了顺序。