PID 算法优化 && 增量式 PID
PID 算法
有关 PID 的介绍可以看这里
PID 优化
输出限幅
- 将控制器的输出限制在一定范围内,防止控制器过大的输出
Code
if (output_ < output_min_) {
output_ = output_min_;
}
if (output_ > output_max_) {
output_= output_max_;
}
抗积分饱和
积分饱和 是指 PID 控制器中的一种现象,当误差较大时,积分器将有很大的累计量,随着时间增加容易引起过冲,当误差方向相反时,仍然会维持一段时间才能恢复正常,影响控制系统的性能
解决方法
条件积分
- 积分项只在 输出未饱和,且误差方向与控制方向一致时才累计
Code
void update(float target, float measurement, float dt){
float error = target - measurement;
float new_integral = integral_ + error * dt;
output_ = (Kp_ * error) + \
(Ki_ * new_integral) + \
(Kd_ * (error - last_error_) / dt);
if (output_ < output_min_) {
output_ = output_min_;
if (error > 0) {
integral_ = new_integral
}
}
else if (output_ > output_max_) {
output_= output_max_;
if (error < 0) {
integral_ = new_integral
}
} else {
integral_ = new_integral
}
last_error_ = error;
}
积分分离
积分项优化为
当误差值小于一定范围时,才进行积分项的累计
Code
void update(float target, float measurement, float dt){
float error = target - measurement;
// 积分分离
if (fabs(error) <= integral_separation_threshold) {
integral_ += error * dt;
}
output_ = (Kp_ * error) + \
(Ki_ * integral_) + \
(Kd_ * (error - last_error_) / dt);
if (output_ < output_min_) {
output_ = output_min_;
}
if (output_ > output_max_) {
output_= output_max_;
}
last_error_ = error;
}
反计算抗饱和
引入反饱和误差 Anti-windup error
积分项更新为
实际的输出为输出限幅后的
PID 完整公式可以更新为
Code
void update(float target, float measurement, float dt){
float error = target - measurement;
float p_term = Kp_ * error;
float d_term = Kd_ * (error - last_error_) / dt;
float output_unsat = p_term + integral_ + d_term;
output_ = std::clamp(output_unsat, output_min, output_max);
// 反计算积分
float aw_error = output - output_unsat;
integral_ += (Ki_ * error + Kc_ * aw_error) * dt
last_error_ = error;
}
此方法引入了一个 新的参数反计算增益
推荐取值范围为
例如
微分项优化
- 添加低通滤波,减少测量噪声对微分项的干扰
Code
float d_term = Kd_ * (error - last_error_) / dt;
d_term = (alpha * last_d_term) + ((1- alpha) * d_term);
...
last_d_term = d_term;