Skip to content

Commit 85fe245

Browse files
Angular acceleration limit on PID rate setpoint made possible (#427)
* Angular acceleration limit on PID rate setpoint
1 parent f440ead commit 85fe245

File tree

6 files changed

+52
-16
lines changed

6 files changed

+52
-16
lines changed

src/main/common/filter.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,25 +102,28 @@ float pt1FilterApply4(pt1Filter_t *filter, float input, float f_cut, float dT)
102102
return filter->state;
103103
}
104104

105-
// f_cut = cutoff frequency
106-
// rate_limit = maximum rate of change of the output value in units per second
107-
float pt1FilterApplyWithRateLimit(pt1Filter_t *filter, float input, float f_cut, float rate_limit, float dT)
105+
void pt1FilterReset(pt1Filter_t *filter, float input)
108106
{
109-
// Pre calculate and store RC
110-
if (!filter->RC) {
111-
filter->RC = 1.0f / ( 2.0f * (float)M_PI * f_cut );
112-
}
113-
114-
const float newState = filter->state + dT / (filter->RC + dT) * (input - filter->state);
115-
const float rateLimitPerSample = rate_limit * dT;
116-
filter->state = constrainf(newState, filter->state - rateLimitPerSample, filter->state + rateLimitPerSample);
107+
filter->state = input;
108+
}
117109

118-
return filter->state;
110+
// rate_limit = maximum rate of change of the output value in units per second
111+
void rateLimitFilterInit(rateLimitFilter_t *filter)
112+
{
113+
filter->state = 0;
119114
}
120115

121-
void pt1FilterReset(pt1Filter_t *filter, float input)
116+
float rateLimitFilterApply4(rateLimitFilter_t *filter, float input, float rate_limit, float dT)
122117
{
123-
filter->state = input;
118+
if (rate_limit > 0) {
119+
const float rateLimitPerSample = rate_limit * dT;
120+
filter->state = constrainf(input, filter->state - rateLimitPerSample, filter->state + rateLimitPerSample);
121+
}
122+
else {
123+
filter->state = input;
124+
}
125+
126+
return filter->state;
124127
}
125128

126129
// FIR filter

src/main/common/filter.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
#pragma once
1919

20+
typedef struct rateLimitFilter_s {
21+
float state;
22+
} rateLimitFilter_t;
23+
2024
typedef struct pt1Filter_s {
2125
float state;
2226
float RC;
@@ -38,9 +42,11 @@ typedef struct firFilter_s {
3842

3943
float pt1FilterApply(pt1Filter_t *filter, float input);
4044
float pt1FilterApply4(pt1Filter_t *filter, float input, float f_cut, float dt);
41-
float pt1FilterApplyWithRateLimit(pt1Filter_t *filter, float input, float f_cut, float rate_limit, float dT);
4245
void pt1FilterReset(pt1Filter_t *filter, float input);
4346

47+
void rateLimitFilterInit(rateLimitFilter_t *filter);
48+
float rateLimitFilterApply4(rateLimitFilter_t *filter, float input, float rate_limit, float dT);
49+
4450
void biquadFilterInit(biquadFilter_t *filter, uint8_t filterCutFreq, int16_t samplingRate);
4551
float biquadFilterApply(biquadFilter_t *filter, float sample);
4652

src/main/config/config.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ static uint32_t activeFeaturesLatch = 0;
170170
static uint8_t currentControlRateProfileIndex = 0;
171171
controlRateConfig_t *currentControlRateProfile;
172172

173-
static const uint8_t EEPROM_CONF_VERSION = 120;
173+
static const uint8_t EEPROM_CONF_VERSION = 121;
174174

175175
static void resetAccelerometerTrims(flightDynamicsTrims_t * accZero, flightDynamicsTrims_t * accGain)
176176
{
@@ -222,6 +222,9 @@ void resetPidProfile(pidProfile_t *pidProfile)
222222
pidProfile->rollPitchItermIgnoreRate = 200; // dps
223223
pidProfile->yawItermIgnoreRate = 50; // dps
224224

225+
pidProfile->axisAccelerationLimitYaw = 10000; // dps/s
226+
pidProfile->axisAccelerationLimitRollPitch = 0; // dps/s
227+
225228
pidProfile->yaw_p_limit = YAW_P_LIMIT_DEFAULT;
226229
pidProfile->mag_hold_rate_limit = MAG_HOLD_RATE_LIMIT_DEFAULT;
227230

src/main/flight/pid.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct {
7474
pt1Filter_t angleFilterState;
7575

7676
// Rate filtering
77+
rateLimitFilter_t axisAccelFilter;
7778
pt1Filter_t ptermLpfState;
7879
pt1Filter_t deltaLpfState;
7980
} pidState_t;
@@ -278,6 +279,16 @@ static void pidLevel(const pidProfile_t *pidProfile, const controlRateConfig_t *
278279
}
279280
}
280281

282+
/* Apply angular acceleration limit to rate target to limit extreme stick inputs to respect physical capabilities of the machine */
283+
static void pidApplySetpointRateLimiting(const pidProfile_t *pidProfile, pidState_t *pidState, flight_dynamics_index_t axis)
284+
{
285+
const uint32_t axisAccelLimit = (axis == FD_YAW) ? pidProfile->axisAccelerationLimitYaw : pidProfile->axisAccelerationLimitRollPitch;
286+
287+
if (axisAccelLimit > AXIS_ACCEL_MIN_LIMIT) {
288+
pidState->rateTarget = rateLimitFilterApply4(&pidState->axisAccelFilter, pidState->rateTarget, (float)axisAccelLimit, dT);
289+
}
290+
}
291+
281292
static void pidApplyRateController(const pidProfile_t *pidProfile, pidState_t *pidState, flight_dynamics_index_t axis)
282293
{
283294
const float rateError = pidState->rateTarget - pidState->gyroRate;
@@ -499,6 +510,11 @@ void pidController(const pidProfile_t *pidProfile, const controlRateConfig_t *co
499510
pidTurnAssistant(pidState);
500511
}
501512

513+
// Apply setpoint rate of change limits
514+
for (int axis = 0; axis < 3; axis++) {
515+
pidApplySetpointRateLimiting(pidProfile, &pidState[axis], axis);
516+
}
517+
502518
// Step 4: Run gyro-driven control
503519
for (int axis = 0; axis < 3; axis++) {
504520
// Apply PID setpoint controller

src/main/flight/pid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#define MAG_HOLD_RATE_LIMIT_MAX 250
3434
#define MAG_HOLD_RATE_LIMIT_DEFAULT 90
3535

36+
#define AXIS_ACCEL_MIN_LIMIT 50
37+
3638
typedef enum {
3739
PIDROLL,
3840
PIDPITCH,
@@ -63,6 +65,9 @@ typedef struct pidProfile_s {
6365
uint16_t rollPitchItermIgnoreRate; // Experimental threshold for ignoring iterm for pitch and roll on certain rates
6466
uint16_t yawItermIgnoreRate; // Experimental threshold for ignoring iterm for yaw on certain rates
6567

68+
uint32_t axisAccelerationLimitYaw; // Max rate of change of yaw angular rate setpoint (deg/s^2 = dps/s)
69+
uint32_t axisAccelerationLimitRollPitch; // Max rate of change of roll/pitch angular rate setpoint (deg/s^2 = dps/s)
70+
6671
int16_t max_angle_inclination[ANGLE_INDEX_COUNT]; // Max possible inclination (roll and pitch axis separately
6772

6873
uint8_t mag_hold_rate_limit; //Maximum rotation rate MAG_HOLD mode can feed to yaw rate PID controller

src/main/io/serial_cli.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,9 @@ const clivalue_t valueTable[] = {
811811
{ "iterm_ignore_threshold", VAR_UINT16 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.rollPitchItermIgnoreRate, .config.minmax = {15, 1000 } },
812812
{ "yaw_iterm_ignore_threshold", VAR_UINT16 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.yawItermIgnoreRate, .config.minmax = {15, 1000 } },
813813

814+
{ "rate_accel_limit_roll_pitch",VAR_UINT32 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.axisAccelerationLimitRollPitch, .config.minmax = {0, 500000 } },
815+
{ "rate_accel_limit_yaw", VAR_UINT32 | PROFILE_VALUE, &masterConfig.profile[0].pidProfile.axisAccelerationLimitYaw, .config.minmax = {0, 500000 } },
816+
814817
#ifdef BLACKBOX
815818
{ "blackbox_rate_num", VAR_UINT8 | MASTER_VALUE, &masterConfig.blackbox_rate_num, .config.minmax = { 1, 32 }, 0 },
816819
{ "blackbox_rate_denom", VAR_UINT8 | MASTER_VALUE, &masterConfig.blackbox_rate_denom, .config.minmax = { 1, 32 }, 0 },

0 commit comments

Comments
 (0)