2. 坐标系与姿态表示:地理坐标系、机体坐标系、欧拉角与四元数
飞控算法里,坐标系和姿态表示是地基中的地基。说白了,你连无人机“朝哪飞”、“怎么转”都描述不清楚,后面什么控制、导航全是空中楼阁。
我个人习惯,每次带新人入门,第一件事就是让他们把这三个概念刻在脑子里:地理坐标系、机体坐标系,以及姿态的数学表达。今天我们就来把这层窗户纸捅破。
2.1 地理坐标系:无人机眼中的“世界”
地理坐标系,也叫导航坐标系。你可以把它想象成一个固定在起飞点的三维空间直角坐标系。
- X轴:指向正北(或正东,看具体定义)
- Y轴:指向正东(或正北)
- Z轴:指向地心(也就是“向下”)
嗯,这里要注意:Z轴向下是航空界的惯例。为什么?因为这样定义,高度越高,Z值越小(负得越多)。虽然反直觉,但行业标准就是这样,别问为什么,记住就行。
核心作用:地理坐标系是无人机的“绝对参考系”。GPS给出的经纬高、航线规划的目标点、返航点,全部基于这个坐标系。
我在项目中遇到过一个问题:有次试飞,无人机返航时总是偏左几米。查了半天,发现是GPS模块的安装方向偏了1度,导致地理坐标系下的航向角有偏差。你看,坐标系不准,飞控再牛也白搭。
2.2 机体坐标系:无人机“自己”的视角
机体坐标系是固定在无人机机身上的坐标系。它跟着飞机一起转。
- X轴:指向机头方向(前进方向)
- Y轴:指向机身右侧(右翼方向)
- Z轴:指向机身下方(符合右手定则)
你想想看,无人机上的传感器——IMU(惯性测量单元)、磁力计、气压计——它们测量的原始数据,都是基于机体坐标系的。比如加速度计测的是“机体坐标系下的加速度”,陀螺仪测的是“机体坐标系下的角速度”。
我的习惯:在代码里,我会用 body_frame 或 BODY 作为变量前缀,提醒自己这是机体坐标系下的量。比如 body_accel、body_gyro。
但问题来了:飞控要控制无人机“往北飞”,而传感器只知道“机头方向有加速度”。这两个坐标系之间怎么转换?这就引出了姿态表示。
2.3 欧拉角:最直观的姿态表示
欧拉角用三个角度来描述机体坐标系相对于地理坐标系的旋转:偏航角(Yaw)、俯仰角(Pitch)、横滚角(Roll)。
| 角度 | 旋转轴 | 范围 | 物理意义 |
|---|---|---|---|
| 偏航角 (Yaw, ψ) | Z轴 | -180° ~ 180° | 机头指向(北偏东为正) |
| 俯仰角 (Pitch, θ) | Y轴 | -90° ~ 90° | 机头抬起/低下(抬头为正) |
| 横滚角 (Roll, φ) | X轴 | -180° ~ 180° | 机身左右倾斜(右倾为正) |
欧拉角的好处是直观。你一看“偏航30度,俯仰10度,横滚5度”,脑子里就能大概想象出飞机的姿态。
我曾经踩过一个坑:欧拉角有“万向锁”问题。当俯仰角接近±90度时,偏航和横滚会失去一个自由度,导致姿态解算出现奇异。所以,在飞控内部做姿态解算和插值时,我几乎不用欧拉角,而是用四元数。
2.4 四元数:飞控工程师的“瑞士军刀”
四元数是一个超复数,形式为 q = w + xi + yj + zk,其中 w 是实部,x, y, z 是虚部。它用四个数来表示三维空间中的旋转。
为什么飞控里非要用四元数?三个原因:
- 无万向锁:随便你怎么转,四元数都能平滑表示。
- 计算效率高:旋转组合只需要四元数乘法,比欧拉角转矩阵快得多。
- 插值平滑:用球面线性插值(SLERP)可以在两个姿态之间做平滑过渡。
我个人习惯,在飞控代码里,姿态的“内部存储”和“运算”全部用四元数。只在需要给地面站显示、或者做简单逻辑判断时,才转成欧拉角。
下面是一个简单的四元数转欧拉角的代码片段,我经常在调试时用:
// 四元数转欧拉角(弧度)
void quaternion_to_euler(float q[4], float *roll, float *pitch, float *yaw) {
// 计算俯仰角(注意asin的范围限制)
float sinr_cosp = 2.0f * (q[0]*q[1] + q[2]*q[3]);
float cosr_cosp = 1.0f - 2.0f * (q[1]*q[1] + q[2]*q[2]);
*roll = atan2f(sinr_cosp, cosr_cosp);
float sinp = 2.0f * (q[0]*q[2] - q[3]*q[1]);
if (fabsf(sinp) >= 1.0f)
*pitch = copysignf(M_PI/2.0f, sinp); // 处理万向锁
else
*pitch = asinf(sinp);
float siny_cosp = 2.0f * (q[0]*q[3] + q[1]*q[2]);
float cosy_cosp = 1.0f - 2.0f * (q[2]*q[2] + q[3]*q[3]);
*yaw = atan2f(siny_cosp, cosy_cosp);
}
避坑指南:四元数一定要归一化!我见过太多新手因为忘记归一化,导致姿态越算越飘。每次更新完四元数,记得做 q = q / norm(q)。
2.5 知识体系总览
为了让你更直观地理解这三者之间的关系,我画了一张图:
这张图把整个逻辑串起来了。你从传感器拿到的是机体坐标系下的数据,经过姿态解算(四元数),转换成地理坐标系下的量,才能做导航和控制。
2.6 实战中的选择建议
说了这么多,到底什么时候用欧拉角,什么时候用四元数?我总结一下:
- 显示和日志:用欧拉角。人看得懂,调试方便。
- 姿态解算(AHRS/INS):用四元数。稳定、无奇异。
- 控制律计算:用四元数或旋转矩阵。避免欧拉角的非线性问题。
- 航点规划:用地理坐标系下的位置和欧拉角。直观。
一句话总结:地理坐标系是“世界”,机体坐标系是“自我”,欧拉角是“人话”,四元数是“机器语言”。飞控工程师的工作,就是在这四者之间自由切换。
好了,坐标系和姿态表示就讲到这里。这些东西看似基础,但每次我遇到飞控bug,十有八九都能追溯到坐标系搞混或者姿态转换出错。希望你能把这些概念刻在脑子里,后面讲悬停控制和航线规划时,我们还会反复用到它们。
公众号:蓝海资料掘金营,微信deep3321