/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "HarmonicNotchFilter.h" #include #define HNF_MAX_FILTERS 3 #define HNF_MAX_HARMONICS 8 // table of user settable parameters const AP_Param::GroupInfo HarmonicNotchFilterParams::var_info[] = { // @Param: ENABLE // @DisplayName: Harmonic Notch Filter enable // @Description: Harmonic Notch Filter enable // @Values: 0:Disabled,1:Enabled // @User: Advanced AP_GROUPINFO_FLAGS("ENABLE", 1, HarmonicNotchFilterParams, _enable, 0, AP_PARAM_FLAG_ENABLE), // @Param: FREQ // @DisplayName: Harmonic Notch Filter base frequency // @Description: Harmonic Notch Filter base center frequency in Hz // @Range: 10 400 // @Units: Hz // @User: Advanced AP_GROUPINFO("FREQ", 2, HarmonicNotchFilterParams, _center_freq_hz, 80), // @Param: BW // @DisplayName: Harmonic Notch Filter bandwidth // @Description: Harmonic Notch Filter bandwidth in Hz // @Range: 5 100 // @Units: Hz // @User: Advanced AP_GROUPINFO("BW", 3, HarmonicNotchFilterParams, _bandwidth_hz, 20), // @Param: ATT // @DisplayName: Harmonic Notch Filter attenuation // @Description: Harmonic Notch Filter attenuation in dB // @Range: 5 30 // @Units: dB // @User: Advanced AP_GROUPINFO("ATT", 4, HarmonicNotchFilterParams, _attenuation_dB, 15), // @Param: HMNCS // @DisplayName: Harmonic Notch Filter harmonics // @Description: Bitmask of harmonic frequencies to apply Harmonic Notch Filter to. This option takes effect on the next reboot. A maximum of 3 harmonics can be used at any one time // @Bitmask: 0:1st harmonic,1:2nd harmonic,2:3rd harmonic,3:4th hamronic,4:5th harmonic,5:6th harmonic,6:7th harmonic,7:8th harmonic // @User: Advanced // @RebootRequired: True AP_GROUPINFO("HMNCS", 5, HarmonicNotchFilterParams, _harmonics, 3), // @Param: REF // @DisplayName: Harmonic Notch Filter reference value // @Description: Reference value associated with the specified frequency to facilitate frequency scaling of the Harmonic Notch Filter // @User: Advanced // @Range: 0.1 0.9 // @RebootRequired: True AP_GROUPINFO("REF", 6, HarmonicNotchFilterParams, _reference, 0.1f), AP_GROUPEND }; /* destroy all of the associated notch filters */ template HarmonicNotchFilter::~HarmonicNotchFilter() { delete[] _filters; _num_filters = 0; _num_enabled_filters = 0; } /* initialise the associated filters with the provided shaping constraints the constraints are used to determine attenuation (A) and quality (Q) factors for the filter */ template void HarmonicNotchFilter::init(float sample_freq_hz, float center_freq_hz, float bandwidth_hz, float attenuation_dB) { // sanity check the input if (_filters == nullptr || is_zero(sample_freq_hz) || isnan(sample_freq_hz)) { return; } _sample_freq_hz = sample_freq_hz; const float nyquist_limit = sample_freq_hz * 0.48f; // adjust the fundamental center frequency to be in the allowable range center_freq_hz = constrain_float(center_freq_hz, bandwidth_hz * 0.52f, nyquist_limit); // calculate attenuation and quality from the shaping constraints NotchFilter::calculate_A_and_Q(center_freq_hz, bandwidth_hz, attenuation_dB, _A, _Q); _num_enabled_filters = 0; // initialize all the configured filters with the same A & Q and multiples of the center frequency for (uint8_t i = 0, filt = 0; i < HNF_MAX_HARMONICS && filt < _num_filters; i++) { const float notch_center = center_freq_hz * (i+1); if ((1U< void HarmonicNotchFilter::allocate_filters(uint8_t harmonics) { for (uint8_t i = 0; i < HNF_MAX_HARMONICS && _num_filters < HNF_MAX_FILTERS; i++) { if ((1U< 0) { _filters = new NotchFilter[_num_filters]; if (_filters == nullptr) { gcs().send_text(MAV_SEVERITY_WARNING, "Failed to allocate %u bytes for HarmonicNotchFilter", (unsigned int)(_num_filters * sizeof(NotchFilter))); _num_filters = 0; } } _harmonics = harmonics; } /* update the underlying filters' center frequency using the current attenuation and quality this function is cheaper than init() because A & Q do not need to be recalculated */ template void HarmonicNotchFilter::update(float center_freq_hz) { if (!_initialised) { return; } // adjust the fundamental center frequency to be in the allowable range const float nyquist_limit = _sample_freq_hz * 0.48f; center_freq_hz = constrain_float(center_freq_hz, 1.0f, nyquist_limit); _num_enabled_filters = 0; // update all of the filters using the new center frequency and existing A & Q for (uint8_t i = 0, filt = 0; i < HNF_MAX_HARMONICS && filt < _num_filters; i++) { const float notch_center = center_freq_hz * (i+1); if ((1U< T HarmonicNotchFilter::apply(const T &sample) { if (!_initialised) { return sample; } T output = sample; for (uint8_t i = 0; i < _num_enabled_filters; i++) { output = _filters[i].apply(output); } return output; } /* reset all of the underlying filters */ template void HarmonicNotchFilter::reset() { if (!_initialised) { return; } for (uint8_t i = 0; i < _num_filters; i++) { _filters[i].reset(); } } /* create parameters for the harmonic notch filter and initialise defaults */ HarmonicNotchFilterParams::HarmonicNotchFilterParams(void) { AP_Param::setup_object_defaults(this, var_info); } /* instantiate template classes */ template class HarmonicNotchFilter;