1. 项目概述:四旋翼PID控制的复现挑战
去年在调试一台自制四旋翼时,我遇到了一个典型问题:当飞行器受到侧风干扰时,姿态角会出现持续振荡。这让我意识到经典PID控制在非线性系统中的局限性,于是开始系统研究《基于内外环结构的四旋翼飞行器PID控制方法》这篇论文。该论文提出了一种分层控制架构,通过内外环协同解决了单环PID的响应滞后问题。
复现这类控制算法需要同时掌握三个维度的知识:飞行器动力学建模、PID参数整定方法以及Matlab/Simulink仿真技巧。我在实验室用DJI Flame Wheel 450机架搭建测试平台时发现,论文中的理论参数在实际飞行中往往需要20%-30%的调整,这促使我深入分析算法实现细节。
2. 核心原理拆解
2.1 四旋翼动力学模型
建立准确的数学模型是控制的基础。在机体坐标系下,四旋翼的动力学方程可表示为:
code复制τ = J·ω' + ω×(J·ω) // 旋转运动方程
F = m·a - R·[0;0;mg] // 平移运动方程
其中J是惯性矩阵,ω为角速度向量,R为旋转矩阵。这个耦合的非线性系统正是需要PID控制来解决的核心问题。我在Matlab中建模时特别注意了三个关键参数:
- 电机力矩系数 (Kt)
- 螺旋桨升力系数 (Kf)
- 机体惯性矩 (Jxx, Jyy, Jzz)
实测提示:实验室常用悬停法测量Kf,即让飞行器保持悬停状态,通过电机转速和总重量反推升力系数。
2.2 内外环控制结构
论文提出的分层架构如下图所示(示意结构):
code复制[外环位置PID] → [内环姿态PID] → [电机混控] → [物理系统]
↑ ↑ |
| | ↓
[位置反馈] ← [姿态反馈] ← [角速度反馈]
外环处理位置控制,生成期望姿态角;内环快速响应姿态变化,输出电机控制量。这种解耦设计使得:
- 外环可以用较大时间常数保证稳定性
- 内环采用高带宽控制抑制扰动
我在Simulink中实现时,外环采样周期设为20ms,内环设为5ms,这与实际飞控的处理能力匹配。
3. Matlab实现细节
3.1 仿真环境搭建
使用Simulink Aerospace Blockset构建完整模型,关键模块包括:
- 六自由度刚体模块(Aerospace Blockset)
- PWM信号生成模块(Simulink-Pulse Generator)
- 电机模型(Lookup Table实现非线性映射)
matlab复制% 电机模型参数示例
rpm_range = [0 20000]; % 电机转速范围
thrust_table = [0 0.2 0.5 0.8 1.0]; % 归一化推力曲线
pwm_table = [1000 1200 1500 1800 2000]; % 对应PWM值
3.2 PID参数整定技巧
论文采用Ziegler-Nichols法整定参数,但实际测试发现需要改进:
| 控制环 | 比例Kp | 积分Ki | 微分Kd | 调整建议 |
|---|---|---|---|---|
| 外环X | 1.2 | 0.01 | 0.5 | 先调Kp至临界振荡,再减半 |
| 内环Roll | 3.5 | 0.5 | 0.2 | 优先保证Kp,Ki后期微调 |
避坑指南:内环微分项过大会导致电机高频抖动,建议先用低通滤波器处理角速度信号。
4. 硬件在环测试
4.1 STLink调试现象分析
在将算法移植到STM32F4时,遇到了一个典型问题:连接STLink时控制正常,断开后出现发散。经排查发现:
- 时钟配置错误:调试器自动配置了HSE时钟,独立运行时使用HSI
- 中断优先级冲突:PID计算中断被其他任务抢占
- 浮点单元未启用:添加
__FPU_PRESENT宏定义解决
c复制// 正确的时钟初始化代码片段
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
4.2 实际飞行测试数据
对比仿真与实测数据发现:
| 指标 | 仿真值 | 实测值 | 差异分析 |
|---|---|---|---|
| 阶跃响应时间 | 0.8s | 1.2s | 电机响应延迟 |
| 超调量 | 5% | 15% | 模型未考虑空气阻尼 |
| 稳态误差 | <1% | 3% | 传感器噪声影响 |
通过增加加速度前馈补偿,最终将实测性能提升到接近仿真水平。
5. 进阶优化方向
5.1 模糊PID自适应
在论文基础上,我尝试加入模糊逻辑实现参数自整定:
matlab复制fis = newfis('pid_adjust');
fis = addvar(fis,'input','error',[-1 1]);
fis = addvar(fis,'input','derror',[-0.5 0.5]);
fis = addvar(fis,'output','deltaKp',[-0.3 0.3]);
% 添加模糊规则...
测试表明这种方法能有效应对突风扰动,但会增加约15%的计算负载。
5.2 串级PID改进
将内环进一步拆分为:
code复制角速度环(最内层) → 角度环 → 位置环(最外层)
这种三层结构在高速机动时表现更优,但需要精确的角速度传感器校准。
6. 工程经验总结
经过三个月的反复调试,总结出以下核心经验:
- 参数整定顺序:先内环后外环,先比例后微分最后积分
- 抗饱和处理:必须对积分项进行限幅,典型值为控制量的20%
- 传感器同步:使用DMA方式读取IMU数据,时间偏差控制在1ms内
- 实时监控:通过VOFA+等上位机工具观察参数变化趋势
最后分享一个调试技巧:在Matlab中用tic/toc测量每个控制周期的执行时间,确保留有30%的余量应对突发计算任务。当发现姿态角出现高频抖动时,优先检查陀螺仪滤波参数而非盲目调整PID。
