agv-control/Plugin/Driver/pid_controller.cpp
CaiXiang 4be62027c6 引入PID控制器并更新相关功能
在多个文件中进行了重要更改:
- 更新 `Driver.rc` 和 `resource.h` 的二进制文件。
- 在 `Driver.vcxproj` 中添加了多线程调试DLL的运行库设置。
- 引入 `pid_controller.h` 和 `pid_controller.cpp`,实现PID控制器功能。
- 在 `DriverMainDlg.cpp` 中添加了对PID控制的支持,包括新成员变量和方法。
- 增加了自动发送和车辆位置更新的功能。
- 在 `Protocol.h` 中添加了新的消息类型 `GUIDE_FAST`。
2025-06-16 11:16:20 +08:00

76 lines
2.0 KiB
C++

#include "pid_controller.h"
#include <cmath>
PIDController::PIDController(float proportionalGain, float integralGain, float derivativeGain,
float iLimitLow, float iLimitHigh, float oLimitLow, float oLimitHigh, float timeStep)
: kp(proportionalGain), ki(integralGain), kd(derivativeGain),
integralLimitLow(iLimitLow), integralLimitHigh(iLimitHigh),
outputLimitLow(oLimitLow), outputLimitHigh(oLimitHigh),
dt(timeStep), prevError(0.0f), integral(0.0f), prevMeasurement(0.0f), firstRun(true) {
}
void PIDController::reset() {
prevError = 0.0f;
integral = 0.0f;
prevMeasurement = 0.0f;
firstRun = true;
}
float PIDController::compute(float setpoint, float measurement) {
// 计算误差(期望角度 - 当前角度)
float error = setpoint - measurement;
// 比例项
float proportionalTerm = kp * error;
// 积分项(带抗积分饱和)
integral += error * dt;
// 积分限幅,防止积分饱和
if (integral > integralLimitHigh) {
integral = integralLimitHigh;
}
else if (integral < integralLimitLow) {
integral = integralLimitLow;
}
float integralTerm = ki * integral;
// 微分项(使用测量值的变化率而非误差变化率,以减少噪声影响)
float derivativeTerm = 0.0f;
if (!firstRun) {
// 使用测量值的变化率计算微分
float dMeasurement = measurement - prevMeasurement;
derivativeTerm = -kd * (dMeasurement / dt);
}
firstRun = false;
// 保存当前测量值用于下次计算
prevMeasurement = measurement;
// 计算总输出
float output = proportionalTerm + integralTerm + derivativeTerm;
// 输出限幅
if (output > outputLimitHigh) {
output = outputLimitHigh;
}
else if (output < outputLimitLow) {
output = outputLimitLow;
}
return output;
}
void PIDController::getTunings(float& p, float& i, float& d) const {
p = kp;
i = ki;
d = kd;
}
void PIDController::setTunings(float p, float i, float d) {
kp = p;
ki = i;
kd = d;
}