Skip to content

Commit c3a9be4

Browse files
authored
Merge pull request #4630 from iNavFlight/dzikuvx-port-iterm-relax
Direct port of BF Iterm relax
2 parents 7af86a9 + 34bd2ea commit c3a9be4

File tree

6 files changed

+94
-3
lines changed

6 files changed

+94
-3
lines changed

src/main/build/debug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ typedef enum {
6969
DEBUG_SMARTAUDIO,
7070
DEBUG_ACC,
7171
DEBUG_GENERIC,
72+
DEBUG_ITERM_RELAX,
7273
DEBUG_COUNT
7374
} debugType_e;

src/main/common/maths.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,15 @@ int32_t applyDeadband(int32_t value, int32_t deadband)
139139
return value;
140140
}
141141

142+
float fapplyDeadbandf(float value, float deadband)
143+
{
144+
if (fabsf(value) < deadband) {
145+
return 0;
146+
}
147+
148+
return value >= 0 ? value - deadband : value + deadband;
149+
}
150+
142151
int constrain(int amt, int low, int high)
143152
{
144153
if (amt < low)

src/main/common/maths.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void sensorCalibrationSolveForScale(sensorCalibrationState_t * state, float resu
123123

124124
int gcd(int num, int denom);
125125
int32_t applyDeadband(int32_t value, int32_t deadband);
126+
float fapplyDeadbandf(float value, float deadband);
126127

127128
int constrain(int amt, int low, int high);
128129
float constrainf(float amt, float low, float high);

src/main/fc/settings.yaml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ tables:
7777
- name: debug_modes
7878
values: ["NONE", "GYRO", "NOTCH", "NAV_LANDING", "FW_ALTITUDE", "AGL", "FLOW_RAW",
7979
"FLOW", "SBUS", "FPORT", "ALWAYS", "STAGE2", "WIND_ESTIMATOR", "SAG_COMP_VOLTAGE",
80-
"VIBE", "CRUISE", "REM_FLIGHT_TIME", "SMARTAUDIO", "ACC", "GENERIC"]
80+
"VIBE", "CRUISE", "REM_FLIGHT_TIME", "SMARTAUDIO", "ACC", "GENERIC", "ITERM_RELAX"]
8181
- name: async_mode
8282
values: ["NONE", "GYRO", "ALL"]
8383
- name: aux_operator
@@ -114,6 +114,12 @@ tables:
114114
values: ["PT1", "BIQUAD"]
115115
- name: log_level
116116
values: ["ERROR", "WARNING", "INFO", "VERBOSE", "DEBUG"]
117+
- name: iterm_relax
118+
values: ["OFF", "RP", "RPY"]
119+
enum: itermRelax_e
120+
- name: iterm_relax_type
121+
values: ["GYRO", "SETPOINT"]
122+
enum: itermRelaxType_e
117123

118124
groups:
119125
- name: PG_GYRO_CONFIG
@@ -1107,6 +1113,16 @@ groups:
11071113
condition: USE_NAV
11081114
min: 0
11091115
max: 255
1116+
- name: mc_iterm_relax_type
1117+
field: iterm_relax_type
1118+
table: iterm_relax_type
1119+
- name: mc_iterm_relax
1120+
field: iterm_relax
1121+
table: iterm_relax
1122+
- name: mc_iterm_relax_cutoff
1123+
field: iterm_relax_cutoff
1124+
min: 1
1125+
max: 100
11101126

11111127
- name: PG_PID_AUTOTUNE_CONFIG
11121128
type: pidAutotuneConfig_t

src/main/flight/pid.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ int32_t axisPID_P[FLIGHT_DYNAMICS_INDEX_COUNT], axisPID_I[FLIGHT_DYNAMICS_INDEX_
110110

111111
STATIC_FASTRAM pidState_t pidState[FLIGHT_DYNAMICS_INDEX_COUNT];
112112

113-
PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 7);
113+
static EXTENDED_FASTRAM pt1Filter_t windupLpf[XYZ_AXIS_COUNT];
114+
static EXTENDED_FASTRAM uint8_t itermRelax;
115+
static EXTENDED_FASTRAM uint8_t itermRelaxType;
116+
static EXTENDED_FASTRAM float itermRelaxSetpointThreshold;
117+
118+
PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 8);
114119

115120
PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
116121
.bank_mc = {
@@ -206,6 +211,9 @@ PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
206211

207212
.loiter_direction = NAV_LOITER_RIGHT,
208213
.navVelXyDTermLpfHz = NAV_ACCEL_CUTOFF_FREQUENCY_HZ,
214+
.iterm_relax_type = ITERM_RELAX_SETPOINT,
215+
.iterm_relax_cutoff = MC_ITERM_RELAX_CUTOFF_DEFAULT,
216+
.iterm_relax = ITERM_RELAX_OFF,
209217
);
210218

211219
void pidInit(void)
@@ -217,6 +225,10 @@ void pidInit(void)
217225
cos_approx(DECIDEGREES_TO_RADIANS(pidProfile()->max_angle_inclination[FD_PITCH]));
218226

219227
pidGainsUpdateRequired = false;
228+
229+
itermRelax = pidProfile()->iterm_relax;
230+
itermRelaxType = pidProfile()->iterm_relax_type;
231+
itermRelaxSetpointThreshold = MC_ITERM_RELAX_SETPOINT_THRESHOLD * MC_ITERM_RELAX_CUTOFF_DEFAULT / pidProfile()->iterm_relax_cutoff;
220232
}
221233

222234
bool pidInitFilters(void)
@@ -266,6 +278,10 @@ bool pidInitFilters(void)
266278
biquadFilterInitLPF(&pidState[axis].deltaLpfState, pidProfile()->dterm_lpf_hz, refreshRate);
267279
}
268280

281+
for (int i = 0; i < XYZ_AXIS_COUNT; i++) {
282+
pt1FilterInit(&windupLpf[i], pidProfile()->iterm_relax_cutoff, refreshRate * 1e-6f);
283+
}
284+
269285
pidFiltersConfigured = true;
270286

271287
return true;
@@ -552,6 +568,33 @@ static void FAST_CODE pidApplyFixedWingRateController(pidState_t *pidState, flig
552568
#endif
553569
}
554570

571+
static void FAST_CODE applyItermRelax(const int axis, const float gyroRate, float currentPidSetpoint, float *itermErrorRate)
572+
{
573+
const float setpointLpf = pt1FilterApply(&windupLpf[axis], currentPidSetpoint);
574+
const float setpointHpf = fabsf(currentPidSetpoint - setpointLpf);
575+
576+
if (itermRelax) {
577+
if (axis < FD_YAW || itermRelax == ITERM_RELAX_RPY) {
578+
579+
const float itermRelaxFactor = MAX(0, 1 - setpointHpf / itermRelaxSetpointThreshold);
580+
581+
if (itermRelaxType == ITERM_RELAX_SETPOINT) {
582+
*itermErrorRate *= itermRelaxFactor;
583+
} else if (itermRelaxType == ITERM_RELAX_GYRO ) {
584+
*itermErrorRate = fapplyDeadbandf(setpointLpf - gyroRate, setpointHpf);
585+
} else {
586+
*itermErrorRate = 0.0f;
587+
}
588+
589+
if (axis == FD_ROLL) {
590+
DEBUG_SET(DEBUG_ITERM_RELAX, 0, lrintf(setpointHpf));
591+
DEBUG_SET(DEBUG_ITERM_RELAX, 1, lrintf(itermRelaxFactor * 100.0f));
592+
DEBUG_SET(DEBUG_ITERM_RELAX, 2, lrintf(*itermErrorRate));
593+
}
594+
}
595+
}
596+
}
597+
555598
static void FAST_CODE pidApplyMulticopterRateController(pidState_t *pidState, flight_dynamics_index_t axis)
556599
{
557600
const float rateError = pidState->rateTarget - pidState->gyroRate;
@@ -605,7 +648,10 @@ static void FAST_CODE pidApplyMulticopterRateController(pidState_t *pidState, fl
605648
const float motorItermWindupPoint = 1.0f - (pidProfile()->itermWindupPointPercent / 100.0f);
606649
const float antiWindupScaler = constrainf((1.0f - getMotorMixRange()) / motorItermWindupPoint, 0.0f, 1.0f);
607650

608-
pidState->errorGyroIf += (rateError * pidState->kI * antiWindupScaler * dT)
651+
float itermErrorRate = rateError;
652+
applyItermRelax(axis, pidState->gyroRate, pidState->rateTarget, &itermErrorRate);
653+
654+
pidState->errorGyroIf += (itermErrorRate * pidState->kI * antiWindupScaler * dT)
609655
+ ((newOutputLimited - newOutput) * pidState->kT * antiWindupScaler * dT);
610656

611657
// Don't grow I-term if motors are at their limit

src/main/flight/pid.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ FP-PID has been rescaled to match LuxFloat (and MWRewrite) from Cleanflight 1.13
5050
#define FP_PID_LEVEL_P_MULTIPLIER 6.56f // Level P gain units is [1/sec] and angle error is [deg] => [deg/s]
5151
#define FP_PID_YAWHOLD_P_MULTIPLIER 80.0f
5252

53+
#define MC_ITERM_RELAX_SETPOINT_THRESHOLD 40.0f
54+
#define MC_ITERM_RELAX_CUTOFF_DEFAULT 20
55+
5356
typedef enum {
5457
/* PID MC FW */
5558
PID_ROLL, // + +
@@ -76,6 +79,17 @@ typedef struct pidBank_s {
7679
pid8_t pid[PID_ITEM_COUNT];
7780
} pidBank_t;
7881

82+
typedef enum {
83+
ITERM_RELAX_OFF = 0,
84+
ITERM_RELAX_RP,
85+
ITERM_RELAX_RPY
86+
} itermRelax_e;
87+
88+
typedef enum {
89+
ITERM_RELAX_GYRO = 0,
90+
ITERM_RELAX_SETPOINT
91+
} itermRelaxType_e;
92+
7993
typedef struct pidProfile_s {
8094
pidBank_t bank_fw;
8195
pidBank_t bank_mc;
@@ -109,6 +123,10 @@ typedef struct pidProfile_s {
109123

110124
uint8_t loiter_direction; // Direction of loitering center point on right wing (clockwise - as before), or center point on left wing (counterclockwise)
111125
float navVelXyDTermLpfHz;
126+
127+
uint8_t iterm_relax_type; // Specifies type of relax algorithm
128+
uint8_t iterm_relax_cutoff; // This cutoff frequency specifies a low pass filter which predicts average response of the quad to setpoint
129+
uint8_t iterm_relax; // Enable iterm suppression during stick input
112130
} pidProfile_t;
113131

114132
typedef struct pidAutotuneConfig_s {

0 commit comments

Comments
 (0)