欧拉角:三维姿态的直观表示

目录

概述

1 欧拉角基础概念

1.1 核心定义

1.2  旋转顺序的重要性

1.3 欧拉角的数学表示

2 从传感器数据计算欧拉角

2.1 仅用加速度计(静态条件)

2.2 结合陀螺仪(动态条件)

2.3 从四元数转换

3 欧拉角的应用领域

3.1 无人机飞行控制

3.2 3D相机控制系统

3.3 虚拟现实头部追踪

4 欧拉角与其他表示法的比较

5 欧拉角的最佳实践

5.1 避免万向节死锁

5.2 角度归一化

5.3 平滑滤波

5.4 多传感器融合

6 高级主题:方向余弦矩阵 (DCM)


概述

欧拉角是在三维空间中描述刚体方向的一种方式。欧拉角由三个角度组成,通常称为俯仰角(pitch)、滚转角(roll)和偏航角(yaw)。这些角度分别围绕物体的三个轴(通常是X、Y、Z轴)进行旋转。欧拉角的定义: 1. 俯仰角(pitch):围绕X轴的旋转角度,表示物体向上或向下的倾斜。 2. 滚转角(roll):围绕Y轴的旋转角度,表示物体向左或向右的翻滚。 3. 偏航角(yaw):围绕Z轴的旋转角度,表示物体在水平面上的方向。 注意:旋转顺序很重要。常见的顺序是:先偏航(yaw),再俯仰(pitch),最后滚转(roll)。但不同的应用可能使用不同的顺序。在航空航天领域,通常使用Z-Y-X顺序(即先偏航,再俯仰,最后滚转)。

1 欧拉角基础概念

欧拉角是描述物体在三维空间中方向的最直观方法之一,通过三个独立的旋转角度来定义物体相对于参考坐标系的姿态。

1.1 核心定义

欧拉角由三个旋转角度组成:

  • 俯仰角 (Pitch):围绕X轴的旋转(抬头/低头)

  • 滚转角 (Roll):围绕Y轴的旋转(左右倾斜)

  • 偏航角 (Yaw):围绕Z轴的旋转(左右转向)

1.2  旋转顺序的重要性

欧拉角的表示取决于旋转顺序,常见顺序:

  • 航空航天序列:偏航 → 俯仰 → 滚转 (Z-Y-X)

  • 相机稳定序列:滚转 → 俯仰 → 偏航 (X-Y-Z)

  • 机器人学序列:俯仰 → 滚转 → 偏航 (Y-X-Z)

1.3 欧拉角的数学表示

  偏航角(yaw)ψ:绕Z轴旋转  

  俯仰角(pitch)θ:绕Y轴旋转  

  滚转角(roll)φ:绕X轴旋转

 旋转矩阵R由三个基本旋转矩阵相乘得到(按顺序右乘):    

 R = R_z(ψ) * R_y(θ) * R_x(φ)

绕Z轴旋转ψ:          

            R_z(ψ) =  | cosψ  -sinψ     0  |                            

                            | sinψ   cosψ     0  |                            

                            |  0          0          1  |

 绕Y轴旋转θ:            

             R_y(θ) = | cosθ    0    sinθ    |                            

                            |  0        1      0        |                          

                            | -sinθ   0    cosθ   |

  绕X轴旋转φ:      

              R_x(φ) =  |  1      0            0   |                        

                              |  0    cosφ   -sinφ |                      

                              |  0    sinφ     cosφ |

 因此,组合旋转矩阵R为:                    

 R = R_z(ψ)*R_y(θ)*R_x(φ)                        

    =  | cosθ*cosψ     sinφ*sinθ*cosψ - cosφ*sinψ     cosφ*sinθ*cosψ + sinφ*sinψ |                       | cosθ*sinψ        sinφ*sinθ*sinψ + cosφ*cosψ    cosφ*sinθ*sinψ - sinφ*cosψ |                        |   -sinθ               sinφ*cosθ                                      cosφ*cosθ        |

完整数学公式: 

2 从传感器数据计算欧拉角

2.1 仅用加速度计(静态条件)

void accel_to_euler(float ax, float ay, float az, float *roll, float *pitch)
{
    // 计算滚转角 (绕Y轴)
    *roll = atan2(ay, sqrt(ax*ax + az*az));
    
    // 计算俯仰角 (绕X轴)
    *pitch = atan2(-ax, az);
}

2.2 结合陀螺仪(动态条件)

void update_attitude(float *roll, float *pitch, float *yaw,
                    float gx, float gy, float gz,
                    float ax, float ay, float az,
                    float dt)
{
    // 陀螺仪积分
    *roll += gx * dt;
    *pitch += gy * dt;
    *yaw += gz * dt;
    
    // 加速度计补偿(仅适用于低频运动)
    float accel_roll = atan2(ay, sqrt(ax*ax + az*az));
    float accel_pitch = atan2(-ax, az);
    
    // 互补滤波
    const float alpha = 0.98;
    *roll = alpha * (*roll) + (1-alpha) * accel_roll;
    *pitch = alpha * (*pitch) + (1-alpha) * accel_pitch;
}

2.3 从四元数转换

void quaternion_to_euler(float q0, float q1, float q2, float q3,
                        float *roll, float *pitch, float *yaw)
{
    // 滚转 (X轴旋转)
    *roll = atan2(2*(q0*q1 + q2*q3), 1 - 2*(q1*q1 + q2*q2));
    
    // 俯仰 (Y轴旋转)
    float sinp = 2*(q0*q2 - q3*q1);
    if (fabs(sinp) >= 1)
        *pitch = copysign(M_PI/2, sinp);
    else
        *pitch = asin(sinp);
    
    // 偏航 (Z轴旋转)
    *yaw = atan2(2*(q0*q3 + q1*q2), 1 - 2*(q2*q2 + q3*q3));
    
    // 转换为角度
    *roll *= 180.0/M_PI;
    *pitch *= 180.0/M_PI;
    *yaw *= 180.0/M_PI;
}

3 欧拉角的应用领域

3.1 无人机飞行控制

// PID控制器实现
void drone_control(float target_roll, float target_pitch, float target_yaw,
                  float current_roll, float current_pitch, float current_yaw,
                  float *motor1, float *motor2, float *motor3, float *motor4)
{
    // PID参数
    const float Kp = 2.5, Ki = 0.05, Kd = 0.8;
    
    // 计算误差
    float roll_error = target_roll - current_roll;
    float pitch_error = target_pitch - current_pitch;
    float yaw_error = target_yaw - current_yaw;
    
    // PID计算 (简化版)
    float roll_correction = Kp * roll_error;
    float pitch_correction = Kp * pitch_error;
    float yaw_correction = Kp * yaw_error;
    
    // 分配电机输出
    *motor1 = BASE_SPEED + roll_correction + pitch_correction + yaw_correction;
    *motor2 = BASE_SPEED - roll_correction + pitch_correction - yaw_correction;
    *motor3 = BASE_SPEED + roll_correction - pitch_correction - yaw_correction;
    *motor4 = BASE_SPEED - roll_correction - pitch_correction + yaw_correction;
}

3.2 3D相机控制系统

void camera_stabilization(float current_roll, float current_pitch,
                         float *gimbal_roll, float *gimbal_pitch)
{
    // 目标角度(水平)
    const float target_roll = 0;
    const float target_pitch = 0;
    
    // 比例控制
    const float K = 0.8;
    *gimbal_roll = -K * current_roll;
    *gimbal_pitch = -K * current_pitch;
    
    // 限幅保护
    *gimbal_roll = constrain(*gimbal_roll, -45, 45);
    *gimbal_pitch = constrain(*gimbal_pitch, -30, 30);
}

3.3 虚拟现实头部追踪

void vr_head_tracking(float roll, float pitch, float yaw,
                      float *view_matrix)
{
    // 创建旋转矩阵
    float cosR = cos(roll), sinR = sin(roll);
    float cosP = cos(pitch), sinP = sin(pitch);
    float cosY = cos(yaw), sinY = sin(yaw);
    
    // 构建视图矩阵 (列优先)
    view_matrix[0] = cosY*cosP;
    view_matrix[1] = sinY*cosP;
    view_matrix[2] = -sinP;
    
    view_matrix[4] = cosY*sinP*sinR - sinY*cosR;
    view_matrix[5] = sinY*sinP*sinR + cosY*cosR;
    view_matrix[6] = cosP*sinR;
    
    view_matrix[8] = cosY*sinP*cosR + sinY*sinR;
    view_matrix[9] = sinY*sinP*cosR - cosY*sinR;
    view_matrix[10] = cosP*cosR;
    
    // 位置部分设为单位矩阵
    view_matrix[12] = view_matrix[13] = view_matrix[14] = 0;
    view_matrix[15] = 1;
}

4 欧拉角与其他表示法的比较

特性欧拉角四元数旋转矩阵轴角
参数数量3494
奇异性有 (万向锁)
插值困难简单 (球面插值)复杂简单
计算效率
直观性最好
组合旋转困难简单简单困难
存储需求最小

5 欧拉角的最佳实践

5.1 避免万向节死锁

// 俯仰角安全限制
const float MAX_PITCH = 85.0f; // 度

float safe_pitch(float pitch)
{
    if (pitch > MAX_PITCH) return MAX_PITCH;
    if (pitch < -MAX_PITCH) return -MAX_PITCH;
    return pitch;
}

// 在控制循环中使用
current_pitch = safe_pitch(current_pitch);

5.2 角度归一化

// 将角度归一化到 [-180, 180] 范围
float normalize_angle(float angle)
{
    while (angle > 180.0f) angle -= 360.0f;
    while (angle < -180.0f) angle += 360.0f;
    return angle;
}

// 在误差计算中使用
float error = normalize_angle(target - current);

5.3 平滑滤波

// 一阶低通滤波器
float low_pass_filter(float new_value, float old_value, float alpha)
{
    return alpha * new_value + (1 - alpha) * old_value;
}

// 在姿态更新中使用
current_roll = low_pass_filter(raw_roll, current_roll, 0.2f);
current_pitch = low_pass_filter(raw_pitch, current_pitch, 0.2f);

5.4 多传感器融合

void sensor_fusion(float *roll, float *pitch, float *yaw,
                  float accel_x, float accel_y, float accel_z,
                  float gyro_x, float gyro_y, float gyro_z,
                  float mag_x, float mag_y, float mag_z,
                  float dt)
{
    // 1. 陀螺仪积分
    *roll += gyro_x * dt;
    *pitch += gyro_y * dt;
    *yaw += gyro_z * dt;
    
    // 2. 加速度计补偿滚转和俯仰
    float accel_roll = atan2(accel_y, sqrt(accel_x*accel_x + accel_z*accel_z));
    float accel_pitch = atan2(-accel_x, accel_z);
    
    // 互补滤波
    const float alpha = 0.98;
    *roll = alpha * (*roll) + (1 - alpha) * accel_roll;
    *pitch = alpha * (*pitch) + (1 - alpha) * accel_pitch;
    
    // 3. 磁力计补偿偏航
    float mag_roll = *roll;
    float mag_pitch = *pitch;
    
    // 磁力矢量补偿
    float mag_x_comp = mag_x * cos(mag_pitch) + mag_z * sin(mag_pitch);
    float mag_y_comp = mag_x * sin(mag_roll) * sin(mag_pitch) + 
                      mag_y * cos(mag_roll) - 
                      mag_z * sin(mag_roll) * cos(mag_pitch);
    
    float mag_yaw = atan2(-mag_y_comp, mag_x_comp);
    
    // 偏航滤波
    *yaw = alpha * (*yaw) + (1 - alpha) * mag_yaw;
}

6 高级主题:方向余弦矩阵 (DCM)

当需要避免奇异性时,DCM 是欧拉角的良好替代方案:

1) DCM 初始化

void init_dcm(float dcm[3][3])
{
    // 初始化为单位矩阵
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            dcm[i][j] = (i == j) ? 1.0f : 0.0f;
        }
    }
}

2)DCM 更新

void update_dcm(float dcm[3][3], float wx, float wy, float wz, float dt)
{
    // 角速度矩阵
    float omega[3][3] = {
        {0, -wz, wy},
        {wz, 0, -wx},
        {-wy, wx, 0}
    };
    
    // 临时矩阵 I + Ω*dt/2
    float temp[3][3];
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            temp[i][j] = (i == j ? 1.0f : 0.0f) + omega[i][j] * dt / 2;
        }
    }
    
    // 更新DCM: DCM' = DCM * (I + Ω*dt/2)
    float new_dcm[3][3];
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            new_dcm[i][j] = 0;
            for (int k = 0; k < 3; k++) {
                new_dcm[i][j] += dcm[i][k] * temp[k][j];
            }
        }
    }
    
    // 复制回原矩阵
    memcpy(dcm, new_dcm, sizeof(new_dcm));
}

 3)DCM 到欧拉角转换

void dcm_to_euler(const float dcm[3][3], float *roll, float *pitch, float *yaw)
{
    // 俯仰角
    *pitch = asin(-dcm[2][0]);
    
    // 滚转角
    *roll = atan2(dcm[2][1], dcm[2][2]);
    
    // 偏航角
    *yaw = atan2(dcm[1][0], dcm[0][0]);
    
    // 转换为角度
    *roll *= 180.0f / M_PI;
    *pitch *= 180.0f / M_PI;
    *yaw *= 180.0f / M_PI;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值