坐标系与旋转表示:地理坐标系、载体坐标系、欧拉角、旋转矩阵
各位同学,今天我们来聊聊姿态解算里最基础、也最绕不开的东西——坐标系和旋转表示。说实话,我见过不少新手,算法写得飞起,结果坐标系搞反了,整个系统直接炸掉。我自己也踩过这个坑,所以这一章咱们把它彻底讲透。
1. 地理坐标系:我们到底在哪儿?
地理坐标系,说白了就是给地球贴个坐标轴。我们通常用 NED 或 ENU 两种约定。我个人习惯用 NED,也就是北-东-地。
- X轴:指向北(North)
- Y轴:指向东(East)
- Z轴:指向地心(Down)
你想想看,为什么 Z 轴要指向地心?因为重力方向是向下的,这样我们测量加速度时,静止状态下 Z 轴输出就是 +g。嗯,这里要注意,如果你用 ENU 约定,Z 轴是朝上的,那静止时 Z 轴输出就是 -g。我在项目里就吃过这个亏,当时把加速度计装反了,解算出来的俯仰角直接反了 180 度。
重要提醒: 地理坐标系是惯性导航的绝对参考系。所有姿态解算的最终目标,就是把载体坐标系下的测量值,转换到地理坐标系下。
2. 载体坐标系:传感器装在哪儿?
载体坐标系是固定在设备上的。比如你的手机、无人机、或者我手头这块 IMU 板子。通常我们这样定义:
- X轴:指向载体前方(Forward)
- Y轴:指向载体右方(Right)
- Z轴:指向载体下方(Down)
这个坐标系会随着载体一起旋转。你想想看,当无人机抬头时,它的 X 轴就翘起来了。这时候加速度计测到的重力分量,就不再是单纯的 Z 轴了,而是分散到了 X 和 Z 轴上。这就是我们解算姿态的原始依据。
个人经验: 我建议你在做硬件设计时,就把 IMU 的安装方向标清楚。我曾经接手过一个项目,IMU 被焊歪了 45 度,结果软件里还得做一次额外的旋转补偿,麻烦得很。
3. 欧拉角:俯仰、横滚、偏航
欧拉角是描述旋转最直观的方式。三个角度,分别对应三个轴的旋转:
| 角度 | 英文 | 旋转轴 | 范围 |
|---|---|---|---|
| 俯仰角 | Pitch | Y轴(右轴) | -90° ~ +90° |
| 横滚角 | Roll | X轴(前轴) | -180° ~ +180° |
| 偏航角 | Yaw | Z轴(下轴) | -180° ~ +180° |
这里有个经典问题:旋转顺序。我习惯用 Z-Y-X 的顺序,也就是先偏航、再俯仰、最后横滚。为什么?因为这样最符合直觉——你先转方向,再抬头,最后侧倾。如果你顺序搞反了,解算出来的姿态会完全不对。
避坑指南: 我曾经在写四轴飞控时,用了不同的旋转顺序,结果无人机一解锁就翻了个底朝天。后来查了三天代码,才发现是欧拉角顺序没对齐。所以,请务必在代码注释里写明你的旋转顺序!
4. 旋转矩阵:数学工具
欧拉角虽然直观,但计算起来不方便。所以我们用旋转矩阵。说白了,旋转矩阵就是一个 3x3 的矩阵,它能把载体坐标系下的向量,映射到地理坐标系下。
单个轴的旋转矩阵长这样:
// 绕Z轴旋转(偏航)
Rz(yaw) = [cos(yaw) -sin(yaw) 0]
[sin(yaw) cos(yaw) 0]
[0 0 1]
// 绕Y轴旋转(俯仰)
Ry(pitch) = [cos(pitch) 0 sin(pitch)]
[0 1 0]
[-sin(pitch) 0 cos(pitch)]
// 绕X轴旋转(横滚)
Rx(roll) = [1 0 0]
[0 cos(roll) -sin(roll)]
[0 sin(roll) cos(roll)]
完整的旋转矩阵就是这三个矩阵的乘积。按照 Z-Y-X 顺序:
R = Rz(yaw) * Ry(pitch) * Rx(roll)
你想想看,这个矩阵有什么用?举个例子,加速度计测到了载体坐标系下的加速度 [ax, ay, az],想把它转到地理坐标系下,只需要:
[a_north, a_east, a_down] = R * [ax, ay, az]
就这么简单。但要注意,旋转矩阵是正交矩阵,它的逆等于它的转置。这个性质在代码里非常有用,可以省去求逆的麻烦。
核心要点: 旋转矩阵是姿态解算的数学桥梁。你写的卡尔曼滤波、互补滤波,本质上都是在估计这个矩阵里的 9 个元素(或者用四元数表示,那是下一章的内容)。
5. 知识体系总览
为了让你更直观地理解这些概念之间的关系,我画了一张图:
从这张图你可以看到,地理坐标系和载体坐标系是物理概念,而旋转矩阵和欧拉角是数学工具。我们做姿态解算,本质上就是在这四个东西之间来回倒腾。
6. 实战中的选择
在实际项目中,我一般这样选:
- 调试阶段:用欧拉角,因为直观,一眼就能看出姿态对不对。
- 算法内部:用旋转矩阵或四元数,避免万向锁问题,计算也方便。
- 输出给用户:再转回欧拉角,因为用户只看角度。
小技巧: 如果你在代码里看到 atan2 函数,那多半是在从旋转矩阵提取欧拉角。比如从矩阵元素 m[2][1] 和 m[2][2] 算横滚角。这个公式我建议你直接背下来,写代码时能省不少时间。
好了,这一章的内容就到这里。坐标系和旋转表示是姿态解算的基石,你把它搞明白了,后面的卡尔曼滤波、互补滤波学起来就轻松多了。