1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-14 03:50:02 +03:00

update antigravity for 4.4, no boost on yaw

Update to anti-gravity, including removal of the old Step mode, ability to adjust the P contribution (thanks @Limon), PT2 smoothed derivative model, inherent limiting of P boost during extremely fast stick travels to minimise P oscillations, less I during the middle of a throttle up, no I boost on yaw, add hz to cutoff labels

No antigravity on yaw, fix longstanding typo

h
This commit is contained in:
ctzsnooze 2022-06-20 08:55:31 +10:00
parent 4fa4d4851e
commit 6aaaf727ff
13 changed files with 92 additions and 160 deletions

View file

@ -117,7 +117,7 @@ PG_RESET_TEMPLATE(pidConfig_t, pidConfig,
#define LAUNCH_CONTROL_YAW_ITERM_LIMIT 50 // yaw iterm windup limit when launch mode is "FULL" (all axes)
PG_REGISTER_ARRAY_WITH_RESET_FN(pidProfile_t, PID_PROFILE_COUNT, pidProfiles, PG_PID_PROFILE, 3);
PG_REGISTER_ARRAY_WITH_RESET_FN(pidProfile_t, PID_PROFILE_COUNT, pidProfiles, PG_PID_PROFILE, 4);
void resetPidProfile(pidProfile_t *pidProfile)
{
@ -140,8 +140,7 @@ void resetPidProfile(pidProfile_t *pidProfile)
.feedforward_transition = 0,
.yawRateAccelLimit = 0,
.rateAccelLimit = 0,
.itermThrottleThreshold = 250,
.itermAcceleratorGain = 3500,
.anti_gravity_gain = 80,
.crash_time = 500, // ms
.crash_delay = 0, // ms
.crash_recovery_angle = 10, // degrees
@ -168,7 +167,6 @@ void resetPidProfile(pidProfile_t *pidProfile)
.abs_control_limit = 90,
.abs_control_error_limit = 20,
.abs_control_cutoff = 11,
.antiGravityMode = ANTI_GRAVITY_SMOOTH,
.dterm_lpf1_static_hz = DTERM_LPF1_DYN_MIN_HZ_DEFAULT,
// NOTE: dynamic lpf is enabled by default so this setting is actually
// overridden and the static lowpass 1 is disabled. We can't set this
@ -218,6 +216,8 @@ void resetPidProfile(pidProfile_t *pidProfile)
.simplified_pitch_pi_gain = SIMPLIFIED_TUNING_DEFAULT,
.simplified_dterm_filter = true,
.simplified_dterm_filter_multiplier = SIMPLIFIED_TUNING_DEFAULT,
.anti_gravity_cutoff_hz = 5,
.anti_gravity_p_gain = 100,
);
#ifndef USE_D_MIN
@ -303,25 +303,23 @@ void pidUpdateTpaFactor(float throttle)
void pidUpdateAntiGravityThrottleFilter(float throttle)
{
if (pidRuntime.antiGravityMode == ANTI_GRAVITY_SMOOTH) {
// calculate a boost factor for P in the same way as for I when throttle changes quickly
const float antiGravityThrottleLpf = pt1FilterApply(&pidRuntime.antiGravityThrottleLpf, throttle);
// focus P boost on low throttle range only
if (throttle < 0.5f) {
pidRuntime.antiGravityPBoost = 0.5f - throttle;
} else {
pidRuntime.antiGravityPBoost = 0.0f;
}
// use lowpass to identify start of a throttle up, use this to reduce boost at start by half
if (antiGravityThrottleLpf < throttle) {
pidRuntime.antiGravityPBoost *= 0.5f;
}
// high-passed throttle focuses boost on faster throttle changes
pidRuntime.antiGravityThrottleHpf = fabsf(throttle - antiGravityThrottleLpf);
pidRuntime.antiGravityPBoost = pidRuntime.antiGravityPBoost * pidRuntime.antiGravityThrottleHpf;
// smooth the P boost at 3hz to remove the jagged edges and prolong the effect after throttle stops
pidRuntime.antiGravityPBoost = pt1FilterApply(&pidRuntime.antiGravitySmoothLpf, pidRuntime.antiGravityPBoost);
static float previousThrottle = 0.0f;
const float throttleInv = 1.0f - throttle;
float throttleDerivative = fabsf(throttle - previousThrottle) * pidRuntime.pidFrequency;
DEBUG_SET(DEBUG_ANTI_GRAVITY, 0, lrintf(throttleDerivative * 100));
throttleDerivative *= throttleInv * throttleInv;
// generally focus on the low throttle period
if (throttle > previousThrottle) {
throttleDerivative *= throttleInv * 0.5f;
// when increasing throttle, focus even more on the low throttle range
}
previousThrottle = throttle;
throttleDerivative = pt2FilterApply(&pidRuntime.antiGravityLpf, throttleDerivative);
// lower cutoff suppresses peaks relative to troughs and prolongs the effects
// PT2 smoothing of throttle derivative.
// 6 is a typical value for the peak boost factor with default cutoff of 6Hz
DEBUG_SET(DEBUG_ANTI_GRAVITY, 1, lrintf(throttleDerivative * 100));
pidRuntime.antiGravityThrottleD = throttleDerivative;
}
#ifdef USE_ACRO_TRAINER
@ -874,32 +872,27 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
UNUSED(currentTimeUs);
#endif
// Dynamic i component,
if ((pidRuntime.antiGravityMode == ANTI_GRAVITY_SMOOTH) && pidRuntime.antiGravityEnabled) {
// traditional itermAccelerator factor for iTerm
pidRuntime.itermAccelerator = pidRuntime.antiGravityThrottleHpf * 0.01f * pidRuntime.itermAcceleratorGain;
DEBUG_SET(DEBUG_ANTI_GRAVITY, 1, lrintf(pidRuntime.itermAccelerator * 1000));
// users AG Gain changes P boost
pidRuntime.antiGravityPBoost *= pidRuntime.itermAcceleratorGain;
// add some percentage of that slower, longer acting P boost factor to prolong AG effect on iTerm
pidRuntime.itermAccelerator += pidRuntime.antiGravityPBoost * 0.05f;
// set the final P boost amount
pidRuntime.antiGravityPBoost *= 0.02f;
// Anti Gravity
if (pidRuntime.antiGravityEnabled) {
pidRuntime.antiGravityThrottleD *= pidRuntime.antiGravityGain;
// used later to increase pTerm
pidRuntime.itermAccelerator = pidRuntime.antiGravityThrottleD * ANTIGRAVITY_KI;
} else {
pidRuntime.antiGravityPBoost = 0.0f;
pidRuntime.antiGravityThrottleD = 0.0f;
pidRuntime.itermAccelerator = 0.0f;
}
DEBUG_SET(DEBUG_ANTI_GRAVITY, 0, lrintf(pidRuntime.itermAccelerator * 1000));
DEBUG_SET(DEBUG_ANTI_GRAVITY, 2, lrintf((1 + (pidRuntime.itermAccelerator / pidRuntime.pidCoefficient[FD_PITCH].Ki)) * 1000));
// amount of antigravity added relative to user's pitch iTerm coefficient
pidRuntime.itermAccelerator *= pidRuntime.dT;
// used later to increase iTerm
const float agGain = pidRuntime.dT * pidRuntime.itermAccelerator * AG_KI;
// gradually scale back integration when above windup point
// iTerm windup (attenuation of iTerm if motorMix range is large)
float dynCi = pidRuntime.dT;
if (pidRuntime.itermWindupPointInv > 1.0f) {
dynCi *= constrainf((1.0f - getMotorMixRange()) * pidRuntime.itermWindupPointInv, 0.0f, 1.0f);
}
// Precalculate gyro deta for D-term here, this allows loop unrolling
// Precalculate gyro delta for D-term here, this allows loop unrolling
float gyroRateDterm[XYZ_AXIS_COUNT];
for (int axis = FD_ROLL; axis <= FD_YAW; ++axis) {
gyroRateDterm[axis] = gyro.gyroADCf[axis];
@ -1010,8 +1003,8 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
}
// -----calculate I component
float Ki;
float axisDynCi;
float Ki = pidRuntime.pidCoefficient[axis].Ki;
float axisDynCi = pidRuntime.dT;
#ifdef USE_LAUNCH_CONTROL
// if launch control is active override the iterm gains and apply iterm windup protection to all axes
if (launchControlActive) {
@ -1020,11 +1013,13 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
} else
#endif
{
Ki = pidRuntime.pidCoefficient[axis].Ki;
axisDynCi = (axis == FD_YAW) ? dynCi : pidRuntime.dT; // only apply windup protection to yaw
if (axis == FD_YAW) {
axisDynCi = dynCi; // only apply windup protection to yaw
pidRuntime.itermAccelerator = 0.0f; // no antigravity on yaw iTerm
}
}
pidData[axis].I = constrainf(previousIterm + (Ki * axisDynCi + agGain) * itermErrorRate, -pidRuntime.itermLimit, pidRuntime.itermLimit);
pidData[axis].I = constrainf(previousIterm + (Ki * axisDynCi + pidRuntime.itermAccelerator) * itermErrorRate, -pidRuntime.itermLimit, pidRuntime.itermLimit);
// -----calculate pidSetpointDelta
float pidSetpointDelta = 0;
@ -1149,18 +1144,20 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
}
}
#endif
// calculating the PID sum
// P boost at the end of throttle chop
// attenuate effect if turning more than 50 deg/s, half at 100 deg/s
float agBoostAttenuator = fabsf(currentPidSetpoint) / 50.0f;
agBoostAttenuator = MAX(agBoostAttenuator, 1.0f);
const float agBoost = 1.0f + (pidRuntime.antiGravityPBoost / agBoostAttenuator);
// Add P boost from antiGravity when sticks are close to zero
if (axis != FD_YAW) {
pidData[axis].P *= agBoost;
DEBUG_SET(DEBUG_ANTI_GRAVITY, axis - FD_ROLL + 2, lrintf(agBoost * 1000));
float agSetpointAttenuator = fabsf(currentPidSetpoint) / 50.0f;
agSetpointAttenuator = MAX(agSetpointAttenuator, 1.0f);
// attenuate effect if turning more than 50 deg/s, half at 100 deg/s
const float antiGravityPBoost = 1.0f + (pidRuntime.antiGravityThrottleD / agSetpointAttenuator) * pidRuntime.antiGravityPGain;
pidData[axis].P *= antiGravityPBoost;
if (axis == FD_PITCH) {
DEBUG_SET(DEBUG_ANTI_GRAVITY, 3, lrintf(antiGravityPBoost * 1000));
}
}
// calculating the PID sum
const float pidSum = pidData[axis].P + pidData[axis].I + pidData[axis].D + pidData[axis].F;
#ifdef USE_INTEGRATED_YAW_CONTROL
if (axis == FD_YAW && pidRuntime.useIntegratedYaw) {