第4章:经典PID姿态控制
各位同学,今天咱们来聊聊PID控制。说实话,PID这东西在飞控领域已经用了好几十年了,但你别小看它。我见过不少团队,上来就搞什么自适应、神经网络,结果飞起来还不如一个调好的PID稳当。
这一章,我会把PID的原理、串级结构、参数整定,还有那个让人头疼的积分饱和问题,一次性给你讲透。
4.1 PID控制器原理
PID说白了就是三个字:比例、积分、微分。你想想看,无人机要稳住姿态,靠的就是这三个环节的配合。
- 比例(P):当前偏差有多大,我就给多大的力。偏差大,输出大;偏差小,输出小。简单粗暴。
- 积分(I):把过去的偏差累加起来。如果一直有稳态误差,积分项就会慢慢增大,直到把误差消除。
- 微分(D):预测未来的趋势。偏差变化快了,微分项就出来压一压,防止超调。
公式长这样:
u(t) = Kp * e(t) + Ki * ∫e(t)dt + Kd * de(t)/dt
嗯,这里要注意,实际飞控里用的是离散形式。我早期做飞控时,直接把连续公式套进去,结果发现采样周期一变,参数全得重调。后来才明白,离散化处理才是关键。
核心要点:P是现在,I是过去,D是未来。三个环节配合好了,飞机才能稳如老狗。
4.2 角度环与角速度环串级PID
为什么不用单环?我刚开始做飞控时也这么想,一个PID搞定所有不香吗?结果试了才知道,单环PID对外部扰动(比如阵风)的响应太慢了。
串级PID的结构是这样的:
- 外环(角度环):输入是期望角度,输出是期望角速度。说白了,就是告诉内环「你该转多快」。
- 内环(角速度环):输入是期望角速度,输出是电机控制量。它负责快速响应,把实际的角速度拉回来。
我个人的习惯是,内环频率跑高一点(200-400Hz),外环频率低一些(50-100Hz)。为什么?因为角速度变化快,角度变化慢。你想想看,飞机稍微一晃,角速度传感器就跳了,但角度可能还没变多少。
实战技巧:内环先调稳,再调外环。我曾经遇到过内环没调好就急着调外环,结果飞机在天上像抽风一样,差点炸机。
4.3 PID参数整定方法
参数整定是门手艺活。我见过有人靠蒙,有人靠公式,有人靠玄学。这里我介绍两种靠谱的方法。
4.3.1 Ziegler-Nichols方法
这个方法适合快速找到一组可用参数。步骤很简单:
- 先把积分和微分关掉(Ki=0, Kd=0)。
- 慢慢增大Kp,直到系统开始等幅振荡。
- 记录此时的临界增益Ku和振荡周期Tu。
- 按表格计算参数。
| 控制器类型 | Kp | Ki | Kd |
|---|---|---|---|
| P | 0.5 * Ku | - | - |
| PI | 0.45 * Ku | 1.2 * Kp / Tu | - |
| PID | 0.6 * Ku | 2 * Kp / Tu | Kp * Tu / 8 |
注意:Z-N方法给出的参数通常偏激进,实际飞行时可能需要手动微调。我建议你把它当作起点,而不是终点。
4.3.2 试凑法
这个方法更依赖经验,但调出来的参数往往更贴合实际。我的步骤是这样的:
- 先调P:从小到大加,直到飞机有轻微振荡。然后退回来一点。
- 再加D:D能抑制振荡,让飞机更稳。但D太大会引入噪声,电机嗡嗡响。
- 最后加I:I消除稳态误差。但I太大会导致超调,甚至积分饱和。
我记得有一次调一架大四轴,P加到0.8时飞机开始抖,我退到0.6,然后加D到0.2,飞机稳得像块石头。最后加I到0.05,悬停误差从5度降到了0.5度以内。
避坑指南:我曾经在试凑时犯过一个低级错误——每次只改一个参数,但改完没等系统稳定就继续调。结果参数越调越乱。记住,每次改完参数,至少等3-5秒观察响应。
4.4 抗积分饱和
积分饱和是个坑,很多新手会栽在这里。说白了就是:当执行器已经饱和(比如电机已经满油门了),积分项还在累加,导致偏差消除后,积分项还要花很长时间才能退回来。
后果是什么?飞机超调严重,甚至振荡发散。
解决办法有几种:
- 积分限幅:给积分项设个上限,别让它无限累加。
- 积分分离:当偏差大于某个阈值时,停止积分。
- 反计算法:当执行器饱和时,把多余的积分量减掉。
我个人最常用的是积分限幅加反计算法。代码实现也不复杂:
// 反计算抗积分饱和
float pid_update(float setpoint, float measurement) {
float error = setpoint - measurement;
float p_term = Kp * error;
// 计算未限幅的输出
float u_unsat = p_term + integral + Kd * (error - prev_error);
// 限幅
float u_sat = constrain(u_unsat, -limit, limit);
// 反计算:如果输出饱和,减小积分项
if (u_unsat != u_sat) {
integral -= Ki * (u_unsat - u_sat) * dt;
} else {
integral += Ki * error * dt;
}
prev_error = error;
return u_sat;
}
经验之谈:积分限幅的值我一般设为输出限幅的10%-20%。太小了没效果,太大了等于没限。这个比例是我炸了两次机之后才悟出来的。
好了,这一章的内容就到这里。PID看似简单,但真正调好需要大量实践。下一章我们会讲如何把PID应用到实际的姿态解算中,到时候再聊。