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

下面这张图是我自己整理的坐标系转换知识体系,你可以把它当作一个快速参考:

坐标系定义与转换知识体系 地理坐标系 (n系) NED:北-东-地 绝对参考基准 机体坐标系 (b系) 前-右-下 传感器原始数据 导航坐标系 (n系) 控制律计算基准 与地理坐标系相同 C_b^n C_b^n 欧拉角法 直观但存在万向锁 四元数法 无奇点,工程首选 典型应用场景 姿态解算:加速度计/陀螺仪数据融合 控制律:位置环/速度环指令转换 GPS导航:经纬度转NED坐标 视觉SLAM:相机坐标系与世界坐标系对齐

3.8 工程中的常见坑

最后,分享几个我实际项目中踩过的坑:

  • 坐标系方向搞反:有一次我把Z轴向上当成了向下,结果高度估计直接反了。飞行器一解锁就往天上窜,差点撞到天花板。
  • 旋转顺序错误:前面说过,ZYX顺序不能乱。我见过有人用XYZ顺序,结果姿态角全乱套。
  • 四元数未归一化:四元数必须保持单位长度。如果忘了归一化,累积误差会让姿态越偏越远。
  • 欧拉角与四元数混用:在同一个模块里,有人用欧拉角输入,有人用四元数输出,中间没做转换。这种问题最难查。

我的铁律:在飞控代码里,统一用四元数做内部计算。只在日志输出和用户交互时,才转成欧拉角。这样能避免90%的坐标系相关bug。

好了,坐标系定义与转换就讲到这里。记住一句话:坐标系是飞控的「语言」,搞懂了它,你就能跟飞行器顺畅沟通了。


专注资料整理