四元数在无人机姿态解算中的实战应用:从理论到代码实现

当你的无人机在强风中突然倾斜30度时,飞控系统如何在0.01秒内完成姿态修正?这个看似神奇的过程,核心秘密就藏在四元数这个数学工具里。不同于传统欧拉角会遇到的"万向节死锁"问题,四元数通过四个维度的数值就能完整描述三维空间中的任意旋转,这正是现代无人机飞控的首选方案。

1. 四元数基础与无人机姿态的数学表达

四元数由数学家哈密顿在1843年提出,形式上可以记作Q = q0 + q1i + q2j + q3*k。对于无人机应用,我们通常使用单位四元数(满足q0²+q1²+q2²+q3²=1),其中:

  • 实部q0表示旋转角度
  • 虚部(q1,q2,q3)构成旋转轴向量

在STM32飞控开发中,常用以下结构体存储四元数:

typedef struct {
    float q0;  // 实部
    float q1;  // i分量
    float q2;  // j分量 
    float q3;  // k分量
} Quaternion;

四元数相比欧拉角的优势主要体现在:

特性欧拉角四元数
维度3个参数4个参数
奇异点存在(万向节锁)无
计算效率中等高(仅乘法运算)
插值平滑度差优秀(SLERP)

提示:当无人机做90度俯仰时,欧拉角会出现万向节锁导致姿态解算失效,而四元数则完全不受影响。

2. 传感器数据到四元数的转换实战

MPU6050输出的原始数据包含三轴加速度计和三轴陀螺仪数据,我们需要通过传感器融合算法得到四元数。Mahony滤波算法因其在STM32上的高效实现而被广泛采用:

void MahonyUpdate(float gx, float gy, float gz, float ax, float ay, float az, Quaternion *q) {
    float recipNorm;
    float vx, vy, vz;
    float ex, ey, ez;  // 误差项
    
    // 标准化加速度计测量值
    recipNorm = 1.0f / sqrt(ax * ax + ay * ay + az * az);
    ax *= recipNorm;
    ay *= recipNorm;
    az *= recipNorm;
    
    // 估计重力方向
    vx = 2.0f * (q->q1 * q->q3 - q->q0 * q->q2);
    vy = 2.0f * (q->q0 * q->q1 + q->q2 * q->q3);
    vz = q->q0 * q->q0 - q->q1 * q->q1 - q->q2 * q->q2 + q->q3 * q->q3;
    
    // 计算误差
    ex = (ay * vz - az * vy);
    ey = (az * vx - ax * vz);
    ez = (ax * vy - ay * vx);
    
    // 积分误差
    integralFBx += Ki * ex * dt;
    integralFBy += Ki * ey * dt;
    integralFBz += Ki * ez * dt;
    
    // 应用反馈
    gx += Kp * ex + integralFBx;
    gy += Kp * ey + integralFBy;
    gz += Kp * ez + integralFBz;
    
    // 四元数积分
    q->q0 += (-q->q1 * gx - q->q2 * gy - q->q3 * gz) * 0.5f * dt;
    q->q1 += (q->q0 * gx + q->q2 * gz - q->q3 * gy) * 0.5f * dt;
    q->q2 += (q->q0 * gy - q->q1 * gz + q->q3 * gx) * 0.5f * dt;
    q->q3 += (q->q0 * gz + q->q1 * gy - q->q2 * gx) * 0.5f * dt;
    
    // 归一化
    recipNorm = 1.0f / sqrt(q->q0 * q->q0 + q->q1 * q->q1 + 
                           q->q2 * q->q2 + q->q3 * q->q3);
    q->q0 *= recipNorm;
    q->q1 *= recipNorm;
    q->q2 *= recipNorm;
    q->q3 *= recipNorm;
}

实际工程中需要注意的几个关键点:

  1. 采样时间dt:必须精确测量,建议使用STM32的硬件定时器
  2. 滤波器参数:
    • Kp:比例增益,典型值0.5-2.0
    • Ki:积分增益,典型值0.001-0.005
  3. 传感器校准:
    • 陀螺仪零偏校准
    • 加速度计坐标系对齐

3. 从四元数到欧拉角的实用转换

虽然飞控内部使用四元数计算,但最终控制需要转换为更直观的俯仰(pitch)、横滚(roll)、偏航(yaw)角度。转换公式如下:

roll = atan2(2*(q0*q1 + q2*q3), 1 - 2*(q1² + q2²))
pitch = asin(2*(q0*q2 - q3*q1))
yaw = atan2(2*(q0*q3 + q1*q2), 1 - 2*(q2² + q3²))

对应的C语言实现需要考虑计算效率和精度平衡:

void QuaternionToEuler(const Quaternion *q, float *roll, float *pitch, float *yaw) {
    // 横滚角(绕X轴旋转)
    float sinr_cosp = 2.0f * (q->q0 * q->q1 + q->q2 * q->q3);
    float cosr_cosp = 1.0f - 2.0f * (q->q1 * q->q1 + q->q2 * q->q2);
    *roll = atan2f(sinr_cosp, cosr_cosp);
    
    // 俯仰角(绕Y轴旋转)
    float sinp = 2.0f * (q->q0 * q->q2 - q->q3 * q->q1);
    if (fabs(sinp) >= 1)
        *pitch = copysign(M_PI / 2, sinp); // 使用90度极值
    else
        *pitch = asinf(sinp);
    
    // 偏航角(绕Z轴旋转)
    float siny_cosp = 2.0f * (q->q0 * q->q3 + q->q1 * q->q2);
    float cosy_cosp = 1.0f - 2.0f * (q->q2 * q->q2 + q->q3 * q->q3);
    *yaw = atan2f(siny_cosp, cosy_cosp);
}

注意:当俯仰角接近±90度时,虽然四元数本身不会出现奇异点,但欧拉角转换会出现计算不稳定性,这是所有欧拉角表示法的固有缺陷。

4. 工程实践中的常见问题与优化方案

4.1 数据漂移问题解决方案

即使经过精心校准,长时间运行后四元数仍可能出现漂移。我们采用多传感器融合策略:

  1. 加速度计补偿:

    • 在静止状态下,加速度计测量值应与重力方向一致
    • 通过比较实际测量值与重力向量的偏差来修正陀螺仪漂移
  2. 磁力计辅助(如HMC5883L):

    void ApplyMagCorrection(float mx, float my, float mz, Quaternion *q) {
        // 计算预期磁场方向
        float hx = 2.0f * (mx * (0.5f - q->q2*q->q2 - q->q3*q->q3) 
                          + my * (q->q1*q->q2 - q->q0*q->q3) 
                          + mz * (q->q1*q->q3 + q->q0*q->q2));
        
        float hy = 2.0f * (mx * (q->q1*q->q2 + q->q0*q->q3) 
                          + my * (0.5f - q->q1*q->q1 - q->q3*q->q3) 
                          + mz * (q->q2*q->q3 - q->q0*q->q1));
        
        // 计算误差并应用修正
        float bx = sqrt(hx * hx + hy * hy);
        float bz = 2.0f * (mx * (q->q1*q->q3 - q->q0*q->q2) 
                          + my * (q->q2*q->q3 + q->q0*q->q1) 
                          + mz * (0.5f - q->q1*q->q1 - q->q2*q->q2));
        
        float ex = (my * bz - mz * hy);
        float ey = (mz * hx - mx * bz);
        // ... 类似加速度计补偿的处理
    }
    

4.2 计算效率优化技巧

在STM32F4系列上,通过以下方法可将四元数更新耗时从200μs降至50μs:

  1. 使用硬件FPU:确保编译器开启-mfloat-abi=hard选项
  2. 查表法:预先计算三角函数值
  3. 汇编优化:关键循环使用CMSIS-DSP库
    #include "arm_math.h"
    void QuaternionMultiply(Quaternion *a, Quaternion *b, Quaternion *out) {
        arm_quaternion_product_f32(a, b, out);
    }
    

4.3 实际飞行测试中的参数整定

通过实际飞行日志分析,我们发现不同飞行模式需要调整滤波器参数:

飞行模式推荐Kp值推荐Ki值适用场景
平稳模式0.80.003航拍、巡检
运动模式1.50.001竞速、特技飞行
强风模式2.00.005恶劣天气条件

调试时建议按照以下步骤:

  1. 先设置Ki=0,逐渐增大Kp直到出现高频振荡
  2. 取振荡临界值的60%作为Kp最终值
  3. 缓慢增加Ki直到静态姿态误差消除
  4. 室外实际飞行验证,微调参数
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐