数学基础(上):刚体变换与齐次坐标、旋转矩阵、欧拉角、四元数

各位同学,欢迎来到《激光雷达与相机外参标定实战》的第一章。

说实话,很多做感知的工程师,一听到「数学基础」四个字就想跳过。我当年也一样,觉得写代码才是硬功夫。直到有一次,我在做多传感器融合时,因为旋转矩阵用错了符号,导致整个点云投影到图像上偏移了十几个像素。排查了整整两天,最后发现是欧拉角顺序搞反了。嗯,从那以后,我再也不敢轻视这部分内容了。

这一章,我们不讲虚的。直接上干货,把刚体变换、齐次坐标、旋转矩阵、欧拉角、四元数这几个核心概念,用实战工程师的视角捋一遍。

1. 刚体变换:传感器在空间中的「搬家」

什么叫刚体变换?说白了,就是你把一个物体从位置A挪到位置B,过程中不捏扁、不拉长、不扭曲。激光雷达和相机之间的外参标定,本质上就是在求一个刚体变换矩阵。

刚体变换由两部分组成:旋转和平移。

  • 旋转:描述传感器坐标系之间的朝向关系。比如激光雷达的X轴,对应相机坐标系的哪个方向。
  • 平移:描述两个传感器原点之间的物理偏移。比如激光雷达装在相机上方10厘米,右侧5厘米。

我个人的习惯是,先理解旋转,再理解平移。因为旋转搞错了,平移再准也没用。

核心公式:

点P在坐标系A中的坐标 PA,变换到坐标系B中的坐标 PB:

PB = R * PA + t

其中R是旋转矩阵,t是平移向量。

2. 齐次坐标:把旋转和平移「打包」

你想想看,上面那个公式里,旋转是矩阵乘法,平移是向量加法。每次变换都要做两步操作,写代码时容易漏掉平移。有没有办法把旋转和平移合并成一个操作?

有,就是齐次坐标。

齐次坐标的核心思想很简单:给三维点(x, y, z)加一个维度,变成(x, y, z, 1)。然后旋转矩阵R和平移向量t可以拼成一个4x4的矩阵:

| R   t |
| 0   1 |

这样,一次矩阵乘法就完成了旋转+平移。我在项目中经常用这个技巧,尤其是在写标定代码时,用齐次矩阵可以避免很多低级错误。

实战小技巧:

在代码中,我习惯用4x4齐次矩阵表示外参。这样无论是点云变换、坐标转换,还是多传感器串联,都只需要做矩阵乘法。干净利落。

3. 旋转矩阵:最直观,但最啰嗦

旋转矩阵是一个3x3的正交矩阵,行列式为+1。它的每一列,代表原坐标系的一个轴在新坐标系中的投影。

举个例子,绕Z轴旋转θ角:

R_z(θ) = | cosθ  -sinθ  0 |
         | sinθ   cosθ  0 |
         | 0      0     1 |

旋转矩阵的好处是直观,你一眼就能看出每个轴怎么转。但坏处也很明显——9个元素,其实只有3个自由度。冗余信息太多,而且容易受数值误差影响,导致矩阵不再是正交的。

我记得有一次做标定优化,迭代几次后旋转矩阵的行列式变成了0.98,结果点云全歪了。从那以后,我很少直接用旋转矩阵做优化。

避坑指南:

我曾经在代码里直接用9个参数优化旋转矩阵,结果收敛到非正交矩阵。后来改用四元数,问题迎刃而解。记住:旋转矩阵适合表示,不适合优化。

4. 欧拉角:直观但容易「万向锁」

欧拉角用三个角度表示旋转:绕X轴转(roll)、绕Y轴转(pitch)、绕Z轴转(yaw)。

为什么说它直观?因为你可以想象成:先低头(pitch),再摇头(yaw),最后歪头(roll)。每个角度都有物理意义。

但欧拉角有个致命问题——万向锁。当pitch接近±90°时,roll和yaw会变得无法区分。说白了,你失去了一个自由度。

我在做车载激光雷达标定时,遇到过这个问题。车辆在坡道上,pitch角接近90°,结果欧拉角表示下的旋转矩阵突然跳变。嗯,从那以后,我标定代码里只用四元数做内部计算,欧拉角只用来给人看。

表示方式 优点 缺点
旋转矩阵 直观,无奇异性 冗余,不适合优化
欧拉角 物理意义明确 万向锁,插值困难
四元数 紧凑,无奇异性,适合插值 不够直观

5. 四元数:工程师的「瑞士军刀」

四元数,说白了就是一个有四个分量的超复数:q = w + xi + yj + zk。其中w是实部,(x, y, z)是虚部。

为什么它这么重要?三个原因:

  • 紧凑:4个参数,没有冗余。
  • 无奇异性:不会出现万向锁。
  • 适合插值:球面线性插值(Slerp)可以平滑过渡。

我个人的习惯是,所有内部计算都用四元数。只有在最后输出给用户看时,才转成欧拉角。

四元数转旋转矩阵(Python示例):

import numpy as np

def quat_to_rot(q):
    w, x, y, z = q
    R = np.array([
        [1 - 2*y*y - 2*z*z, 2*x*y - 2*w*z, 2*x*z + 2*w*y],
        [2*x*y + 2*w*z, 1 - 2*x*x - 2*z*z, 2*y*z - 2*w*x],
        [2*x*z - 2*w*y, 2*y*z + 2*w*x, 1 - 2*x*x - 2*y*y]
    ])
    return R

6. 知识体系总览

下面这张图,是我自己总结的本章知识体系。你可以把它当作一个「导航图」,随时回来对照。

刚体变换 齐次坐标 (4x4矩阵) 旋转矩阵 (3x3) 欧拉角 (roll/pitch/yaw) 四元数 (w, x, y, z) 外参标定 / 坐标变换 核心概念 表示方式 应用

7. 总结与个人建议

这一章的内容,说白了就是一句话:用四元数做计算,用欧拉角做展示,用齐次矩阵做变换。

我刚开始做标定时,总想着把所有东西都搞懂再动手。后来发现,先跑通一个最简单的标定流程,再回头理解数学,效率反而更高。你想想看,代码跑通了,你自然就知道哪里容易出问题,数学也就有了落脚点。

下一章,我们会进入实战环节——用Python实现一个简单的旋转矩阵和四元数互转工具。到时候,我会把今天讲的这些数学概念,全部写成可运行的代码。

课后练习:

1. 写一个函数,将欧拉角(roll, pitch, yaw)转换为四元数。

2. 验证:绕Z轴旋转90°,再绕X轴旋转90°,与先绕X轴再绕Z轴,结果是否相同?为什么?

3. 用齐次矩阵表示:点(1, 0, 0)先平移(1, 0, 0),再绕Y轴旋转90°,求最终坐标。

可可精品资料库