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

Make filter type selectable and add BIQUAD

Adds options to select the filter type for both input and derivative.
rc_smoothing_input_type = PT1 | BIQUAD (default is BIQUAD)
rc_smoothing_derivative_type = OFF | PT1 | BIQUAD (default is OFF)
This commit is contained in:
Bruce Luckcuck 2018-06-01 21:23:30 -04:00
parent 8b42c80790
commit 7e18d7c1b9
8 changed files with 72 additions and 12 deletions

View file

@ -250,7 +250,8 @@ FAST_CODE uint8_t processRcSmoothingFilter(void)
uint8_t updatedChannel = 0; uint8_t updatedChannel = 0;
static float lastRxData[4]; static float lastRxData[4];
static pt1Filter_t rcCommandFilter[4]; static pt1Filter_t rcCommandFilterPt1[4];
static biquadFilter_t rcCommandFilterBiquad[4];
static bool initialized = false; static bool initialized = false;
static bool filterInitialized = false; static bool filterInitialized = false;
static float rxFrameTimeSum; static float rxFrameTimeSum;
@ -285,9 +286,17 @@ FAST_CODE uint8_t processRcSmoothingFilter(void)
const float dT = targetPidLooptime * 1e-6f; const float dT = targetPidLooptime * 1e-6f;
for (int i = 0; i < interpolationChannels; i++) { for (int i = 0; i < interpolationChannels; i++) {
pt1FilterInit(&rcCommandFilter[i], pt1FilterGain(filterCutoffFrequency, dT)); switch (rxConfig()->rc_smoothing_input_type) {
case RC_SMOOTHING_INPUT_BIQUAD:
biquadFilterInitLPF(&rcCommandFilterBiquad[i], filterCutoffFrequency, targetPidLooptime);
break;
case RC_SMOOTHING_INPUT_PT1:
default:
pt1FilterInit(&rcCommandFilterPt1[i], pt1FilterGain(filterCutoffFrequency, dT));
break;
}
} }
pidInitSetpointDerivativeLpf(derivativeCutoffFrequency, rxConfig()->rc_smoothing_debug_axis); pidInitSetpointDerivativeLpf(derivativeCutoffFrequency, rxConfig()->rc_smoothing_debug_axis, rxConfig()->rc_smoothing_derivative_type);
filterInitialized = true; filterInitialized = true;
} }
} else { } else {
@ -302,7 +311,15 @@ FAST_CODE uint8_t processRcSmoothingFilter(void)
for (updatedChannel = ROLL; updatedChannel < interpolationChannels; updatedChannel++) { for (updatedChannel = ROLL; updatedChannel < interpolationChannels; updatedChannel++) {
if (filterInitialized) { if (filterInitialized) {
rcCommand[updatedChannel] = pt1FilterApply(&rcCommandFilter[updatedChannel], lastRxData[updatedChannel]); switch (rxConfig()->rc_smoothing_input_type) {
case RC_SMOOTHING_INPUT_BIQUAD:
rcCommand[updatedChannel] = biquadFilterApply(&rcCommandFilterBiquad[updatedChannel], lastRxData[updatedChannel]);
break;
case RC_SMOOTHING_INPUT_PT1:
default:
rcCommand[updatedChannel] = pt1FilterApply(&rcCommandFilterPt1[updatedChannel], lastRxData[updatedChannel]);
break;
}
} else { } else {
// If filter isn't initialized yet then use the actual unsmoothed rx channel data // If filter isn't initialized yet then use the actual unsmoothed rx channel data
rcCommand[updatedChannel] = lastRxData[updatedChannel]; rcCommand[updatedChannel] = lastRxData[updatedChannel];

View file

@ -61,7 +61,18 @@ typedef enum {
typedef enum { typedef enum {
RC_SMOOTHING_TYPE_INTERPOLATION, RC_SMOOTHING_TYPE_INTERPOLATION,
RC_SMOOTHING_TYPE_FILTER RC_SMOOTHING_TYPE_FILTER
} rcInterpolationType_e; } rcSmoothingType_e;
typedef enum {
RC_SMOOTHING_INPUT_PT1,
RC_SMOOTHING_INPUT_BIQUAD
} rcSmoothingInputFilter_e;
typedef enum {
RC_SMOOTHING_DERIVATIVE_OFF,
RC_SMOOTHING_DERIVATIVE_PT1,
RC_SMOOTHING_DERIVATIVE_BIQUAD
} rcSmoothingDerivativeFilter_e;
#define ROL_LO (1 << (2 * ROLL)) #define ROL_LO (1 << (2 * ROLL))

View file

@ -211,9 +211,11 @@ static FAST_RAM_ZERO_INIT uint8_t itermRelaxCutoffHigh;
#endif #endif
#ifdef USE_RC_SMOOTHING_FILTER #ifdef USE_RC_SMOOTHING_FILTER
static FAST_RAM_ZERO_INIT pt1Filter_t setpointDerivativeLpf[2]; static FAST_RAM_ZERO_INIT pt1Filter_t setpointDerivativePt1[2];
static FAST_RAM_ZERO_INIT biquadFilter_t setpointDerivativeBiquad[2];
static FAST_RAM_ZERO_INIT bool setpointDerivativeLpfInitialized; static FAST_RAM_ZERO_INIT bool setpointDerivativeLpfInitialized;
static FAST_RAM_ZERO_INIT uint8_t rcSmoothingDebugAxis; static FAST_RAM_ZERO_INIT uint8_t rcSmoothingDebugAxis;
static FAST_RAM_ZERO_INIT uint8_t rcSmoothingFilterType;
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
void pidInitFilters(const pidProfile_t *pidProfile) void pidInitFilters(const pidProfile_t *pidProfile)
@ -302,11 +304,19 @@ void pidInitFilters(const pidProfile_t *pidProfile)
} }
#ifdef USE_RC_SMOOTHING_FILTER #ifdef USE_RC_SMOOTHING_FILTER
void pidInitSetpointDerivativeLpf(uint16_t filterCutoff, uint8_t debugAxis) { void pidInitSetpointDerivativeLpf(uint16_t filterCutoff, uint8_t debugAxis, uint8_t filterType) {
setpointDerivativeLpfInitialized = true; setpointDerivativeLpfInitialized = true;
rcSmoothingDebugAxis = debugAxis; rcSmoothingDebugAxis = debugAxis;
rcSmoothingFilterType = filterType;
for (int axis = FD_ROLL; axis <= FD_PITCH; axis++) { for (int axis = FD_ROLL; axis <= FD_PITCH; axis++) {
pt1FilterInit(&setpointDerivativeLpf[axis], pt1FilterGain(filterCutoff, dT)); switch (rcSmoothingFilterType) {
case RC_SMOOTHING_DERIVATIVE_PT1:
pt1FilterInit(&setpointDerivativePt1[axis], pt1FilterGain(filterCutoff, dT));
break;
case RC_SMOOTHING_DERIVATIVE_BIQUAD:
biquadFilterInitLPF(&setpointDerivativeBiquad[axis], filterCutoff, targetPidLooptime);
break;
}
} }
} }
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
@ -884,9 +894,15 @@ void FAST_CODE pidController(const pidProfile_t *pidProfile, const rollAndPitchT
if (axis == rcSmoothingDebugAxis) { if (axis == rcSmoothingDebugAxis) {
DEBUG_SET(DEBUG_RC_SMOOTHING, 1, lrintf(pidSetpointDelta * 100.0f)); DEBUG_SET(DEBUG_RC_SMOOTHING, 1, lrintf(pidSetpointDelta * 100.0f));
} }
if ((dynCd != 0) && setpointDerivativeLpfInitialized) { if ((dynCd != 0) && setpointDerivativeLpfInitialized && (rcSmoothingFilterType != RC_SMOOTHING_DERIVATIVE_OFF)) {
pidSetpointDelta = pt1FilterApply(&setpointDerivativeLpf[axis], pidSetpointDelta); switch (rcSmoothingFilterType) {
case RC_SMOOTHING_DERIVATIVE_PT1:
pidSetpointDelta = pt1FilterApply(&setpointDerivativePt1[axis], pidSetpointDelta);
break;
case RC_SMOOTHING_DERIVATIVE_BIQUAD:
pidSetpointDelta = biquadFilterApply(&setpointDerivativeBiquad[axis], pidSetpointDelta);
break;
}
if (axis == rcSmoothingDebugAxis) { if (axis == rcSmoothingDebugAxis) {
DEBUG_SET(DEBUG_RC_SMOOTHING, 2, lrintf(pidSetpointDelta * 100.0f)); DEBUG_SET(DEBUG_RC_SMOOTHING, 2, lrintf(pidSetpointDelta * 100.0f));
} }

View file

@ -178,4 +178,4 @@ void pidCopyProfile(uint8_t dstPidProfileIndex, uint8_t srcPidProfileIndex);
bool crashRecoveryModeActive(void); bool crashRecoveryModeActive(void);
void pidAcroTrainerInit(void); void pidAcroTrainerInit(void);
void pidSetAcroTrainerState(bool newState); void pidSetAcroTrainerState(bool newState);
void pidInitSetpointDerivativeLpf(uint16_t filterCutoff, uint8_t debugAxis); void pidInitSetpointDerivativeLpf(uint16_t filterCutoff, uint8_t debugAxis, uint8_t filterType);

View file

@ -356,6 +356,12 @@ static const char * const lookupTableRcSmoothingType[] = {
static const char * const lookupTableRcSmoothingDebug[] = { static const char * const lookupTableRcSmoothingDebug[] = {
"ROLL", "PITCH", "YAW", "THROTTLE" "ROLL", "PITCH", "YAW", "THROTTLE"
}; };
static const char * const lookupTableRcSmoothingInputType[] = {
"PT1", "BIQUAD"
};
static const char * const lookupTableRcSmoothingDerivativeType[] = {
"OFF", "PT1", "BIQUAD"
};
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
#define LOOKUP_TABLE_ENTRY(name) { name, ARRAYLEN(name) } #define LOOKUP_TABLE_ENTRY(name) { name, ARRAYLEN(name) }
@ -442,6 +448,8 @@ const lookupTableEntry_t lookupTables[] = {
#ifdef USE_RC_SMOOTHING_FILTER #ifdef USE_RC_SMOOTHING_FILTER
LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingType), LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingType),
LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingDebug), LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingDebug),
LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingInputType),
LOOKUP_TABLE_ENTRY(lookupTableRcSmoothingDerivativeType),
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
}; };
@ -544,6 +552,8 @@ const clivalue_t valueTable[] = {
{ "rc_smoothing_input_hz", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_input_cutoff) }, { "rc_smoothing_input_hz", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_input_cutoff) },
{ "rc_smoothing_derivative_hz", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_derivative_cutoff) }, { "rc_smoothing_derivative_hz", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_derivative_cutoff) },
{ "rc_smoothing_debug_axis", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RC_SMOOTHING_DEBUG }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_debug_axis) }, { "rc_smoothing_debug_axis", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RC_SMOOTHING_DEBUG }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_debug_axis) },
{ "rc_smoothing_input_type", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RC_SMOOTHING_INPUT_TYPE }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_input_type) },
{ "rc_smoothing_derivative_type",VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RC_SMOOTHING_DERIVATIVE_TYPE }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_derivative_type) },
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
{ "fpv_mix_degrees", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 50 }, PG_RX_CONFIG, offsetof(rxConfig_t, fpvCamAngleDegrees) }, { "fpv_mix_degrees", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 50 }, PG_RX_CONFIG, offsetof(rxConfig_t, fpvCamAngleDegrees) },

View file

@ -107,6 +107,8 @@ typedef enum {
#ifdef USE_RC_SMOOTHING_FILTER #ifdef USE_RC_SMOOTHING_FILTER
TABLE_RC_SMOOTHING_TYPE, TABLE_RC_SMOOTHING_TYPE,
TABLE_RC_SMOOTHING_DEBUG, TABLE_RC_SMOOTHING_DEBUG,
TABLE_RC_SMOOTHING_INPUT_TYPE,
TABLE_RC_SMOOTHING_DERIVATIVE_TYPE,
#endif // USE_RC_SMOOTHING_FILTER #endif // USE_RC_SMOOTHING_FILTER
LOOKUP_TABLE_COUNT LOOKUP_TABLE_COUNT
} lookupTableIndex_e; } lookupTableIndex_e;

View file

@ -64,6 +64,8 @@ void pgResetFn_rxConfig(rxConfig_t *rxConfig)
.rc_smoothing_input_cutoff = 0, // automatically calculate the cutoff by default .rc_smoothing_input_cutoff = 0, // automatically calculate the cutoff by default
.rc_smoothing_derivative_cutoff = 0, // automatically calculate the cutoff by default .rc_smoothing_derivative_cutoff = 0, // automatically calculate the cutoff by default
.rc_smoothing_debug_axis = ROLL, // default to debug logging for the roll axis .rc_smoothing_debug_axis = ROLL, // default to debug logging for the roll axis
.rc_smoothing_input_type = RC_SMOOTHING_INPUT_BIQUAD,
.rc_smoothing_derivative_type = RC_SMOOTHING_DERIVATIVE_OFF,
); );
#ifdef RX_CHANNELS_TAER #ifdef RX_CHANNELS_TAER

View file

@ -55,6 +55,8 @@ typedef struct rxConfig_s {
uint8_t rc_smoothing_input_cutoff; // Filter cutoff frequency for the input filter (0 = auto) uint8_t rc_smoothing_input_cutoff; // Filter cutoff frequency for the input filter (0 = auto)
uint8_t rc_smoothing_derivative_cutoff; // Filter cutoff frequency for the setpoint weight derivative filter (0 = auto) uint8_t rc_smoothing_derivative_cutoff; // Filter cutoff frequency for the setpoint weight derivative filter (0 = auto)
uint8_t rc_smoothing_debug_axis; // Axis to log as debug values when debug_mode = RC_SMOOTHING uint8_t rc_smoothing_debug_axis; // Axis to log as debug values when debug_mode = RC_SMOOTHING
uint8_t rc_smoothing_input_type; // Input filter type (0 = PT1, 1 = BIQUAD)
uint8_t rc_smoothing_derivative_type; // Derivative filter type (0 = OFF, 1 = PT1, 2 = BIQUAD)
} rxConfig_t; } rxConfig_t;
PG_DECLARE(rxConfig_t, rxConfig); PG_DECLARE(rxConfig_t, rxConfig);