4、姿态控制环路:角度环与角速度环的PID控制、串级PID结构详解、控制参数整定方法与经验
各位同学,咱们今天聊点硬核的——姿态控制环路。说实话,这是飞控系统里最核心、也最考验调参功底的部分。很多新手一上来就对着PID参数猛调,结果飞机要么抖得像筛子,要么软得像面条。我当年也踩过这个坑,后来才慢慢摸清楚里面的门道。
4.1 为什么需要串级PID?
先问大家一个问题:如果只用一个PID环,能不能把飞机姿态稳住?理论上可以,但实际效果很差。为什么呢?
你想想看,角度环的输出是期望角速度,而角速度环的输出才是最终的控制量(比如电机油门)。如果只用单环,相当于你直接告诉电机“给我转到30度”,但电机怎么转、转多快,它自己没概念。结果就是——超调、震荡、甚至炸机。
串级PID说白了,就是给外环(角度环)配了一个“执行助理”——内环(角速度环)。外环负责定方向,内环负责执行。我在项目里见过不少同学把内外环搞混,结果调了半天飞机还是乱晃。
4.2 串级PID结构详解
咱们直接上图,看看串级PID到底长什么样。
从图上可以看得很清楚:期望角度进来,先跟实际角度做个减法,得到角度误差。这个误差喂给角度环PID,输出一个期望角速度。然后期望角速度再跟实际角速度做减法,得到角速度误差,喂给角速度环PID,最终输出控制量。
嗯,这里要注意:内环的更新频率一定要比外环高。我一般习惯内环跑400Hz,外环跑100Hz。比例大概是4:1,这样内环才能及时响应外环的指令。
4.3 角度环PID vs 角速度环PID
这两个环的PID参数意义完全不同,千万别搞混了。
| 参数 | 角度环(外环) | 角速度环(内环) |
|---|---|---|
| P(比例) | 决定角度恢复的刚度,越大越硬 | 决定角速度跟踪的响应速度 |
| I(积分) | 消除稳态角度误差(比如重心偏移) | 消除角速度稳态误差 |
| D(微分) | 抑制角度超调,但容易引入噪声 | 抑制角速度震荡,提高稳定性 |
| 典型值范围 | P: 2.0~6.0, I: 0.01~0.1, D: 0.01~0.05 | P: 0.1~0.5, I: 0.001~0.01, D: 0.001~0.005 |
4.4 控制参数整定方法与经验
说到调参,这可是个技术活。我见过有人对着PID参数调了一整天,飞机还是乱晃。其实方法对了,半小时就能搞定。
4.4.1 角速度环整定(先调内环)
- 先把I和D设为0,只留P。从0.1开始慢慢加。
- 用手拨动飞机,感受阻力。如果感觉有弹性回中,说明P差不多了。
- 继续加P直到出现轻微震荡,然后退回70%。
- 加一点点D(0.001起步),抑制震荡。
- 最后加I(0.001起步),消除稳态误差。
4.4.2 角度环整定(再调外环)
- 内环调好后,把外环P从2.0开始加。
- 悬停测试:看飞机能不能稳住。如果来回晃,说明P太小;如果猛地回中然后超调,说明P太大。
- 加I(0.01起步),解决悬停时的角度偏移。
- 加D(0.01起步),抑制超调。
说白了,调参就是个“试错-修正”的过程。我建议每次只改一个参数,改完飞一下看看效果。别一次改好几个参数,出了问题你都不知道是哪个改坏了。
4.5 代码实现示例
下面给一个串级PID的伪代码实现,实际项目中可以直接套用这个框架。
// 角速度环PID(内环,400Hz)
float angular_velocity_pid(float target_rate, float current_rate) {
float error = target_rate - current_rate;
float p_term = kp_rate * error;
// 积分项带限幅
integral_rate += ki_rate * error * dt;
integral_rate = constrain(integral_rate, -integral_limit, integral_limit);
// 微分项(注意:对测量值微分,避免微分冲击)
float d_term = kd_rate * (current_rate - last_rate) / dt;
last_rate = current_rate;
return p_term + integral_rate + d_term;
}
// 角度环PID(外环,100Hz)
float angle_pid(float target_angle, float current_angle) {
float error = target_angle - current_angle;
float p_term = kp_angle * error;
// 角度环积分(用于消除重心偏移等静差)
integral_angle += ki_angle * error * dt;
integral_angle = constrain(integral_angle, -integral_limit_angle, integral_limit_angle);
// 角度环微分(对角度微分得到角速度,但这里直接用内环,所以可以省略)
// 或者用角度误差的微分
float d_term = kd_angle * (error - last_error) / dt;
last_error = error;
// 输出作为内环的期望角速度
return p_term + integral_angle + d_term;
}
// 主循环
void control_loop() {
// 外环:角度 -> 期望角速度
float target_rate = angle_pid(target_roll, current_roll);
// 内环:角速度 -> 控制量
float control = angular_velocity_pid(target_rate, current_rate);
// 输出到电机混控
motor_mix(control);
}
4.6 常见问题与调试技巧
- 飞机高频抖动:内环P太大,或者D太小。先降P,再加D。
- 飞机低频摇摆:外环P太小,或者I太大。先加P,再降I。
- 悬停时慢慢偏航:I不够,或者重心偏移。加I,同时检查重心。
- 打舵后回中过冲:外环D不够,或者内环响应太慢。加D,或者提高内环频率。
我记得有一次调一架大四轴,怎么调都抖。折腾了半天,发现是机架共振频率跟控制频率对上了。后来在机架上贴了点减震棉,问题就解决了。所以说,调参不只是调软件,硬件问题也得考虑。
好了,这一章的内容就到这儿。串级PID是飞控的基石,理解了它,后面的姿态解算、位置控制才能顺理成章。大家回去可以拿自己的飞控试试,先调内环再调外环,感受一下参数变化带来的影响。
公众号:蓝海资料掘金营,微信deep3321