目录

一、位置式PID和增量式PID

二、问题分析

三、参数调节


小车由于在自身重力或摩擦力等因素影响下,实际转速会小于输入转速,导致里程计误差较大。在较小速度情况下可能会出现堵转情况,导致小车在导航过程中输入小幅度角度转动的时候,无法及时调整进而撞到障碍物,因此需要给电机加PID速度环闭环控制。

一、位置式PID和增量式PID

        PID有位置式和增量式,两者各有优缺点。

        位置式PID的输出直接对应系统输出,响应速度快,适用于需要快速响应的系统,但缺点是容易出现积分饱和:当惯性系统达到最大输出值时,由于系统还未达到目标位置,error一直存在,如果没有积分限幅积分项会不断累加,一旦开始反向变化,系统需要一定时间从饱和区退出,会导致系统超调或震荡。

        增量式PID不需要做累加,控制量增量的确定仅与最近三次偏差采样值有关,计算误差对控制量计算的影响较小,当输出达到最大值时,增量自动归零,避免持续饱和,适用于需要平滑控制的系统,如步进电机。缺点是由于输出的是控制量的增量,响应不如位置式PID,更难直接用于控制一些需要精确位置调整的系统

二、问题分析

        我们先采用位置式PID来进行调试,下面给出代码

double PID::compute_positional(double setpoint, double measured_value, short outLimit, short IntegralLimit) {
    outLimit = config_outLimit;
    IntegralLimit = config_IntegralLimit;

    double error = setpoint - measured_value;

    // 当目标值为零时,重置积分项
    if (setpoint == 0.0) {
        integral_pos = 0.0;
    }

    double proportional = kp * error;
    integral_pos += ki * error;
    double derivative = kd * (error - prev_error_pos);

    // 积分限幅
    if (integral_pos > IntegralLimit)
        integral_pos = IntegralLimit;
    else if (integral_pos < -IntegralLimit)
        integral_pos = -IntegralLimit;

    double output_unclamped = proportional + integral_pos - derivative;
    double output = output_unclamped;
    // ROS_INFO("integral_pos=%.1f,output=%.1f",integral_pos,output);

    // 输出限幅
    if (output > outLimit)          output = outLimit;
    else if (output < -outLimit)    output = -outLimit;

    // 抗积分饱和:输出被限幅时调整积分项
    if (output_unclamped != output) {
        integral_pos = output - proportional - derivative;
    }

    prev_error_pos = error;
    return output;
}

小车最大pwm为900,最大线速度0.3m/s,先给小车一个KP=2000,KI和KP都为0,输出限幅和积分限幅为900,目标速度为0.2,输出左右两轮速度波形图如下:

小车速度始终达不到0.2,这里有个矛盾的地方:如果小车速度达到0.2了,则偏差值error为0,那么KP*error为0,output也为0,那么速度为0,速度为0那么error值又不为0,就会有速度输出,形成矛盾,为此我记录了几组数据,得出以下公式:实际速度=f+(目标速度-f)/2,f为小车克服摩擦力的速度,当f为0时,小车实际速度为目标速度一半,此时加入KI,先给个较小值20

可以看到小车速度逐渐到达0.2,分析后得知:小车电机速度环的KP可以帮助小车预先接近目标速度,再此基础上,KI开始进行积分,从积分开始到目标速度的那块红色阴影面积即为最终的pwm值,如下图,当达到目标速度时KP和KI稳定在目标速度进行调节使小车稳定在目标速度

三、参数调节

        个人调参经验:KP<=最大output/最大误差。KI影响增长到目标转速的快慢,但太快会过冲,我对小车的要求使快速到达目标转速,建议大家对着波形调试,将KI调到速度波形可快速到达目标转速,或稍微过冲。KD我个人不建议加,因为小车电机要快速达到目标转速,但KD会抑制速度过快增长,所以KD给0。

KP=2000,KI=200效果:

位置式和增量式效果对比,上面是位置式,下面是增量式,相同参数情况下:

个人觉得差别不大,但增量式在参数较小的情况下变化更平滑,KP=200,KI=20:

增量式PID代码:

double PID::compute_incremental(double setpoint, double measured_value, short outLimit) {
    // 当目标速度为0时,重置历史值
    if (setpoint == 0.0) {
        prev_output_inc = 0.0;
        prev_error_inc1 = 0.0;
        prev_error_inc2 = 0.0;
    }

    double error = setpoint - measured_value;
    double output = prev_output_inc + kp * (error - prev_error_inc1) +
                    ki * error + kd * (error - 2 * prev_error_inc1 + prev_error_inc2);

    prev_error_inc2 = prev_error_inc1;
    prev_error_inc1 = error;
    prev_output_inc = output;

    // 输出限幅
    if (output > outLimit)          output = outLimit;
    else if (output < -outLimit)    output = -outLimit;


    return output;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐