mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 11:29:58 +03:00
TPA mode PDS + Wing setpoint attenuation (for wings) (#14010)
* TPA mode PDS + Wing setpoint attenuation * removed brackets by haslinghuis :) * Ledvinap's review --------- Co-authored-by: limonspb <gendalf44@yandex.ru>
This commit is contained in:
parent
ed6a4a4769
commit
1c1c78f80f
5 changed files with 114 additions and 29 deletions
|
@ -118,6 +118,12 @@ PG_RESET_TEMPLATE(pidConfig_t, pidConfig,
|
|||
|
||||
#define LAUNCH_CONTROL_YAW_ITERM_LIMIT 50 // yaw iterm windup limit when launch mode is "FULL" (all axes)
|
||||
|
||||
#ifdef USE_ACC
|
||||
#define IS_AXIS_IN_ANGLE_MODE(i) (pidRuntime.axisInAngleMode[(i)])
|
||||
#else
|
||||
#define IS_AXIS_IN_ANGLE_MODE(i) false
|
||||
#endif // USE_ACC
|
||||
|
||||
PG_REGISTER_ARRAY_WITH_RESET_FN(pidProfile_t, PID_PROFILE_COUNT, pidProfiles, PG_PID_PROFILE, 11);
|
||||
|
||||
void resetPidProfile(pidProfile_t *pidProfile)
|
||||
|
@ -256,6 +262,21 @@ void resetPidProfile(pidProfile_t *pidProfile)
|
|||
);
|
||||
}
|
||||
|
||||
static bool isTpaActive(tpaMode_e tpaMode, term_e term) {
|
||||
switch (tpaMode) {
|
||||
case TPA_MODE_PD:
|
||||
return term == TERM_P || term == TERM_D;
|
||||
case TPA_MODE_D:
|
||||
return term == TERM_D;
|
||||
#ifdef USE_WING
|
||||
case TPA_MODE_PDS:
|
||||
return term == TERM_P || term == TERM_D || term == TERM_S;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void pgResetFn_pidProfiles(pidProfile_t *pidProfiles)
|
||||
{
|
||||
for (int i = 0; i < PID_PROFILE_COUNT; i++) {
|
||||
|
@ -343,8 +364,50 @@ static float calcWingTpaArgument(void)
|
|||
|
||||
return tpaArgument;
|
||||
}
|
||||
|
||||
static void updateStermTpaFactor(int axis, float tpaFactor)
|
||||
{
|
||||
float tpaFactorSterm = tpaFactor;
|
||||
if (pidRuntime.tpaCurveType == TPA_CURVE_HYPERBOLIC) {
|
||||
const float maxSterm = tpaFactorSterm * (float)currentPidProfile->pid[axis].S * S_TERM_SCALE;
|
||||
if (maxSterm > 1.0f) {
|
||||
tpaFactorSterm *= 1.0f / maxSterm;
|
||||
}
|
||||
}
|
||||
pidRuntime.tpaFactorSterm[axis] = tpaFactorSterm;
|
||||
}
|
||||
|
||||
static void updateStermTpaFactors(void) {
|
||||
for (int i = 0; i < XYZ_AXIS_COUNT; i++) {
|
||||
float tpaFactor = pidRuntime.tpaFactor;
|
||||
if (i == FD_YAW && currentPidProfile->yaw_type == YAW_TYPE_DIFF_THRUST) {
|
||||
tpaFactor = pidRuntime.tpaFactorYaw;
|
||||
}
|
||||
updateStermTpaFactor(i, tpaFactor);
|
||||
}
|
||||
}
|
||||
#endif // USE_WING
|
||||
|
||||
static float wingAdjustSetpoint(float currentPidSetpoint, int axis)
|
||||
{
|
||||
#ifdef USE_WING
|
||||
float adjustedSetpoint = currentPidSetpoint;
|
||||
if (!IS_AXIS_IN_ANGLE_MODE(axis)) {
|
||||
const bool skipYaw = axis == FD_YAW && currentPidProfile->yaw_type == YAW_TYPE_DIFF_THRUST;
|
||||
if (pidRuntime.tpaFactorSterm[axis] > 0.0f && pidRuntime.tpaFactor > 0.0f && !skipYaw) {
|
||||
adjustedSetpoint = currentPidSetpoint * pidRuntime.tpaFactorSterm[axis] / pidRuntime.tpaFactor;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_SET(DEBUG_WING_SETPOINT, 2 * axis, lrintf(currentPidSetpoint));
|
||||
DEBUG_SET(DEBUG_WING_SETPOINT, 2 * axis + 1, lrintf(adjustedSetpoint));
|
||||
return adjustedSetpoint;
|
||||
#else
|
||||
UNUSED(axis);
|
||||
return currentPidSetpoint;
|
||||
#endif // USE_WING
|
||||
}
|
||||
|
||||
float getTpaFactorClassic(float tpaArgument)
|
||||
{
|
||||
static bool isTpaLowFaded = false;
|
||||
|
@ -399,6 +462,7 @@ void pidUpdateTpaFactor(float throttle)
|
|||
pidRuntime.tpaFactorYaw = pidRuntime.tpaFactor;
|
||||
break;
|
||||
}
|
||||
updateStermTpaFactors();
|
||||
#endif // USE_WING
|
||||
}
|
||||
|
||||
|
@ -930,18 +994,48 @@ static FAST_CODE_NOINLINE float applyLaunchControl(int axis, const rollAndPitchT
|
|||
}
|
||||
#endif
|
||||
|
||||
static float getSterm(int axis, const pidProfile_t *pidProfile)
|
||||
static float getTpaFactor(const pidProfile_t *pidProfile, int axis, term_e term)
|
||||
{
|
||||
float tpaFactor = pidRuntime.tpaFactor;
|
||||
|
||||
#ifdef USE_WING
|
||||
if (axis == FD_YAW) {
|
||||
tpaFactor = pidRuntime.tpaFactorYaw;
|
||||
}
|
||||
#else
|
||||
UNUSED(axis);
|
||||
#endif
|
||||
|
||||
const bool tpaActive = isTpaActive(pidProfile->tpa_mode, term);
|
||||
switch (term) {
|
||||
case TERM_P:
|
||||
return tpaActive ? tpaFactor : 1.0f;
|
||||
case TERM_D:
|
||||
return tpaFactor;
|
||||
#ifdef USE_WING
|
||||
case TERM_S:
|
||||
return tpaActive ? pidRuntime.tpaFactorSterm[axis] : 1.0f;
|
||||
#endif
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static float getSterm(int axis, const pidProfile_t *pidProfile, float setpoint)
|
||||
{
|
||||
#ifdef USE_WING
|
||||
const float sTerm = getSetpointRate(axis) / getMaxRcRate(axis) * 1000.0f *
|
||||
(float)pidProfile->pid[axis].S / 100.0f;
|
||||
float sTerm = setpoint / getMaxRcRate(axis) * 1000.0f *
|
||||
(float)pidProfile->pid[axis].S * S_TERM_SCALE;
|
||||
|
||||
DEBUG_SET(DEBUG_S_TERM, axis, lrintf(sTerm));
|
||||
DEBUG_SET(DEBUG_S_TERM, 2 * axis, lrintf(sTerm));
|
||||
sTerm *= getTpaFactor(pidProfile, axis, TERM_S);
|
||||
DEBUG_SET(DEBUG_S_TERM, 2 * axis + 1, lrintf(sTerm));
|
||||
|
||||
return sTerm;
|
||||
#else
|
||||
UNUSED(axis);
|
||||
UNUSED(pidProfile);
|
||||
UNUSED(setpoint);
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
@ -993,28 +1087,6 @@ NOINLINE static void applySpa(int axis, const pidProfile_t *pidProfile)
|
|||
#endif // USE_WING
|
||||
}
|
||||
|
||||
static float getTpaFactor(const pidProfile_t *pidProfile, int axis, term_e term)
|
||||
{
|
||||
float tpaFactor = pidRuntime.tpaFactor;
|
||||
|
||||
#ifdef USE_WING
|
||||
if (axis == FD_YAW) {
|
||||
tpaFactor = pidRuntime.tpaFactorYaw;
|
||||
}
|
||||
#else
|
||||
UNUSED(axis);
|
||||
#endif
|
||||
|
||||
switch (term) {
|
||||
case TERM_P:
|
||||
return (pidProfile->tpa_mode == TPA_MODE_PD) ? tpaFactor : 1.0f;
|
||||
case TERM_D:
|
||||
return tpaFactor;
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Betaflight pid controller, which will be maintained in the future with additional features specialised for current (mini) multirotor usage.
|
||||
// Based on 2DOF reference design (matlab)
|
||||
void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTimeUs)
|
||||
|
@ -1145,6 +1217,9 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
|
|||
}
|
||||
#endif
|
||||
|
||||
const float currentPidSetpointBeforeWingAdjust = currentPidSetpoint;
|
||||
currentPidSetpoint = wingAdjustSetpoint(currentPidSetpoint, axis);
|
||||
|
||||
#ifdef USE_ACRO_TRAINER
|
||||
if ((axis != FD_YAW) && pidRuntime.acroTrainerActive && !pidRuntime.inCrashRecoveryMode && !launchControlActive) {
|
||||
currentPidSetpoint = applyAcroTrainer(axis, angleTrim, currentPidSetpoint);
|
||||
|
@ -1367,7 +1442,7 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
|
|||
}
|
||||
}
|
||||
|
||||
pidData[axis].S = getSterm(axis, pidProfile);
|
||||
pidData[axis].S = getSterm(axis, pidProfile, currentPidSetpointBeforeWingAdjust);
|
||||
applySpa(axis, pidProfile);
|
||||
|
||||
// calculating the PID sum
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue