3. 坐标系定义与转换:地理坐标系、机体坐标系、导航坐标系之间的转换关系
做飞控这么多年,我见过太多新手在坐标系转换上栽跟头。说白了,坐标系就是给飞行器一个「定位基准」。你想想看,如果连自己在哪、朝哪飞都说不清楚,那还谈什么控制?
今天咱们就把这三个核心坐标系——地理坐标系、机体坐标系、导航坐标系——彻底捋清楚。我会结合自己踩过的坑,把转换关系讲透。
3.1 地理坐标系(n系)—— 你的「绝对参考」
地理坐标系,也叫导航坐标系(n系),是固定在地球上的。我习惯用北-东-地(NED)作为标准:
- X轴:指向地理北
- Y轴:指向地理东
- Z轴:指向地心(向下)
为什么用NED而不是ENU?嗯,这里有个小故事。我早期做的一个项目,用了ENU(东-北-天)坐标系,结果跟惯性导航模块的默认输出对不上,调试了整整两天才发现是坐标系方向反了。从那以后,我统一用NED,省心很多。
关键点:地理坐标系是惯性导航的「锚点」。你的加速度计、陀螺仪数据最终都要转换到这个坐标系下才有意义。
3.2 机体坐标系(b系)—— 飞行器的「身体感知」
机体坐标系是固定在飞行器上的。想象你坐在飞机里:
- X轴:指向机头(前进方向)
- Y轴:指向右翼
- Z轴:指向机身下方(符合右手定则)
传感器(IMU)直接输出的数据,就是在这个坐标系下的。比如加速度计测到的重力加速度,在机体坐标系下是 [ax, ay, az],而不是 [0, 0, g]。为什么?因为飞行器在倾斜啊!
我的习惯:在代码里,我会用 b_ 前缀标记机体坐标系下的变量,比如 b_acc、b_gyro。这样一眼就能看出数据来源,避免混淆。
3.3 导航坐标系(n系)—— 你的「控制基准」
导航坐标系其实和地理坐标系是同一个东西,只是叫法不同。在飞控领域,我们通常说「导航坐标系」时,强调的是它作为控制律计算的基准。
举个例子:你想让飞行器往北飞10米。这个「北」是在导航坐标系下定义的。但电机怎么转?你得先把导航坐标系下的指令,转换到机体坐标系下,才能驱动电机。
注意:有些文献把导航坐标系定义为「起始点处的当地水平坐标系」,跟地理坐标系有细微差别。但在实际工程中,我们通常混用。我个人建议统一叫「n系」,省得绕晕。
3.4 坐标系转换的核心:旋转矩阵
好了,三个坐标系定义清楚了。接下来就是怎么转的问题。核心工具是旋转矩阵。
从机体坐标系(b系)到导航坐标系(n系)的转换,用 C_b^n 表示。反过来就是 C_n^b,其实就是转置(因为旋转矩阵是正交矩阵)。
旋转矩阵怎么算?最常用的方法是基于欧拉角(横滚角 φ、俯仰角 θ、偏航角 ψ):
C_b^n = R_z(ψ) * R_y(θ) * R_x(φ)
其中:
R_x(φ) = [1, 0, 0;
0, cos(φ), sin(φ);
0, -sin(φ), cos(φ)]
R_y(θ) = [cos(θ), 0, -sin(θ);
0, 1, 0;
sin(θ), 0, cos(θ)]
R_z(ψ) = [cos(ψ), sin(ψ), 0;
-sin(ψ), cos(ψ), 0;
0, 0, 1]
注意顺序:先绕X轴转 φ,再绕Y轴转 θ,最后绕Z轴转 ψ。这个顺序叫「ZYX顺序」,也是飞控里最常用的。
避坑指南:我曾经在代码里把旋转顺序搞反了,结果飞行器一解锁就往地上栽。检查了半天才发现是矩阵乘法顺序错了。记住:C_b^n 是从b系到n系,乘法顺序是 R_z * R_y * R_x,从右往左读。
3.5 实际应用:加速度计数据转换
咱们来看个实际例子。假设IMU输出的加速度是 b_acc = [0, 0, -9.8](飞行器水平悬停,Z轴向下)。
要把它转到导航坐标系下:
n_acc = C_b^n * b_acc
如果飞行器是水平的(φ=0, θ=0, ψ=0),那么 C_b^n 就是单位矩阵,结果不变。但如果飞行器倾斜了,比如横滚角 φ=30°,那么:
n_acc = [0, 9.8*sin(30°), -9.8*cos(30°)]
= [0, 4.9, -8.49]
你看,在导航坐标系下,Y轴方向出现了加速度分量。这就是为什么我们能通过加速度计估算姿态——因为重力在机体坐标系下的投影会随姿态变化。
3.6 四元数:更优雅的转换方式
欧拉角有个致命问题:万向锁。当俯仰角接近 ±90° 时,横滚和偏航会耦合,导致姿态解算失效。
所以实际工程中,我几乎不用欧拉角做内部计算。我用四元数。
四元数 q = [q0, q1, q2, q3] 表示一个旋转。从b系到n系的旋转矩阵用四元数表示为:
C_b^n = [1-2(q2²+q3²), 2(q1q2 - q0q3), 2(q1q3 + q0q2);
2(q1q2 + q0q3), 1-2(q1²+q3²), 2(q2q3 - q0q1);
2(q1q3 - q0q2), 2(q2q3 + q0q1), 1-2(q1²+q2²)]
看着复杂?其实代码里就是几行乘法。而且四元数没有万向锁问题,计算效率也高。
我的建议:新手可以先从欧拉角理解概念,但实际写代码时直接用四元数。我见过太多人因为欧拉角的万向锁问题,在调试时浪费大量时间。
3.7 知识体系总览
下面这张图是我自己整理的坐标系转换知识体系,你可以把它当作一个快速参考:
3.8 工程中的常见坑
最后,分享几个我实际项目中踩过的坑:
- 坐标系方向搞反:有一次我把Z轴向上当成了向下,结果高度估计直接反了。飞行器一解锁就往天上窜,差点撞到天花板。
- 旋转顺序错误:前面说过,ZYX顺序不能乱。我见过有人用XYZ顺序,结果姿态角全乱套。
- 四元数未归一化:四元数必须保持单位长度。如果忘了归一化,累积误差会让姿态越偏越远。
- 欧拉角与四元数混用:在同一个模块里,有人用欧拉角输入,有人用四元数输出,中间没做转换。这种问题最难查。
我的铁律:在飞控代码里,统一用四元数做内部计算。只在日志输出和用户交互时,才转成欧拉角。这样能避免90%的坐标系相关bug。
好了,坐标系定义与转换就讲到这里。记住一句话:坐标系是飞控的「语言」,搞懂了它,你就能跟飞行器顺畅沟通了。