HarmonicNotchFilter.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include "HarmonicNotchFilter.h"
  14. #include <GCS_MAVLink/GCS.h>
  15. #define HNF_MAX_FILTERS 3
  16. #define HNF_MAX_HARMONICS 8
  17. // table of user settable parameters
  18. const AP_Param::GroupInfo HarmonicNotchFilterParams::var_info[] = {
  19. // @Param: ENABLE
  20. // @DisplayName: Harmonic Notch Filter enable
  21. // @Description: Harmonic Notch Filter enable
  22. // @Values: 0:Disabled,1:Enabled
  23. // @User: Advanced
  24. AP_GROUPINFO_FLAGS("ENABLE", 1, HarmonicNotchFilterParams, _enable, 0, AP_PARAM_FLAG_ENABLE),
  25. // @Param: FREQ
  26. // @DisplayName: Harmonic Notch Filter base frequency
  27. // @Description: Harmonic Notch Filter base center frequency in Hz
  28. // @Range: 10 400
  29. // @Units: Hz
  30. // @User: Advanced
  31. AP_GROUPINFO("FREQ", 2, HarmonicNotchFilterParams, _center_freq_hz, 80),
  32. // @Param: BW
  33. // @DisplayName: Harmonic Notch Filter bandwidth
  34. // @Description: Harmonic Notch Filter bandwidth in Hz
  35. // @Range: 5 100
  36. // @Units: Hz
  37. // @User: Advanced
  38. AP_GROUPINFO("BW", 3, HarmonicNotchFilterParams, _bandwidth_hz, 20),
  39. // @Param: ATT
  40. // @DisplayName: Harmonic Notch Filter attenuation
  41. // @Description: Harmonic Notch Filter attenuation in dB
  42. // @Range: 5 30
  43. // @Units: dB
  44. // @User: Advanced
  45. AP_GROUPINFO("ATT", 4, HarmonicNotchFilterParams, _attenuation_dB, 15),
  46. // @Param: HMNCS
  47. // @DisplayName: Harmonic Notch Filter harmonics
  48. // @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
  49. // @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
  50. // @User: Advanced
  51. // @RebootRequired: True
  52. AP_GROUPINFO("HMNCS", 5, HarmonicNotchFilterParams, _harmonics, 3),
  53. // @Param: REF
  54. // @DisplayName: Harmonic Notch Filter reference value
  55. // @Description: Reference value associated with the specified frequency to facilitate frequency scaling of the Harmonic Notch Filter
  56. // @User: Advanced
  57. // @Range: 0.1 0.9
  58. // @RebootRequired: True
  59. AP_GROUPINFO("REF", 6, HarmonicNotchFilterParams, _reference, 0.1f),
  60. AP_GROUPEND
  61. };
  62. /*
  63. destroy all of the associated notch filters
  64. */
  65. template <class T>
  66. HarmonicNotchFilter<T>::~HarmonicNotchFilter() {
  67. delete[] _filters;
  68. _num_filters = 0;
  69. _num_enabled_filters = 0;
  70. }
  71. /*
  72. initialise the associated filters with the provided shaping constraints
  73. the constraints are used to determine attenuation (A) and quality (Q) factors for the filter
  74. */
  75. template <class T>
  76. void HarmonicNotchFilter<T>::init(float sample_freq_hz, float center_freq_hz, float bandwidth_hz, float attenuation_dB)
  77. {
  78. // sanity check the input
  79. if (_filters == nullptr || is_zero(sample_freq_hz) || isnan(sample_freq_hz)) {
  80. return;
  81. }
  82. _sample_freq_hz = sample_freq_hz;
  83. const float nyquist_limit = sample_freq_hz * 0.48f;
  84. // adjust the fundamental center frequency to be in the allowable range
  85. center_freq_hz = constrain_float(center_freq_hz, bandwidth_hz * 0.52f, nyquist_limit);
  86. // calculate attenuation and quality from the shaping constraints
  87. NotchFilter<T>::calculate_A_and_Q(center_freq_hz, bandwidth_hz, attenuation_dB, _A, _Q);
  88. _num_enabled_filters = 0;
  89. // initialize all the configured filters with the same A & Q and multiples of the center frequency
  90. for (uint8_t i = 0, filt = 0; i < HNF_MAX_HARMONICS && filt < _num_filters; i++) {
  91. const float notch_center = center_freq_hz * (i+1);
  92. if ((1U<<i) & _harmonics) {
  93. // only enable the filter if its center frequency is below the nyquist frequency
  94. if (notch_center < nyquist_limit) {
  95. _filters[filt].init_with_A_and_Q(sample_freq_hz, notch_center, _A, _Q);
  96. _num_enabled_filters++;
  97. }
  98. filt++;
  99. }
  100. }
  101. _initialised = true;
  102. }
  103. /*
  104. allocate a collection of, at most HNF_MAX_FILTERS, notch filters to be managed by this harmonic notch filter
  105. */
  106. template <class T>
  107. void HarmonicNotchFilter<T>::allocate_filters(uint8_t harmonics)
  108. {
  109. for (uint8_t i = 0; i < HNF_MAX_HARMONICS && _num_filters < HNF_MAX_FILTERS; i++) {
  110. if ((1U<<i) & harmonics) {
  111. _num_filters++;
  112. }
  113. }
  114. if (_num_filters > 0) {
  115. _filters = new NotchFilter<T>[_num_filters];
  116. if (_filters == nullptr) {
  117. gcs().send_text(MAV_SEVERITY_WARNING, "Failed to allocate %u bytes for HarmonicNotchFilter", (unsigned int)(_num_filters * sizeof(NotchFilter<T>)));
  118. _num_filters = 0;
  119. }
  120. }
  121. _harmonics = harmonics;
  122. }
  123. /*
  124. update the underlying filters' center frequency using the current attenuation and quality
  125. this function is cheaper than init() because A & Q do not need to be recalculated
  126. */
  127. template <class T>
  128. void HarmonicNotchFilter<T>::update(float center_freq_hz)
  129. {
  130. if (!_initialised) {
  131. return;
  132. }
  133. // adjust the fundamental center frequency to be in the allowable range
  134. const float nyquist_limit = _sample_freq_hz * 0.48f;
  135. center_freq_hz = constrain_float(center_freq_hz, 1.0f, nyquist_limit);
  136. _num_enabled_filters = 0;
  137. // update all of the filters using the new center frequency and existing A & Q
  138. for (uint8_t i = 0, filt = 0; i < HNF_MAX_HARMONICS && filt < _num_filters; i++) {
  139. const float notch_center = center_freq_hz * (i+1);
  140. if ((1U<<i) & _harmonics) {
  141. // only enable the filter if its center frequency is below the nyquist frequency
  142. if (notch_center < nyquist_limit) {
  143. _filters[filt].init_with_A_and_Q(_sample_freq_hz, notch_center, _A, _Q);
  144. _num_enabled_filters++;
  145. }
  146. filt++;
  147. }
  148. }
  149. }
  150. /*
  151. apply a sample to each of the underlying filters in turn and return the output
  152. */
  153. template <class T>
  154. T HarmonicNotchFilter<T>::apply(const T &sample)
  155. {
  156. if (!_initialised) {
  157. return sample;
  158. }
  159. T output = sample;
  160. for (uint8_t i = 0; i < _num_enabled_filters; i++) {
  161. output = _filters[i].apply(output);
  162. }
  163. return output;
  164. }
  165. /*
  166. reset all of the underlying filters
  167. */
  168. template <class T>
  169. void HarmonicNotchFilter<T>::reset()
  170. {
  171. if (!_initialised) {
  172. return;
  173. }
  174. for (uint8_t i = 0; i < _num_filters; i++) {
  175. _filters[i].reset();
  176. }
  177. }
  178. /*
  179. create parameters for the harmonic notch filter and initialise defaults
  180. */
  181. HarmonicNotchFilterParams::HarmonicNotchFilterParams(void)
  182. {
  183. AP_Param::setup_object_defaults(this, var_info);
  184. }
  185. /*
  186. instantiate template classes
  187. */
  188. template class HarmonicNotchFilter<Vector3f>;