mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-05 23:43:58 -04:00
AC_PID: added slew limiter AC_PID
this adds the fixed wing slew limiter as an optional part of AC_PID. It allows the user to configure a maximum slew limit to prevent oscillations in PIDs when gains are too high
This commit is contained in:
parent
709e1f8f93
commit
739410953b
@ -61,6 +61,14 @@ const AP_Param::GroupInfo AC_HELI_PID::var_info[] = {
|
|||||||
// @Units: Hz
|
// @Units: Hz
|
||||||
AP_GROUPINFO("FLTD", 11, AC_HELI_PID, _filt_D_hz, AC_PID_DFILT_HZ_DEFAULT),
|
AP_GROUPINFO("FLTD", 11, AC_HELI_PID, _filt_D_hz, AC_PID_DFILT_HZ_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: SMAX
|
||||||
|
// @DisplayName: Slew rate limit
|
||||||
|
// @Description: Sets an upper limit on the slew rate produced by the combined P and D gains. If the amplitude of the control action produced by the rate feedback exceeds this value, then the D+P gain is reduced to respect the limit. This limits the amplitude of high frequency oscillations caused by an excessive gain. The limit should be set to no more than 25% of the actuators maximum slew rate to allow for load effects. Note: The gain will not be reduced to less than 10% of the nominal value. A value of zero will disable this feature.
|
||||||
|
// @Range: 0 200
|
||||||
|
// @Increment: 0.5
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("SMAX", 12, AC_HELI_PID, _slew_rate_max, 0),
|
||||||
|
|
||||||
AP_GROUPEND
|
AP_GROUPEND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,11 +56,20 @@ const AP_Param::GroupInfo AC_PID::var_info[] = {
|
|||||||
// @Units: Hz
|
// @Units: Hz
|
||||||
AP_GROUPINFO("FLTD", 11, AC_PID, _filt_D_hz, AC_PID_DFILT_HZ_DEFAULT),
|
AP_GROUPINFO("FLTD", 11, AC_PID, _filt_D_hz, AC_PID_DFILT_HZ_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: SMAX
|
||||||
|
// @DisplayName: Slew rate limit
|
||||||
|
// @Description: Sets an upper limit on the slew rate produced by the combined P and D gains. If the amplitude of the control action produced by the rate feedback exceeds this value, then the D+P gain is reduced to respect the limit. This limits the amplitude of high frequency oscillations caused by an excessive gain. The limit should be set to no more than 25% of the actuators maximum slew rate to allow for load effects. Note: The gain will not be reduced to less than 10% of the nominal value. A value of zero will disable this feature.
|
||||||
|
// @Range: 0 200
|
||||||
|
// @Increment: 0.5
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("SMAX", 12, AC_PID, _slew_rate_max, 0),
|
||||||
|
|
||||||
AP_GROUPEND
|
AP_GROUPEND
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AC_PID::AC_PID(float initial_p, float initial_i, float initial_d, float initial_ff, float initial_imax, float initial_filt_T_hz, float initial_filt_E_hz, float initial_filt_D_hz, float dt) :
|
AC_PID::AC_PID(float initial_p, float initial_i, float initial_d, float initial_ff, float initial_imax, float initial_filt_T_hz, float initial_filt_E_hz, float initial_filt_D_hz,
|
||||||
|
float dt, float initial_srmax, float initial_srtau):
|
||||||
_dt(dt),
|
_dt(dt),
|
||||||
_integrator(0.0f),
|
_integrator(0.0f),
|
||||||
_error(0.0f),
|
_error(0.0f),
|
||||||
@ -77,6 +86,8 @@ AC_PID::AC_PID(float initial_p, float initial_i, float initial_d, float initial_
|
|||||||
filt_T_hz(initial_filt_T_hz);
|
filt_T_hz(initial_filt_T_hz);
|
||||||
filt_E_hz(initial_filt_E_hz);
|
filt_E_hz(initial_filt_E_hz);
|
||||||
filt_D_hz(initial_filt_D_hz);
|
filt_D_hz(initial_filt_D_hz);
|
||||||
|
_slew_rate_max.set(initial_srmax);
|
||||||
|
_slew_rate_tau.set(initial_srtau);
|
||||||
|
|
||||||
// reset input filter to first value received
|
// reset input filter to first value received
|
||||||
_flags._reset_filter = true;
|
_flags._reset_filter = true;
|
||||||
@ -144,6 +155,12 @@ float AC_PID::update_all(float target, float measurement, bool limit)
|
|||||||
float P_out = (_error * _kp);
|
float P_out = (_error * _kp);
|
||||||
float D_out = (_derivative * _kd);
|
float D_out = (_derivative * _kd);
|
||||||
|
|
||||||
|
// calculate slew limit modifier for P+D
|
||||||
|
_pid_info.Dmod = _slew_limiter.modifier(_pid_info.P + _pid_info.D, _dt);
|
||||||
|
|
||||||
|
P_out *= _pid_info.Dmod;
|
||||||
|
D_out *= _pid_info.Dmod;
|
||||||
|
|
||||||
_pid_info.target = _target;
|
_pid_info.target = _target;
|
||||||
_pid_info.actual = measurement;
|
_pid_info.actual = measurement;
|
||||||
_pid_info.error = _error;
|
_pid_info.error = _error;
|
||||||
@ -190,6 +207,12 @@ float AC_PID::update_error(float error, bool limit)
|
|||||||
float P_out = (_error * _kp);
|
float P_out = (_error * _kp);
|
||||||
float D_out = (_derivative * _kd);
|
float D_out = (_derivative * _kd);
|
||||||
|
|
||||||
|
// calculate slew limit modifier for P+D
|
||||||
|
_pid_info.Dmod = _slew_limiter.modifier(_pid_info.P + _pid_info.D, _dt);
|
||||||
|
|
||||||
|
P_out *= _pid_info.Dmod;
|
||||||
|
D_out *= _pid_info.Dmod;
|
||||||
|
|
||||||
_pid_info.target = 0.0f;
|
_pid_info.target = 0.0f;
|
||||||
_pid_info.actual = 0.0f;
|
_pid_info.actual = 0.0f;
|
||||||
_pid_info.error = _error;
|
_pid_info.error = _error;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <AP_Logger/AP_Logger.h>
|
#include <AP_Logger/AP_Logger.h>
|
||||||
|
#include <Filter/SlewLimiter.h>
|
||||||
|
|
||||||
#define AC_PID_TFILT_HZ_DEFAULT 0.0f // default input filter frequency
|
#define AC_PID_TFILT_HZ_DEFAULT 0.0f // default input filter frequency
|
||||||
#define AC_PID_EFILT_HZ_DEFAULT 0.0f // default input filter frequency
|
#define AC_PID_EFILT_HZ_DEFAULT 0.0f // default input filter frequency
|
||||||
@ -19,7 +20,8 @@ class AC_PID {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructor for PID
|
// Constructor for PID
|
||||||
AC_PID(float initial_p, float initial_i, float initial_d, float initial_ff, float initial_imax, float initial_filt_T_hz, float initial_filt_E_hz, float initial_filt_D_hz, float dt);
|
AC_PID(float initial_p, float initial_i, float initial_d, float initial_ff, float initial_imax, float initial_filt_T_hz, float initial_filt_E_hz, float initial_filt_D_hz,
|
||||||
|
float dt, float initial_srmax=0, float initial_srtau=1.0);
|
||||||
|
|
||||||
// set_dt - set time step in seconds
|
// set_dt - set time step in seconds
|
||||||
void set_dt(float dt);
|
void set_dt(float dt);
|
||||||
@ -105,6 +107,12 @@ public:
|
|||||||
// parameter var table
|
// parameter var table
|
||||||
static const struct AP_Param::GroupInfo var_info[];
|
static const struct AP_Param::GroupInfo var_info[];
|
||||||
|
|
||||||
|
// the time constant tau is not currently configurable, but is set
|
||||||
|
// as an AP_Float to make it easy to make it configurable for a
|
||||||
|
// single user of AC_PID by adding the parameter in the param
|
||||||
|
// table of the parent class. It is made public for this reason
|
||||||
|
AP_Float _slew_rate_tau;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
@ -116,6 +124,9 @@ protected:
|
|||||||
AP_Float _filt_T_hz; // PID target filter frequency in Hz
|
AP_Float _filt_T_hz; // PID target filter frequency in Hz
|
||||||
AP_Float _filt_E_hz; // PID error filter frequency in Hz
|
AP_Float _filt_E_hz; // PID error filter frequency in Hz
|
||||||
AP_Float _filt_D_hz; // PID derivative filter frequency in Hz
|
AP_Float _filt_D_hz; // PID derivative filter frequency in Hz
|
||||||
|
AP_Float _slew_rate_max;
|
||||||
|
|
||||||
|
SlewLimiter _slew_limiter{_slew_rate_max, _slew_rate_tau};
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
struct ac_pid_flags {
|
struct ac_pid_flags {
|
||||||
|
Loading…
Reference in New Issue
Block a user