基于PID的车辆控制integratedError
PID控制器
以下是一个简易版的PID控制器的实现代码:
class PIDController
{
private:
double kp, ki, kd; // PID控制器的参数
double targetValue; // 目标值
double lastError; // 上一次误差
double integratedError; // 误差积分值
public:
void initialize(double p, double i, double d, double target)
{
kp = p;
ki = i;
kd = d;
targetValue = target;
lastError = 0;
integratedError = 0;
}
double calculate(double input)
{
double error = targetValue - input; // 当前误差
double derivativeError = error - lastError; // 误差的变化率
integratedError += error;
lastError = error;
return kp * error + ki * integratedError + kd * derivativeError;
}
}
基于PID的车辆控制
在CyberTorcs中,基于PID控制车辆的简易实现如下:
PIDController speedController; // PID速度控制器
PIDController angleController; // PID舵角控制器
double lastTargetSpeed = 999.0; // 上一帧目标速度,初始化为999.0 米/秒
bool isFirstFrame = true; // 第一帧标志
static void userDriverSetParam(
float* cmdAcc, float* cmdBrake, float* cmdSteer, int* cmdGear)
{
/* ----- 舵角控制 ----- */
double targetAngleError = 0.0;
double currentAngleError = atan2(_midline[5][0], _midline[5][1]);
// 第一帧初始化舵角控制参数,清空积分器和微分器
// 因为控制目标一直为零,所以只需要初始化一次
if (isFirstFrame)
{
isFirstFrame = false;
angleController.initial(1.0, 0.0, 0.0, targetAngleError);
}
// 舵角PID控制
*cmdSteer = constrain(-1.0, 1.0, angleController.calculate(currentAngleError));
/* ----- 速度控制 ----- */
double targetSpeed;
double currentSpeed = _speed;
//判断前方是直道还是弯道
circle myCurve;
float minCruve = 500.0;
for (int fStep = 0; fStep < 50; fStep++)
{
myCurve = getR(
_midline[fStep][0], _midline[fStep][1],
_midline[fStep + 10][0], _midline[fStep + 10][1],
_midline[fStep + 20][0], _midline[fStep + 20][1]
);
if (myCurve.r < minCruve)
minCruve = myCurve.r;
}
// 基于前方赛道状态设定目标速度
if (minCruve > 300)
targetSpeed = 250;
else if (minCruve > 150)
targetSpeed = 150;
else if (minCruve > 100)
targetSpeed = 80;
else
targetSpeed = 50;
// 每当目标速度变化时初始化PID控制器,重设参数,清空积分器和微分器
if (targetSpeed != lastTargetSpeed)
{
speedController.initial(0.01, 0.0, 0.0, targetSpeed);
lastTargetSpeed = targetSpeed;
}
// 根据当前速度和目标速度关系,控制油门刹车以改变速度
if (currentSpeed < targetSpeed) // 当前速度低于目标,需要加速
{
if (_speed > 100 && abs(*cmdSteer) < 0.1) // 速度较快且舵角较小时,使用PID控制
*cmdAcc = constrain(0.0, 1.0, speedController.calculate(currentSpeed));
else if (_speed > 50 && abs(*cmdSteer) < 0.1) // 速度较慢且舵角较小时,限定油门
*cmdAcc = 0.6;
else // 预料之外的情况下,进一步限定油门
*cmdAcc = 0.3;
// 加速状态下刹车为0
*cmdBrake = 0;
}
else // 减速情况下,刹车
{
*cmdAcc = 0;
*cmdBrake = 0.3;
}
// 更新档位
updateGear(cmdGear);
}