掌握欧拉角与四元数,理解万向锁与四元数插值。
| 方法 | 参数 | 万向锁 | 插值 |
|---|---|---|---|
| 欧拉角 | 3 | ❌ | 差 |
| 旋转矩阵 | 9 | ❌ | 差 |
| 四元数 | 4 | ❌ | 优 |
R = Rz(ψ) · Ry(θ) · Rx(φ)
Rz(ψ): 绕Z轴旋转ψ(航向)
Ry(θ): 绕Y轴旋转θ(俯仰)
Rx(φ): 绕X轴旋转φ(滚转)pitch=±90°时roll和yaw轴重合!丢失一个自由度。
θ=90°: Rz(ψ)·Ry(90°)·Rx(φ) = Rz(ψ-φ)·Ry(90°)·I → ψ,φ无法独立确定
q = [w, x, y, z], |q|=1
欧拉角→四元数:
w = cos(φ/2)cos(θ/2)cos(ψ/2) + sin(φ/2)sin(θ/2)sin(ψ/2)
x = sin(φ/2)cos(θ/2)cos(ψ/2) - cos(φ/2)sin(θ/2)sin(ψ/2)
y = cos(φ/2)sin(θ/2)cos(ψ/2) + sin(φ/2)cos(θ/2)sin(ψ/2)
z = cos(φ/2)cos(θ/2)sin(ψ/2) - sin(φ/2)sin(θ/2)cos(ψ/2)
乘法: q₁⊗q₂ (Hamilton积)
导数: q̇ = ½q⊗[0,ωx,ωy,ωz]=== 万向锁演示 ===
Pitch=90°时, Roll=30.0° Yaw=50.0°
等价于 Roll=80.0° Yaw=0° (万向锁!)
=== 四元数插值测试 ===
t=0.00: Roll= 0.0° Pitch= 0.0° Yaw= 0.0°
t=0.25: Roll= 7.3° Pitch= 11.3° Yaw= 11.8°
t=0.50: Roll= 17.3° Pitch= 20.6° Yaw= 25.5°
t=0.75: Roll= 30.1° Pitch= 27.2° Yaw= 41.8°
t=1.00: Roll= 45.0° Pitch= 30.0° Yaw= 60.0°
四元数范数: 1.0000000000 (应为1.0)
class Quaternion:
def __init__(self, w=1,x=0,y=0,z=0):
self.w,self.x,self.y,self.z = w,x,y,z
self.normalize()
def normalize(self):
n = (self.w**2+self.x**2+self.y**2+self.z**2)**0.5
if n>1e-10: self.w/=n;self.x/=n;self.y/=n;self.z/=n
return self
def __mul__(self, o):
return Quaternion(
self.w*o.w-self.x*o.x-self.y*o.y-self.z*o.z,
self.w*o.x+self.x*o.w+self.y*o.z-self.z*o.y,
self.w*o.y-self.x*o.z+self.y*o.w+self.z*o.x,
self.w*o.z+self.x*o.y-self.y*o.x+self.z*o.w)
@staticmethod
def from_euler(r,p,y): ... # 见上文公式
def to_euler(self): ... # 反解
@staticmethod
def slerp(q1,q2,t): ... # 球面插值✅ 欧拉角有万向锁,不适合全姿态飞行
✅ 四元数无奇异性,SLERP保证最短路径
✅ 飞控内部四元数,界面欧拉角
1. 实现quat→rotmat转换。2. pitch≈90°时对比两种插值。3. 四元数角速度积分。
掌握欧拉角/四元数与万向锁
本课涉及的核心公式和算法需要反复练习才能真正掌握。建议通过修改仿真参数、添加扰动等方式深入理解每个参数对系统行为的影响。在实际飞行中,这些参数的选择往往需要在理论分析的基础上结合实验微调。
| 指标 | 消费级 | 工业级 | 研究级 |
|---|---|---|---|
| 姿态精度 | ±2° | ±0.5° | ±0.1° |
| 位置精度(GPS) | ±2m | ±0.5m | ±2cm(RTK) |
| 悬停精度 | ±1m | ±0.3m | ±0.05m |
| 控制频率 | 400Hz | 1kHz | 1kHz+ |
| 传感器融合 | 互补滤波 | EKF | EKF/VIO |
| 续航时间 | 20-30min | 30-45min | 视载荷而定 |
# PX4姿态控制核心流程(简化)
# 1. 计算误差四元数
q_err = q_desired.inverse() * q_current
# 2. 从误差四元数提取轴角
# 如果 q_err.w < 0, 取反保证最短路径
if q_err.w < 0:
q_err = -q_err
angle = 2 * acos(q_err.w)
axis = q_err.xyz / sin(angle/2) # 旋转轴
# 3. 轴角 → 角速度误差
# 小角度: rate_error ≈ 2 * q_err.xyz
# 大角度: rate_error = axis * angle * gain
# 4. 角速度PID → 力矩
torque = rate_pid.update(rate_error)
# 5. 混控矩阵 → 电机
motor_cmds = mixing_matrix @ [thrust, torque_x, torque_y, torque_z]
上电后需进行初始对齐,确定初始姿态:
# 磁力计校准步骤
# 1. 硬磁校准: 绕3轴旋转采集数据
# 2. 拟合椭球 → 球体变换
# 3. 软磁校准: 3x3矩阵消除非正交
# 校准质量指标:
# 校准后球心偏差 < 5%
# 场强偏差 < 10%
# 偏航误差 < 3°
在实际飞控系统中,算法必须在有限的计算资源下实时运行。以下为本课核心算法的复杂度分析:
| 算法/模块 | 时间复杂度 | 空间复杂度 | 典型耗时 |
|---|---|---|---|
| 互补滤波 | O(1) | O(1) | <1μs |
| 卡尔曼滤波(15态) | O(n²) | O(n²) | ~50μs |
| EKF(15态) | O(n³) | O(n²) | ~200μs |
| 串级PID | O(1) | O(1) | <5μs |
| A*(N节点) | O(N log N) | O(N) | 1-100ms |
| RRT(N步) | O(N·K) | O(N) | 10-500ms |
| 最小snap(M段) | O(M³) | O(M²) | ~1ms |
无人机飞控是典型的实时嵌入式系统,必须满足严格的时序约束:
# 典型飞控任务优先级(高→低)
# 1. IMU采样+姿态估计 (1kHz, 优先级最高)
# 2. 角速度PID控制 (1kHz)
# 3. 姿态PID控制 (500Hz)
# 4. EKF状态更新 (200Hz)
# 5. 位置/速度控制 (100Hz)
# 6. 路径规划/避障 (10-50Hz)
# 7. 通信/日志 (1-10Hz)
# RTOS调度: 优先级抢占 + 时间片轮转
飞控软件是安全关键系统,代码质量要求极高:
# 单元测试示例
def test_pid_output():
pid = PID(kp=1.0, ki=0, kd=0)
assert pid.update(1.0, 0.01) == 1.0 # P=1*1.0
def test_pid_integral_limit():
pid = PID(kp=0, ki=1.0, kd=0, i_limit=5.0)
for _ in range(1000):
pid.update(1.0, 0.01) # 大量积分
assert abs(pid.integral) <= 5.0 # 不超过限幅
def test_kalman_convergence():
kf = KalmanFilter(...)
for _ in range(100):
kf.predict()
kf.update(measurement)
assert kf.P[0,0] < initial_P # 协方差下降
| 特性 | PX4 | ArduPilot | Betaflight |
|---|---|---|---|
| 定位 | 研究/工业 | 工业/爱好者 | 竞速穿越 |
| 代码量 | ~500K行 | ~800K行 | ~200K行 |
| 支持的机型 | 多旋翼/固定翼/VTOL | 多旋翼/固定翼/直升机/车/船 | 多旋翼/固定翼 |
| 导航能力 | 强(全面) | 强(最全面) | 弱(仅自稳) |
| 实时性 | NuttX RTOS | ChibiOS/RTOS | Bare-metal |
| 仿真支持 | SITL/Gazebo/AirSim | SITL/Gazebo | 有限 |
| 社区活跃度 | 高 | 最高 | 高(竞速圈) |
无人机系统属于安全关键(Safety-Critical)系统,设计时必须遵循以下原则:
本课所学技术在以下场景中直接应用:
将本课模块集成到完整系统时的注意事项: