1. 项目概述:当PID遇上四旋翼
四旋翼无人机的控制问题一直是飞控领域的经典课题。去年我在调试一台自制无人机时,发现传统PID控制在快速机动时会出现明显的超调现象——当无人机从悬停状态突然转向时,要么反应迟钝像喝醉了酒,要么过度灵敏像触电一样乱抖。这个问题促使我深入研究增量式PID算法在离散系统中的实现方案。
增量PID与传统位置式PID的根本区别在于:它不直接计算控制量输出,而是计算控制量的增量变化。这种特性使其天然具备抗积分饱和能力,特别适合像四旋翼这样需要快速响应的系统。通过MATLAB/Simulink搭建完整的离散化模型后,实测轨迹跟踪误差可以控制在目标位置的±5cm范围内,比常规PID提升约40%的稳定性。
2. 核心算法解析
2.1 增量PID的数学本质
增量PID的离散化公式看似简单,却蕴含精妙设计:
code复制Δu(k) = Kp*[e(k)-e(k-1)] + Ki*e(k) + Kd*[e(k)-2e(k-1)+e(k-2)]
其中各参数含义:
- Kp:比例系数(决定系统响应速度)
- Ki:积分系数(消除稳态误差)
- Kd:微分系数(抑制超调振荡)
- e(k):当前时刻误差
- e(k-1)、e(k-2):前两个采样时刻的误差
关键技巧:实际调试中发现,当采样周期T较小时,建议将Ki改写为KpT/Ti,Kd改写为KpTd/T,这样参数物理意义更明确。
2.2 四旋翼动力学建模
建立机体坐标系下的运动方程时,需考虑以下非线性因素:
matlab复制% 姿态动力学方程示例
Ixx * p_dot = (Iyy - Izz)*q*r + tau_phi - J_r*q*Omega_r
其中:
- Ixx, Iyy, Izz:转动惯量
- p,q,r:角速度分量
- tau_phi:滚转力矩
- J_r:转子惯量
- Omega_r:转子转速差
实测数据表明,在俯仰角超过30°时,非线性项(Iyy-Izz)qr的影响会急剧增大。这就是为什么大机动时需要更精细的PID参数整定。
3. MATLAB实现详解
3.1 离散化处理流程
我的Simulink模型采用固定步长离散化,关键配置如下:
-
采样周期选择:
- 姿态环:0.005s(对应200Hz)
- 位置环:0.02s(50Hz)
-
离散PID实现代码:
matlab复制function [u, delta_u] = incrPID(e, e_prev, e_prev2, Kp, Ki, Kd)
delta_u = Kp*(e - e_prev) + Ki*e + Kd*(e - 2*e_prev + e_prev2);
u = u_prev + delta_u;
end
- 抗饱和处理:
matlab复制if abs(u) > umax
u = sign(u)*umax;
delta_u = 0; % 关键!防止积分累积
end
3.2 轨迹跟踪架构
我的方案采用双闭环结构:
code复制[位置指令] → [位置PID] → [姿态指令] → [姿态PID] → [电机PWM]
实测表明,这种结构在跟踪圆形轨迹时,x/y方向的相位延迟需要补偿:
matlab复制% 前馈补偿示例
theta_des = atan2(yd_dot + k*ey, xd_dot + k*ex);
4. 参数整定实战经验
4.1 试凑法三步走
- 先调Kp:从小到大增加,直到系统出现等幅振荡
- 再调Kd:增大Kd抑制振荡,保留20%裕度
- 最后调Ki:从振荡时Kp值的0.6倍开始微调
血泪教训:曾因Ki过大导致电机过热烧毁,建议先用1/10理论值开始测试。
4.2 典型参数参考
对于500g级四旋翼,我的经验参数范围:
- 姿态环:
- Kp: 1.2~2.5
- Ki: 0.05~0.3
- Kd: 0.3~0.8
- 位置环:
- Kp: 0.8~1.5
- Ki: 0.01~0.1
- Kd: 0.1~0.3
5. 异常处理备忘录
5.1 电机响应不一致
症状:无人机总是偏向某个方向
解决方法:
- 校准电机零位
- 检查PID输出限幅是否对称
- 用示波器检测PWM信号占空比
5.2 高频振荡问题
症状:悬停时出现高频抖动
排查步骤:
- 降低Kd增益
- 检查IMU安装是否牢固
- 增加低通滤波器:
matlab复制alpha = 0.2; % 滤波系数
filtered_value = alpha*new + (1-alpha)*old;
6. 完整代码结构说明
项目包含以下核心文件:
QuadrotorModel.slx:完整的Simulink模型pidTuner.m:交互式参数整定工具trajectoryGen.m:生成8字形测试轨迹plotResults.m:绘制跟踪误差曲线
关键函数调用关系:
code复制main_script → init_params → run_simulation → analyze_results
在模型线性化环节,特别推荐使用MATLAB的linmod函数获取状态空间模型:
matlab复制[A,B,C,D] = linmod('QuadrotorModel');
调试时发现一个易错点:需要先运行load_system再调用linmod,否则会报错。这个细节在官方文档中并没有特别强调,我花了三小时才找到问题根源。
