NotchFilter push initialization/reset into filter

- this simplifies the reset by allowing a notch filter to reset as
needed
 - improves cascade initialization, on reset each filter will reset
properly from the previous
This commit is contained in:
Daniel Agar
2021-12-21 12:19:11 -05:00
parent 2e2ac36cab
commit 7d632254be
2 changed files with 46 additions and 20 deletions
+43 -14
View File
@@ -66,26 +66,24 @@ public:
*/ */
inline T apply(const T &sample) inline T apply(const T &sample)
{ {
// Direct Form I implementation if (!_initialized) {
T output = _b0 * sample + _b1 * _delay_element_1 + _b2 * _delay_element_2 - _a1 * _delay_element_output_1 - _a2 * reset(sample);
_delay_element_output_2; _initialized = true;
}
// shift inputs return applyInternal(sample);
_delay_element_2 = _delay_element_1;
_delay_element_1 = sample;
// shift outputs
_delay_element_output_2 = _delay_element_output_1;
_delay_element_output_1 = output;
return output;
} }
// Filter array of samples in place using the direct form I // Filter array of samples in place using the direct form I
inline void applyArray(T samples[], int num_samples) inline void applyArray(T samples[], int num_samples)
{ {
if (!_initialized) {
reset(samples[0]);
_initialized = true;
}
for (int n = 0; n < num_samples; n++) { for (int n = 0; n < num_samples; n++) {
samples[n] = apply(samples[n]); samples[n] = applyInternal(samples[n]);
} }
} }
@@ -130,6 +128,8 @@ public:
_b2 = b[2]; _b2 = b[2];
} }
void reset() { _initialized = false; }
void reset(const T &sample) void reset(const T &sample)
{ {
const T input = isFinite(sample) ? sample : T{}; const T input = isFinite(sample) ? sample : T{};
@@ -140,6 +140,8 @@ public:
if (!isFinite(_delay_element_1) || !isFinite(_delay_element_2)) { if (!isFinite(_delay_element_1) || !isFinite(_delay_element_2)) {
_delay_element_output_1 = _delay_element_output_2 = {}; _delay_element_output_1 = _delay_element_output_2 = {};
} }
_initialized = true;
} }
void disable() void disable()
@@ -160,9 +162,34 @@ public:
_a1 = 0.f; _a1 = 0.f;
_a2 = 0.f; _a2 = 0.f;
_initialized = false;
} }
protected: protected:
/**
* Add a new raw value to the filter using the Direct Form I
*
* @return retrieve the filtered result
*/
inline T applyInternal(const T &sample)
{
// Direct Form I implementation
T output = _b0 * sample + _b1 * _delay_element_1 + _b2 * _delay_element_2 - _a1 * _delay_element_output_1 - _a2 *
_delay_element_output_2;
// shift inputs
_delay_element_2 = _delay_element_1;
_delay_element_1 = sample;
// shift outputs
_delay_element_output_2 = _delay_element_output_1;
_delay_element_output_1 = output;
return output;
}
T _delay_element_1{}; T _delay_element_1{};
T _delay_element_2{}; T _delay_element_2{};
T _delay_element_output_1{}; T _delay_element_output_1{};
@@ -179,6 +206,8 @@ protected:
float _notch_freq{}; float _notch_freq{};
float _bandwidth{}; float _bandwidth{};
float _sample_freq{}; float _sample_freq{};
bool _initialized{false};
}; };
/** /**
@@ -242,7 +271,7 @@ void NotchFilter<T>::setParameters(float sample_freq, float notch_freq, float ba
_a1 = _b1; _a1 = _b1;
_a2 = (1.f - alpha) * a0_inv; _a2 = (1.f - alpha) * a0_inv;
if (!isFinite(_b0) || !isFinite(_b1) || !isFinite(_b2) || !isFinite(_a1) || !isFinite(_a2)) { if (!isFinite(_b0) || !isFinite(_b1) || !isFinite(_b2) || !isFinite(_a2)) {
disable(); disable();
} }
} }
@@ -171,7 +171,7 @@ void VehicleAngularVelocity::ResetFilters()
// angular velocity notch // angular velocity notch
_notch_filter_velocity[axis].setParameters(_filter_sample_rate_hz, _param_imu_gyro_nf_freq.get(), _notch_filter_velocity[axis].setParameters(_filter_sample_rate_hz, _param_imu_gyro_nf_freq.get(),
_param_imu_gyro_nf_bw.get()); _param_imu_gyro_nf_bw.get());
_notch_filter_velocity[axis].reset(angular_velocity_uncalibrated(axis)); _notch_filter_velocity[axis].reset();
// angular acceleration low pass // angular acceleration low pass
if ((_param_imu_dgyro_cutoff.get() > 0.f) if ((_param_imu_dgyro_cutoff.get() > 0.f)
@@ -548,11 +548,9 @@ void VehicleAngularVelocity::UpdateDynamicNotchEscRpm(bool force)
} }
if (reset) { if (reset) {
const Vector3f reset_angular_velocity{GetResetAngularVelocity()};
for (int axis = 0; axis < 3; axis++) { for (int axis = 0; axis < 3; axis++) {
for (int harmonic = 0; harmonic < MAX_NUM_ESC_RPM_HARMONICS; harmonic++) { for (int harmonic = 0; harmonic < MAX_NUM_ESC_RPM_HARMONICS; harmonic++) {
_dynamic_notch_filter_esc_rpm[axis][esc][harmonic].reset(reset_angular_velocity(axis)); _dynamic_notch_filter_esc_rpm[axis][esc][harmonic].reset();
} }
} }
@@ -633,8 +631,7 @@ void VehicleAngularVelocity::UpdateDynamicNotchFFT(bool force)
// force reset if the notch frequency jumps significantly // force reset if the notch frequency jumps significantly
if (force || reset || (notch_freq_diff > bandwidth)) { if (force || reset || (notch_freq_diff > bandwidth)) {
const Vector3f reset_angular_velocity{GetResetAngularVelocity()}; nf.reset();
nf.reset(reset_angular_velocity(axis));
perf_count(_dynamic_notch_filter_fft_reset_perf); perf_count(_dynamic_notch_filter_fft_reset_perf);
} }