005、四元数与欧拉角互转:一次炸机事故教会我的事
去年夏天,我在调试一架自组四轴时遇到了一个诡异的问题:飞机在地面站里姿态显示正常,但一解锁起飞就疯狂翻滚,不到两秒就炸了。反复检查了传感器数据、PID参数、电机映射,都没发现问题。最后在日志里发现,飞控输出的欧拉角在俯仰超过90度时突然跳变,从85度直接跳到-175度——这是典型的万向锁现象。那一刻我才意识到,自己一直用欧拉角做姿态解算,却从未认真对待过它的致命缺陷。
从那以后,我的飞控代码里所有内部姿态表示全部改用四元数,只在需要人机交互或地面站显示时才转成欧拉角。今天这篇笔记,就聊聊四元数与欧拉角互转的那些坑。
为什么非要用四元数?
很多初学者觉得欧拉角直观,俯仰、横滚、偏航一看就懂。但实际飞控里,欧拉角有三个硬伤:
万向锁:当俯仰角接近±90度时,横滚和偏航会失去一个自由度,导致姿态解算奇异。这不是算法能解决的,是欧拉角数学表示本身的缺陷。
插值困难:两个欧拉角之间做线性插值,得到的中间姿态往往不是最短路径。比如从(0, 0, 0)到(0, 0, 350度),线性插值会绕一大圈,而不是直接转-10度。
计算效率:欧拉角的三角函数运算多,在STM32这类MCU上跑,每次更新姿态都要算sin/cos,CPU开销不小。
四元数没有这些问题。它用四个参数表示旋转,没有奇异点,插值平滑,计算也快。代价就是——人脑很难直观理解四个数的含义。