1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-25 17:25:20 +03:00

Remove d min confusion (#13908)

* rename dMin, remove D_MIN_GAIN_MAX

* rename vars

* fix logic

* fix logic

* Revert "fix tests"

This reverts commit c518c9c444.

* Revert "add yaw and other adjustment cases"

This reverts commit 2cacd4b360.

* Revert "fix unit test"

This reverts commit 3d88f4158a.

* Revert "fix D adjustments change dmax instead of D"

This reverts commit 7ee4e7f8af.

* Revert "Fix telemetry for Spektrum/SRXL (#13814)"

This reverts commit 04fe4b4461.

* review adjustments and test fixes

* Reapply "Fix telemetry for Spektrum/SRXL (#13814)"

This reverts commit eb7f8ee0fd.

* fix logic

* Apply suggestions from code review

Co-authored-by: Jan Post <Rm2k-Freak@web.de>
Co-authored-by: Mark Haslinghuis <mark@numloq.nl>

* fix d_max slider

---------

Co-authored-by: Jan Post <Rm2k-Freak@web.de>
Co-authored-by: Mark Haslinghuis <mark@numloq.nl>
This commit is contained in:
MikeNomatter 2024-09-24 11:28:25 +02:00 committed by GitHub
parent c0c24d7f52
commit 908f9cc32d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 143 additions and 154 deletions

View file

@ -1465,12 +1465,12 @@ static bool blackboxWriteSysinfo(void)
currentPidProfile->pid[PID_LEVEL].I,
currentPidProfile->pid[PID_LEVEL].D);
BLACKBOX_PRINT_HEADER_LINE("magPID", "%d", currentPidProfile->pid[PID_MAG].P);
#ifdef USE_D_MIN
BLACKBOX_PRINT_HEADER_LINE("d_min", "%d,%d,%d", currentPidProfile->d_min[ROLL],
currentPidProfile->d_min[PITCH],
currentPidProfile->d_min[YAW]);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_D_MAX_GAIN, "%d", currentPidProfile->d_min_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_D_MAX_ADVANCE, "%d", currentPidProfile->d_min_advance);
#ifdef USE_D_MAX
BLACKBOX_PRINT_HEADER_LINE("d_max", "%d,%d,%d", currentPidProfile->d_max[ROLL],
currentPidProfile->d_max[PITCH],
currentPidProfile->d_max[YAW]);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_D_MAX_GAIN, "%d", currentPidProfile->d_max_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_D_MAX_ADVANCE, "%d", currentPidProfile->d_max_advance);
#endif
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_DTERM_LPF1_TYPE, "%d", currentPidProfile->dterm_lpf1_type);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_DTERM_LPF1_STATIC_HZ, "%d", currentPidProfile->dterm_lpf1_static_hz);
@ -1641,7 +1641,7 @@ static bool blackboxWriteSysinfo(void)
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_I_GAIN, "%d", currentPidProfile->simplified_i_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_D_GAIN, "%d", currentPidProfile->simplified_d_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_PI_GAIN, "%d", currentPidProfile->simplified_pi_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_DMAX_GAIN, "%d", currentPidProfile->simplified_dmin_ratio);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_D_MAX_GAIN, "%d", currentPidProfile->simplified_d_max_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_FEEDFORWARD_GAIN, "%d", currentPidProfile->simplified_feedforward_gain);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_PITCH_D_GAIN, "%d", currentPidProfile->simplified_roll_pitch_ratio);
BLACKBOX_PRINT_HEADER_LINE(PARAM_NAME_SIMPLIFIED_PITCH_PI_GAIN, "%d", currentPidProfile->simplified_pitch_pi_gain);

View file

@ -74,7 +74,7 @@ const char * const debugModeNames[DEBUG_COUNT] = {
[DEBUG_RX_SPEKTRUM_SPI] = "RX_SPEKTRUM_SPI",
[DEBUG_DSHOT_RPM_TELEMETRY] = "DSHOT_RPM_TELEMETRY",
[DEBUG_RPM_FILTER] = "RPM_FILTER",
[DEBUG_D_MIN] = "D_MIN",
[DEBUG_D_MAX] = "D_MAX",
[DEBUG_AC_CORRECTION] = "AC_CORRECTION",
[DEBUG_AC_ERROR] = "AC_ERROR",
[DEBUG_DUAL_GYRO_SCALED] = "DUAL_GYRO_SCALED",

View file

@ -76,7 +76,7 @@ typedef enum {
DEBUG_RX_SPEKTRUM_SPI,
DEBUG_DSHOT_RPM_TELEMETRY,
DEBUG_RPM_FILTER,
DEBUG_D_MIN,
DEBUG_D_MAX,
DEBUG_AC_CORRECTION,
DEBUG_AC_ERROR,
DEBUG_DUAL_GYRO_SCALED,

View file

@ -1214,12 +1214,12 @@ const clivalue_t valueTable[] = {
{ "integrated_yaw_relax", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 255 }, PG_PID_PROFILE, offsetof(pidProfile_t, integrated_yaw_relax) },
#endif
#ifdef USE_D_MIN
{ "d_min_roll", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, D_MIN_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_min[FD_ROLL]) },
{ "d_min_pitch", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, D_MIN_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_min[FD_PITCH]) },
{ "d_min_yaw", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, D_MIN_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_min[FD_YAW]) },
{ PARAM_NAME_D_MAX_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_PID_PROFILE, offsetof(pidProfile_t, d_min_gain) },
{ PARAM_NAME_D_MAX_ADVANCE, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_PID_PROFILE, offsetof(pidProfile_t, d_min_advance) },
#ifdef USE_D_MAX
{ "d_max_roll", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, PID_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_max[FD_ROLL]) },
{ "d_max_pitch", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, PID_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_max[FD_PITCH]) },
{ "d_max_yaw", VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, PID_GAIN_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, d_max[FD_YAW]) },
{ PARAM_NAME_D_MAX_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_PID_PROFILE, offsetof(pidProfile_t, d_max_gain) },
{ PARAM_NAME_D_MAX_ADVANCE, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_PID_PROFILE, offsetof(pidProfile_t, d_max_advance) },
#endif
{ PARAM_NAME_MOTOR_OUTPUT_LIMIT, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { MOTOR_OUTPUT_LIMIT_PERCENT_MIN, MOTOR_OUTPUT_LIMIT_PERCENT_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, motor_output_limit) },
@ -1268,7 +1268,7 @@ const clivalue_t valueTable[] = {
{ PARAM_NAME_SIMPLIFIED_I_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_i_gain) },
{ PARAM_NAME_SIMPLIFIED_D_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_d_gain) },
{ PARAM_NAME_SIMPLIFIED_PI_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_pi_gain) },
{ PARAM_NAME_SIMPLIFIED_DMAX_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_dmin_ratio) },
{ PARAM_NAME_SIMPLIFIED_D_MAX_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_d_max_gain) },
{ PARAM_NAME_SIMPLIFIED_FEEDFORWARD_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { 0, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_feedforward_gain) },
{ PARAM_NAME_SIMPLIFIED_PITCH_D_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_roll_pitch_ratio) },
{ PARAM_NAME_SIMPLIFIED_PITCH_PI_GAIN, VAR_UINT8 | PROFILE_VALUE, .config.minmaxUnsigned = { SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX }, PG_PID_PROFILE, offsetof(pidProfile_t, simplified_pitch_pi_gain) },

View file

@ -251,8 +251,8 @@ static uint8_t cmsx_simplified_roll_pitch_ratio;
static uint8_t cmsx_simplified_i_gain;
static uint8_t cmsx_simplified_d_gain;
static uint8_t cmsx_simplified_pi_gain;
#ifdef USE_D_MIN
static uint8_t cmsx_simplified_dmin_ratio;
#ifdef USE_D_MAX
static uint8_t cmsx_simplified_d_max_gain;
#endif
static uint8_t cmsx_simplified_feedforward_gain;
static uint8_t cmsx_simplified_pitch_pi_gain;
@ -280,8 +280,8 @@ static const void *cmsx_simplifiedTuningOnEnter(displayPort_t *pDisp)
cmsx_simplified_i_gain = pidProfile->simplified_i_gain;
cmsx_simplified_d_gain = pidProfile->simplified_d_gain;
cmsx_simplified_pi_gain = pidProfile->simplified_pi_gain;
#ifdef USE_D_MIN
cmsx_simplified_dmin_ratio = pidProfile->simplified_dmin_ratio;
#ifdef USE_D_MAX
cmsx_simplified_d_max_gain = pidProfile->simplified_d_max_gain;
#endif
cmsx_simplified_feedforward_gain = pidProfile->simplified_feedforward_gain;
cmsx_simplified_pitch_pi_gain = pidProfile->simplified_pitch_pi_gain;
@ -307,8 +307,8 @@ static const void *cmsx_simplifiedTuningOnExit(displayPort_t *pDisp, const OSD_E
|| pidProfile->simplified_i_gain != cmsx_simplified_i_gain
|| pidProfile->simplified_d_gain != cmsx_simplified_d_gain
|| pidProfile->simplified_pi_gain != cmsx_simplified_pi_gain
#ifdef USE_D_MIN
|| pidProfile->simplified_dmin_ratio != cmsx_simplified_dmin_ratio
#ifdef USE_D_MAX
|| pidProfile->simplified_d_max_gain != cmsx_simplified_d_max_gain
#endif
|| pidProfile->simplified_feedforward_gain != cmsx_simplified_feedforward_gain
|| pidProfile->simplified_pitch_pi_gain != cmsx_simplified_pitch_pi_gain
@ -324,8 +324,8 @@ static const void *cmsx_simplifiedTuningOnExit(displayPort_t *pDisp, const OSD_E
pidProfile->simplified_i_gain = cmsx_simplified_i_gain;
pidProfile->simplified_d_gain = cmsx_simplified_d_gain;
pidProfile->simplified_pi_gain = cmsx_simplified_pi_gain;
#ifdef USE_D_MIN
pidProfile->simplified_dmin_ratio = cmsx_simplified_dmin_ratio;
#ifdef USE_D_MAX
pidProfile->simplified_d_max_gain = cmsx_simplified_d_max_gain;
#endif
pidProfile->simplified_feedforward_gain = cmsx_simplified_feedforward_gain;
pidProfile->simplified_pitch_pi_gain = cmsx_simplified_pitch_pi_gain;
@ -352,8 +352,8 @@ static const OSD_Entry cmsx_menuSimplifiedTuningEntries[] =
{ "FF GAINS", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_simplified_feedforward_gain, SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX, 5, 10 } },
{ "-- EXPERT --", OME_Label, NULL, NULL},
#ifdef USE_D_MIN
{ "D MAX", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_simplified_dmin_ratio, SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX, 5, 10 } },
#ifdef USE_D_MAX
{ "D MAX", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_simplified_d_max_gain, SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX, 5, 10 } },
#endif
{ "I GAINS", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_simplified_i_gain, SIMPLIFIED_TUNING_PIDS_MIN, SIMPLIFIED_TUNING_MAX, 5, 10 } },
@ -527,10 +527,10 @@ static uint8_t cmsx_thrustLinearization;
static uint8_t cmsx_antiGravityGain;
static uint8_t cmsx_motorOutputLimit;
static int8_t cmsx_autoProfileCellCount;
#ifdef USE_D_MIN
static uint8_t cmsx_d_min[XYZ_AXIS_COUNT];
static uint8_t cmsx_d_min_gain;
static uint8_t cmsx_d_min_advance;
#ifdef USE_D_MAX
static uint8_t cmsx_d_max[XYZ_AXIS_COUNT];
static uint8_t cmsx_d_max_gain;
static uint8_t cmsx_d_max_advance;
#endif
#ifdef USE_BATTERY_VOLTAGE_SAG_COMPENSATION
@ -581,12 +581,12 @@ static const void *cmsx_profileOtherOnEnter(displayPort_t *pDisp)
cmsx_motorOutputLimit = pidProfile->motor_output_limit;
cmsx_autoProfileCellCount = pidProfile->auto_profile_cell_count;
#ifdef USE_D_MIN
#ifdef USE_D_MAX
for (unsigned i = 0; i < XYZ_AXIS_COUNT; i++) {
cmsx_d_min[i] = pidProfile->d_min[i];
cmsx_d_max[i] = pidProfile->d_max[i];
}
cmsx_d_min_gain = pidProfile->d_min_gain;
cmsx_d_min_advance = pidProfile->d_min_advance;
cmsx_d_max_gain = pidProfile->d_max_gain;
cmsx_d_max_advance = pidProfile->d_max_advance;
#endif
#ifdef USE_ITERM_RELAX
@ -639,12 +639,12 @@ static const void *cmsx_profileOtherOnExit(displayPort_t *pDisp, const OSD_Entry
pidProfile->motor_output_limit = cmsx_motorOutputLimit;
pidProfile->auto_profile_cell_count = cmsx_autoProfileCellCount;
#ifdef USE_D_MIN
#ifdef USE_D_MAX
for (unsigned i = 0; i < XYZ_AXIS_COUNT; i++) {
pidProfile->d_min[i] = cmsx_d_min[i];
pidProfile->d_max[i] = cmsx_d_max[i];
}
pidProfile->d_min_gain = cmsx_d_min_gain;
pidProfile->d_min_advance = cmsx_d_min_advance;
pidProfile->d_max_gain = cmsx_d_max_gain;
pidProfile->d_max_advance = cmsx_d_max_advance;
#endif
#ifdef USE_ITERM_RELAX
@ -713,12 +713,12 @@ static const OSD_Entry cmsx_menuProfileOtherEntries[] = {
{ "AUTO CELL CNT", OME_INT8, NULL, &(OSD_INT8_t) { &cmsx_autoProfileCellCount, AUTO_PROFILE_CELL_COUNT_CHANGE, MAX_AUTO_DETECT_CELL_COUNT, 1} },
#ifdef USE_D_MIN
{ "D_MIN ROLL", OME_UINT8 | SLIDER_RP, NULL, &(OSD_UINT8_t) { &cmsx_d_min[FD_ROLL], 0, 100, 1 } },
{ "D_MIN PITCH", OME_UINT8 | SLIDER_RP, NULL, &(OSD_UINT8_t) { &cmsx_d_min[FD_PITCH], 0, 100, 1 } },
{ "D_MIN YAW", OME_UINT8 | SLIDER_RPY, NULL, &(OSD_UINT8_t) { &cmsx_d_min[FD_YAW], 0, 100, 1 } },
{ "D_MIN GAIN", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_d_min_gain, 0, 100, 1 } },
{ "D_MIN ADV", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_d_min_advance, 0, 200, 1 } },
#ifdef USE_D_MAX
{ "D_MAX ROLL", OME_UINT8 | SLIDER_RP, NULL, &(OSD_UINT8_t) { &cmsx_d_max[FD_ROLL], 0, 100, 1 } },
{ "D_MAX PITCH", OME_UINT8 | SLIDER_RP, NULL, &(OSD_UINT8_t) { &cmsx_d_max[FD_PITCH], 0, 100, 1 } },
{ "D_MAX YAW", OME_UINT8 | SLIDER_RPY, NULL, &(OSD_UINT8_t) { &cmsx_d_max[FD_YAW], 0, 100, 1 } },
{ "D_MAX GAIN", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_d_max_gain, 0, 100, 1 } },
{ "D_MAX ADV", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_d_max_advance, 0, 200, 1 } },
#endif
#ifdef USE_BATTERY_VOLTAGE_SAG_COMPENSATION

View file

@ -275,10 +275,10 @@ static void validateAndFixConfig(void)
pidProfilesMutable(i)->auto_profile_cell_count = AUTO_PROFILE_CELL_COUNT_STAY;
}
// If the d_min value for any axis is >= the D gain then reset d_min to 0 for consistent Configurator behavior
// If the d_max value for any axis is <= the D gain then reset d_max to 0 for consistent Configurator behavior
for (unsigned axis = 0; axis <= FD_YAW; axis++) {
if (pidProfilesMutable(i)->d_min[axis] > pidProfilesMutable(i)->pid[axis].D) {
pidProfilesMutable(i)->d_min[axis] = 0;
if (pidProfilesMutable(i)->d_max[axis] < pidProfilesMutable(i)->pid[axis].D) {
pidProfilesMutable(i)->d_max[axis] = 0;
}
}

View file

@ -36,8 +36,8 @@ static void calculateNewPidValues(pidProfile_t *pidProfile)
[PID_YAW] = PID_YAW_DEFAULT,
};
#ifdef USE_D_MIN
const int dMinDefaults[FLIGHT_DYNAMICS_INDEX_COUNT] = D_MIN_DEFAULT;
#ifdef USE_D_MAX
const int dMaxDefaults[FLIGHT_DYNAMICS_INDEX_COUNT] = D_MAX_DEFAULT;
#endif
const float masterMultiplier = pidProfile->simplified_master_multiplier / 100.0f;
const float piGain = pidProfile->simplified_pi_gain / 100.0f;
@ -50,14 +50,15 @@ static void calculateNewPidValues(pidProfile_t *pidProfile)
const float pitchPiGain = (axis == FD_PITCH) ? pidProfile->simplified_pitch_pi_gain / 100.0f : 1.0f;
pidProfile->pid[axis].P = constrain(pidDefaults[axis].P * masterMultiplier * piGain * pitchPiGain, 0, PID_GAIN_MAX);
pidProfile->pid[axis].I = constrain(pidDefaults[axis].I * masterMultiplier * piGain * iGain * pitchPiGain, 0, PID_GAIN_MAX);
#ifdef USE_D_MIN
const float dminRatio = (dMinDefaults[axis] > 0) ? 1.0f + (((float)pidDefaults[axis].D - dMinDefaults[axis]) / dMinDefaults[axis]) * (pidProfile->simplified_dmin_ratio / 100.0f) : 1.0f;
pidProfile->pid[axis].D = constrain(dMinDefaults[axis] * masterMultiplier * dGain * pitchDGain * dminRatio, 0, PID_GAIN_MAX);
pidProfile->d_min[axis] = constrain(dMinDefaults[axis] * masterMultiplier * dGain * pitchDGain, 0, PID_GAIN_MAX);
#else
pidProfile->pid[axis].D = constrain(dMinDefaults[axis] * masterMultiplier * dGain * pitchDGain, 0, PID_GAIN_MAX);
#endif
pidProfile->pid[axis].D = constrain(pidDefaults[axis].D * masterMultiplier * dGain * pitchDGain, 0, PID_GAIN_MAX);
pidProfile->pid[axis].F = constrain(pidDefaults[axis].F * masterMultiplier * pitchPiGain * feedforwardGain, 0, F_GAIN_MAX);
#ifdef USE_D_MAX
const float dMaxGain = (dMaxDefaults[axis] > 0)
? pidProfile->simplified_d_max_gain / 100.0f + (1 - pidProfile->simplified_d_max_gain / 100.0f) * pidDefaults[axis].D / dMaxDefaults[axis]
: 1.0f;
pidProfile->d_max[axis] = constrain(dMaxDefaults[axis] * masterMultiplier * dGain * pitchDGain * dMaxGain, 0, PID_GAIN_MAX);
#endif
}
}

View file

@ -133,7 +133,7 @@
#define PARAM_NAME_SIMPLIFIED_I_GAIN "simplified_i_gain"
#define PARAM_NAME_SIMPLIFIED_D_GAIN "simplified_d_gain"
#define PARAM_NAME_SIMPLIFIED_PI_GAIN "simplified_pi_gain"
#define PARAM_NAME_SIMPLIFIED_DMAX_GAIN "simplified_dmax_gain"
#define PARAM_NAME_SIMPLIFIED_D_MAX_GAIN "simplified_d_max_gain"
#define PARAM_NAME_SIMPLIFIED_FEEDFORWARD_GAIN "simplified_feedforward_gain"
#define PARAM_NAME_SIMPLIFIED_PITCH_D_GAIN "simplified_pitch_d_gain"
#define PARAM_NAME_SIMPLIFIED_PITCH_PI_GAIN "simplified_pitch_pi_gain"

View file

@ -364,8 +364,8 @@ static int applyStepAdjustment(controlRateConfig_t *controlRateConfig, uint8_t a
break;
case ADJUSTMENT_PITCH_ROLL_D:
case ADJUSTMENT_PITCH_D:
newValue = constrain((int)currentPidProfile->d_min[FD_PITCH] + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_PITCH] = newValue;
newValue = constrain((int)currentPidProfile->pid[PID_PITCH].D + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->pid[PID_PITCH].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_D, newValue);
if (adjustmentFunction == ADJUSTMENT_PITCH_D) {
break;
@ -373,8 +373,8 @@ static int applyStepAdjustment(controlRateConfig_t *controlRateConfig, uint8_t a
// fall through for combined ADJUSTMENT_PITCH_ROLL_D
FALLTHROUGH;
case ADJUSTMENT_ROLL_D:
newValue = constrain((int)currentPidProfile->d_min[FD_ROLL] + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_ROLL] = newValue;
newValue = constrain((int)currentPidProfile->pid[PID_ROLL].D + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->pid[PID_ROLL].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_D, newValue);
break;
case ADJUSTMENT_YAW_P:
@ -388,8 +388,8 @@ static int applyStepAdjustment(controlRateConfig_t *controlRateConfig, uint8_t a
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_I, newValue);
break;
case ADJUSTMENT_YAW_D:
newValue = constrain((int)currentPidProfile->d_min[FD_YAW] + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_YAW] = newValue;
newValue = constrain((int)currentPidProfile->pid[PID_YAW].D + delta, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->pid[PID_YAW].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_D, newValue);
break;
case ADJUSTMENT_RC_RATE_YAW:
@ -528,7 +528,7 @@ static int applyAbsoluteAdjustment(controlRateConfig_t *controlRateConfig, adjus
case ADJUSTMENT_PITCH_ROLL_D:
case ADJUSTMENT_PITCH_D:
newValue = constrain(value, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_PITCH] = newValue;
currentPidProfile->pid[PID_PITCH].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_D, newValue);
if (adjustmentFunction == ADJUSTMENT_PITCH_D) {
break;
@ -537,7 +537,7 @@ static int applyAbsoluteAdjustment(controlRateConfig_t *controlRateConfig, adjus
FALLTHROUGH;
case ADJUSTMENT_ROLL_D:
newValue = constrain(value, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_ROLL] = newValue;
currentPidProfile->pid[PID_ROLL].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_D, newValue);
break;
case ADJUSTMENT_YAW_P:
@ -552,7 +552,7 @@ static int applyAbsoluteAdjustment(controlRateConfig_t *controlRateConfig, adjus
break;
case ADJUSTMENT_YAW_D:
newValue = constrain(value, 0, 200); // FIXME magic numbers repeated in cli.c
currentPidProfile->d_min[FD_YAW] = newValue;
currentPidProfile->pid[PID_YAW].D = newValue;
blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_D, newValue);
break;
case ADJUSTMENT_RC_RATE_YAW:

View file

@ -186,9 +186,9 @@ void resetPidProfile(pidProfile_t *pidProfile)
.use_integrated_yaw = false,
.integrated_yaw_relax = 200,
.thrustLinearization = 0,
.d_min = D_MIN_DEFAULT,
.d_min_gain = 37,
.d_min_advance = 20,
.d_max = D_MAX_DEFAULT,
.d_max_gain = 37,
.d_max_advance = 20,
.motor_output_limit = 100,
.auto_profile_cell_count = AUTO_PROFILE_CELL_COUNT_STAY,
.transient_throttle_limit = 0,
@ -213,7 +213,7 @@ void resetPidProfile(pidProfile_t *pidProfile)
.simplified_i_gain = SIMPLIFIED_TUNING_DEFAULT,
.simplified_d_gain = SIMPLIFIED_TUNING_D_DEFAULT,
.simplified_pi_gain = SIMPLIFIED_TUNING_DEFAULT,
.simplified_dmin_ratio = SIMPLIFIED_TUNING_D_DEFAULT,
.simplified_d_max_gain = SIMPLIFIED_TUNING_D_DEFAULT,
.simplified_feedforward_gain = SIMPLIFIED_TUNING_DEFAULT,
.simplified_pitch_pi_gain = SIMPLIFIED_TUNING_DEFAULT,
.simplified_dterm_filter = true,
@ -247,11 +247,6 @@ void resetPidProfile(pidProfile_t *pidProfile)
.tpa_curve_pid_thr100 = 70,
.tpa_curve_expo = 20,
);
#ifndef USE_D_MIN
pidProfile->pid[PID_ROLL].D = 30;
pidProfile->pid[PID_PITCH].D = 32;
#endif
}
void pgResetFn_pidProfiles(pidProfile_t *pidProfiles)
@ -1187,7 +1182,7 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
pidSetpointDelta = getFeedforward(axis);
}
#endif
pidRuntime.previousPidSetpoint[axis] = currentPidSetpoint; // this is the value sent to blackbox, and used for Dmin setpoint
pidRuntime.previousPidSetpoint[axis] = currentPidSetpoint; // this is the value sent to blackbox, and used for D-max setpoint
// disable D if launch control is active
if ((pidRuntime.pidCoefficient[axis].Kd > 0) && !launchControlActive) {
@ -1205,27 +1200,27 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, timeUs_t currentTim
}
#endif
#if defined(USE_D_MIN)
float dMinFactor = 1.0f;
if (pidRuntime.dMinPercent[axis] > 0) {
float dMinGyroFactor = pt2FilterApply(&pidRuntime.dMinRange[axis], delta);
dMinGyroFactor = fabsf(dMinGyroFactor) * pidRuntime.dMinGyroGain;
const float dMinSetpointFactor = (fabsf(pidSetpointDelta)) * pidRuntime.dMinSetpointGain;
dMinFactor = MAX(dMinGyroFactor, dMinSetpointFactor);
dMinFactor = pidRuntime.dMinPercent[axis] + (1.0f - pidRuntime.dMinPercent[axis]) * dMinFactor;
dMinFactor = pt2FilterApply(&pidRuntime.dMinLowpass[axis], dMinFactor);
dMinFactor = MIN(dMinFactor, 1.0f);
#ifdef USE_D_MAX
float dMaxFactor = 1.0f;
if (pidRuntime.dMaxPercent[axis] > 0) {
float dMaxGyroFactor = pt2FilterApply(&pidRuntime.dMaxRange[axis], delta);
dMaxGyroFactor = fabsf(dMaxGyroFactor) * pidRuntime.dMaxGyroGain;
const float dMaxSetpointFactor = fabsf(pidSetpointDelta) * pidRuntime.dMaxSetpointGain;
dMaxFactor = MAX(dMaxGyroFactor, dMaxSetpointFactor);
dMaxFactor = 1.0f + (1.0f - pidRuntime.dMaxPercent[axis]) * dMaxFactor;
dMaxFactor = pt2FilterApply(&pidRuntime.dMaxLowpass[axis], dMaxFactor);
dMaxFactor = MIN(dMaxFactor, 1.0f / pidRuntime.dMaxPercent[axis]);
if (axis == FD_ROLL) {
DEBUG_SET(DEBUG_D_MIN, 0, lrintf(dMinGyroFactor * 100));
DEBUG_SET(DEBUG_D_MIN, 1, lrintf(dMinSetpointFactor * 100));
DEBUG_SET(DEBUG_D_MIN, 2, lrintf(pidRuntime.pidCoefficient[axis].Kd * dMinFactor * 10 / DTERM_SCALE));
DEBUG_SET(DEBUG_D_MAX, 0, lrintf(dMaxGyroFactor * 100));
DEBUG_SET(DEBUG_D_MAX, 1, lrintf(dMaxSetpointFactor * 100));
DEBUG_SET(DEBUG_D_MAX, 2, lrintf(pidRuntime.pidCoefficient[axis].Kd * dMaxFactor * 10 / DTERM_SCALE));
} else if (axis == FD_PITCH) {
DEBUG_SET(DEBUG_D_MIN, 3, lrintf(pidRuntime.pidCoefficient[axis].Kd * dMinFactor * 10 / DTERM_SCALE));
DEBUG_SET(DEBUG_D_MAX, 3, lrintf(pidRuntime.pidCoefficient[axis].Kd * dMaxFactor * 10 / DTERM_SCALE));
}
}
// Apply the dMinFactor
preTpaD *= dMinFactor;
// Apply the dMaxFactor
preTpaD *= dMaxFactor;
#endif
pidData[axis].D = preTpaD * pidRuntime.tpaFactor;

View file

@ -40,7 +40,6 @@
#define PID_GAIN_MAX 250
#define F_GAIN_MAX 1000
#define D_MIN_GAIN_MAX 250
// Scaling factors for Pids for better tunable range in configurator for betaflight pid controller. The scaling is based on legacy pid controller or previous float
#define PTERM_SCALE 0.032029f
@ -61,10 +60,10 @@
#define ITERM_ACCELERATOR_GAIN_OFF 0
#define ITERM_ACCELERATOR_GAIN_MAX 250
#define PID_ROLL_DEFAULT { 45, 80, 40, 120, 0 }
#define PID_PITCH_DEFAULT { 47, 84, 46, 125, 0 }
#define PID_ROLL_DEFAULT { 45, 80, 30, 120, 0 }
#define PID_PITCH_DEFAULT { 47, 84, 34, 125, 0 }
#define PID_YAW_DEFAULT { 45, 80, 0, 120, 0 }
#define D_MIN_DEFAULT { 30, 34, 0 }
#define D_MAX_DEFAULT { 40, 46, 0 }
#define DTERM_LPF1_DYN_MIN_HZ_DEFAULT 75
#define DTERM_LPF1_DYN_MAX_HZ_DEFAULT 150
@ -222,9 +221,9 @@ typedef struct pidProfile_s {
uint8_t use_integrated_yaw; // Selects whether the yaw pidsum should integrated
uint8_t integrated_yaw_relax; // Specifies how much integrated yaw should be reduced to offset the drag based yaw component
uint8_t thrustLinearization; // Compensation factor for pid linearization
uint8_t d_min[XYZ_AXIS_COUNT]; // Minimum D value on each axis
uint8_t d_min_gain; // Gain factor for amount of gyro / setpoint activity required to boost D
uint8_t d_min_advance; // Percentage multiplier for setpoint input to boost algorithm
uint8_t d_max[XYZ_AXIS_COUNT]; // Maximum D value on each axis
uint8_t d_max_gain; // Gain factor for amount of gyro / setpoint activity required to boost D
uint8_t d_max_advance; // Percentage multiplier for setpoint input to boost algorithm
uint8_t motor_output_limit; // Upper limit of the motor output (percent)
int8_t auto_profile_cell_count; // Cell count for this profile to be used with if auto PID profile switching is used
uint8_t transient_throttle_limit; // Maximum DC component of throttle change to mix into throttle to prevent airmode mirroring noise
@ -256,7 +255,7 @@ typedef struct pidProfile_s {
uint8_t simplified_i_gain;
uint8_t simplified_d_gain;
uint8_t simplified_pi_gain;
uint8_t simplified_dmin_ratio;
uint8_t simplified_d_max_gain;
uint8_t simplified_feedforward_gain;
uint8_t simplified_dterm_filter;
uint8_t simplified_dterm_filter_multiplier;
@ -401,12 +400,13 @@ typedef struct pidRuntime_s {
float oldSetpointCorrection[XYZ_AXIS_COUNT];
#endif
#ifdef USE_D_MIN
pt2Filter_t dMinRange[XYZ_AXIS_COUNT];
pt2Filter_t dMinLowpass[XYZ_AXIS_COUNT];
float dMinPercent[XYZ_AXIS_COUNT];
float dMinGyroGain;
float dMinSetpointGain;
#ifdef USE_D_MAX
pt2Filter_t dMaxRange[XYZ_AXIS_COUNT];
pt2Filter_t dMaxLowpass[XYZ_AXIS_COUNT];
float dMaxPercent[XYZ_AXIS_COUNT];
uint8_t dMax[XYZ_AXIS_COUNT];
float dMaxGyroGain;
float dMaxSetpointGain;
#endif
#ifdef USE_AIRMODE_LPF

View file

@ -47,11 +47,11 @@
#include "pid_init.h"
#if defined(USE_D_MIN)
#define D_MIN_RANGE_HZ 85 // PT2 lowpass input cutoff to peak D around propwash frequencies
#define D_MIN_LOWPASS_HZ 35 // PT2 lowpass cutoff to smooth the boost effect
#define D_MIN_GAIN_FACTOR 0.00008f
#define D_MIN_SETPOINT_GAIN_FACTOR 0.00008f
#ifdef USE_D_MAX
#define D_MAX_RANGE_HZ 85 // PT2 lowpass input cutoff to peak D around propwash frequencies
#define D_MAX_LOWPASS_HZ 35 // PT2 lowpass cutoff to smooth the boost effect
#define D_MAX_GAIN_FACTOR 0.00008f
#define D_MAX_SETPOINT_GAIN_FACTOR 0.00008f
#endif
#define ATTITUDE_CUTOFF_HZ 50
@ -219,14 +219,14 @@ void pidInitFilters(const pidProfile_t *pidProfile)
}
#endif
#if defined(USE_D_MIN)
// Initialize the filters for all axis even if the d_min[axis] value is 0
// Otherwise if the pidProfile->d_min_xxx parameters are ever added to
#ifdef USE_D_MAX
// Initialize the filters for all axis even if the d_max[axis] value is 0
// Otherwise if the pidProfile->d_max_xxx parameters are ever added to
// in-flight adjustments and transition from 0 to > 0 in flight the feature
// won't work because the filter wasn't initialized.
for (int axis = FD_ROLL; axis <= FD_YAW; axis++) {
pt2FilterInit(&pidRuntime.dMinRange[axis], pt2FilterGain(D_MIN_RANGE_HZ, pidRuntime.dT));
pt2FilterInit(&pidRuntime.dMinLowpass[axis], pt2FilterGain(D_MIN_LOWPASS_HZ, pidRuntime.dT));
pt2FilterInit(&pidRuntime.dMaxRange[axis], pt2FilterGain(D_MAX_RANGE_HZ, pidRuntime.dT));
pt2FilterInit(&pidRuntime.dMaxLowpass[axis], pt2FilterGain(D_MAX_LOWPASS_HZ, pidRuntime.dT));
}
#endif
@ -445,17 +445,17 @@ void pidInitConfig(const pidProfile_t *pidProfile)
pidRuntime.throttleCompensateAmount = pidRuntime.thrustLinearization - 0.5f * sq(pidRuntime.thrustLinearization);
#endif
#if defined(USE_D_MIN)
#ifdef USE_D_MAX
for (int axis = FD_ROLL; axis <= FD_YAW; ++axis) {
const uint8_t dMin = pidProfile->d_min[axis];
if ((dMin > 0) && (dMin < pidProfile->pid[axis].D)) {
pidRuntime.dMinPercent[axis] = dMin / (float)(pidProfile->pid[axis].D);
const uint8_t dMax = pidProfile->d_max[axis];
if ((dMax > 0) && (dMax > pidProfile->pid[axis].D)) {
pidRuntime.dMaxPercent[axis] = (float) pidProfile->pid[axis].D / dMax;
} else {
pidRuntime.dMinPercent[axis] = 0;
pidRuntime.dMaxPercent[axis] = 0;
}
}
pidRuntime.dMinGyroGain = D_MIN_GAIN_FACTOR * pidProfile->d_min_gain / D_MIN_LOWPASS_HZ;
pidRuntime.dMinSetpointGain = D_MIN_SETPOINT_GAIN_FACTOR * pidProfile->d_min_gain * pidProfile->d_min_advance / 100.0f / D_MIN_LOWPASS_HZ;
pidRuntime.dMaxGyroGain = D_MAX_GAIN_FACTOR * pidProfile->d_max_gain / D_MAX_LOWPASS_HZ;
pidRuntime.dMaxSetpointGain = D_MAX_SETPOINT_GAIN_FACTOR * pidProfile->d_max_gain * pidProfile->d_max_advance / 100.0f / D_MAX_LOWPASS_HZ;
// lowpass included inversely in gain since stronger lowpass decreases peak effect
#endif

View file

@ -1988,12 +1988,12 @@ case MSP_NAME:
sbufWriteU16(dst, currentPidProfile->pid[PID_PITCH].F);
sbufWriteU16(dst, currentPidProfile->pid[PID_YAW].F);
sbufWriteU8(dst, 0); // was currentPidProfile->antiGravityMode
#if defined(USE_D_MIN)
sbufWriteU8(dst, currentPidProfile->d_min[PID_ROLL]);
sbufWriteU8(dst, currentPidProfile->d_min[PID_PITCH]);
sbufWriteU8(dst, currentPidProfile->d_min[PID_YAW]);
sbufWriteU8(dst, currentPidProfile->d_min_gain);
sbufWriteU8(dst, currentPidProfile->d_min_advance);
#ifdef USE_D_MAX
sbufWriteU8(dst, currentPidProfile->d_max[PID_ROLL]);
sbufWriteU8(dst, currentPidProfile->d_max[PID_PITCH]);
sbufWriteU8(dst, currentPidProfile->d_max[PID_YAW]);
sbufWriteU8(dst, currentPidProfile->d_max_gain);
sbufWriteU8(dst, currentPidProfile->d_max_advance);
#else
sbufWriteU8(dst, 0);
sbufWriteU8(dst, 0);
@ -2197,8 +2197,8 @@ static void readSimplifiedPids(pidProfile_t* pidProfile, sbuf_t *src)
pidProfile->simplified_i_gain = sbufReadU8(src);
pidProfile->simplified_d_gain = sbufReadU8(src);
pidProfile->simplified_pi_gain = sbufReadU8(src);
#ifdef USE_D_MIN
pidProfile->simplified_dmin_ratio = sbufReadU8(src);
#ifdef USE_D_MAX
pidProfile->simplified_d_max_gain = sbufReadU8(src);
#else
sbufReadU8(src);
#endif
@ -2217,8 +2217,8 @@ static void writeSimplifiedPids(const pidProfile_t *pidProfile, sbuf_t *dst)
sbufWriteU8(dst, pidProfile->simplified_i_gain);
sbufWriteU8(dst, pidProfile->simplified_d_gain);
sbufWriteU8(dst, pidProfile->simplified_pi_gain);
#ifdef USE_D_MIN
sbufWriteU8(dst, pidProfile->simplified_dmin_ratio);
#ifdef USE_D_MAX
sbufWriteU8(dst, pidProfile->simplified_d_max_gain);
#else
sbufWriteU8(dst, 0);
#endif
@ -2307,7 +2307,7 @@ static void writePidfs(pidProfile_t* pidProfile, sbuf_t *dst)
sbufWriteU8(dst, pidProfile->pid[i].P);
sbufWriteU8(dst, pidProfile->pid[i].I);
sbufWriteU8(dst, pidProfile->pid[i].D);
sbufWriteU8(dst, pidProfile->d_min[i]);
sbufWriteU8(dst, pidProfile->d_max[i]);
sbufWriteU16(dst, pidProfile->pid[i].F);
}
}
@ -2495,7 +2495,7 @@ static mspResult_e mspFcProcessOutCommandWithArg(mspDescriptor_t srcDesc, int16_
tempPidProfile.pid[i].P == currentPidProfile->pid[i].P &&
tempPidProfile.pid[i].I == currentPidProfile->pid[i].I &&
tempPidProfile.pid[i].D == currentPidProfile->pid[i].D &&
tempPidProfile.d_min[i] == currentPidProfile->d_min[i] &&
tempPidProfile.d_max[i] == currentPidProfile->d_max[i] &&
tempPidProfile.pid[i].F == currentPidProfile->pid[i].F;
}
@ -3197,12 +3197,12 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
}
if (sbufBytesRemaining(src) >= 7) {
// Added in MSP API 1.41
#if defined(USE_D_MIN)
currentPidProfile->d_min[PID_ROLL] = sbufReadU8(src);
currentPidProfile->d_min[PID_PITCH] = sbufReadU8(src);
currentPidProfile->d_min[PID_YAW] = sbufReadU8(src);
currentPidProfile->d_min_gain = sbufReadU8(src);
currentPidProfile->d_min_advance = sbufReadU8(src);
#ifdef USE_D_MAX
currentPidProfile->d_max[PID_ROLL] = sbufReadU8(src);
currentPidProfile->d_max[PID_PITCH] = sbufReadU8(src);
currentPidProfile->d_max[PID_YAW] = sbufReadU8(src);
currentPidProfile->d_max_gain = sbufReadU8(src);
currentPidProfile->d_max_advance = sbufReadU8(src);
#else
sbufReadU8(src);
sbufReadU8(src);

View file

@ -458,7 +458,7 @@ static void osdFormatPID(char * buff, const char * label, uint8_t axis)
currentPidProfile->pid[axis].P,
currentPidProfile->pid[axis].I,
currentPidProfile->pid[axis].D,
currentPidProfile->d_min[axis],
currentPidProfile->d_max[axis],
currentPidProfile->pid[axis].F);
}

View file

@ -321,7 +321,7 @@
#define USE_GYRO_LPF2
#define USE_DYN_LPF
#define USE_D_MIN
#define USE_D_MAX
#define USE_THROTTLE_BOOST
#define USE_INTEGRATED_YAW_CONTROL

View file

@ -550,10 +550,6 @@ TEST_F(RcControlsAdjustmentsTest, processPIDIncreasePidController0)
pidProfile.pid[PID_YAW].I = 17;
pidProfile.pid[PID_YAW].D = 27;
pidProfile.d_min[FD_PITCH] = 19;
pidProfile.d_min[FD_ROLL] = 19;
pidProfile.d_min[FD_YAW] = 19;
// and
controlRateConfig_t controlRateConfig;
memset(&controlRateConfig, 0, sizeof(controlRateConfig));
@ -596,16 +592,13 @@ TEST_F(RcControlsAdjustmentsTest, processPIDIncreasePidController0)
// and
EXPECT_EQ(1, pidProfile.pid[PID_PITCH].P);
EXPECT_EQ(11, pidProfile.pid[PID_PITCH].I);
EXPECT_EQ(20, pidProfile.pid[PID_PITCH].D);
EXPECT_EQ(20, pidProfile.d_min[FD_PITCH]);
EXPECT_EQ(21, pidProfile.pid[PID_PITCH].D);
EXPECT_EQ(6, pidProfile.pid[PID_ROLL].P);
EXPECT_EQ(16, pidProfile.pid[PID_ROLL].I);
EXPECT_EQ(25, pidProfile.pid[PID_ROLL].D);
EXPECT_EQ(20, pidProfile.d_min[FD_ROLL]);
EXPECT_EQ(26, pidProfile.pid[PID_ROLL].D);
EXPECT_EQ(8, pidProfile.pid[PID_YAW].P);
EXPECT_EQ(18, pidProfile.pid[PID_YAW].I);
EXPECT_EQ(27, pidProfile.pid[PID_YAW].D);
EXPECT_EQ(20, pidProfile.d_min[FD_YAW]);
EXPECT_EQ(28, pidProfile.pid[PID_YAW].D);
}
extern "C" {