/**************************************************************************** * * Copyright (c) 2019-2021 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name PX4 nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace time_literals; namespace sensors { class VehicleAngularVelocity : public ModuleParams, public px4::ScheduledWorkItem { public: VehicleAngularVelocity(); ~VehicleAngularVelocity() override; void PrintStatus(); bool Start(); void Stop(); private: void Run() override; void CalibrateAndPublish(bool publish, const hrt_abstime ×tamp_sample, const matrix::Vector3f &angular_velocity, const matrix::Vector3f &angular_acceleration); inline float FilterAngularVelocity(int axis, float data[], int N = 1); inline float FilterAngularAcceleration(int axis, float dt_s, float data[], int N = 1); void DisableDynamicNotchEscRpm(); void DisableDynamicNotchFFT(); void ParametersUpdate(bool force = false); void ResetFilters(); void SensorBiasUpdate(bool force = false); bool SensorSelectionUpdate(bool force = false); void UpdateDynamicNotchEscRpm(bool force = false); void UpdateDynamicNotchFFT(bool force = false); bool UpdateSampleRate(); // scaled appropriately for current sensor matrix::Vector3f GetResetAngularVelocity() const; matrix::Vector3f GetResetAngularAcceleration() const; static constexpr int MAX_SENSOR_COUNT = 4; uORB::Publication _vehicle_angular_acceleration_pub{ORB_ID(vehicle_angular_acceleration)}; uORB::Publication _vehicle_angular_velocity_pub{ORB_ID(vehicle_angular_velocity)}; uORB::Subscription _estimator_selector_status_sub{ORB_ID(estimator_selector_status)}; uORB::Subscription _estimator_sensor_bias_sub{ORB_ID(estimator_sensor_bias)}; #if !defined(CONSTRAINED_FLASH) uORB::Subscription _esc_status_sub {ORB_ID(esc_status)}; uORB::Subscription _sensor_gyro_fft_sub {ORB_ID(sensor_gyro_fft)}; #endif // !CONSTRAINED_FLASH uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; uORB::SubscriptionCallbackWorkItem _sensor_selection_sub{this, ORB_ID(sensor_selection)}; uORB::SubscriptionCallbackWorkItem _sensor_sub{this, ORB_ID(sensor_gyro)}; uORB::SubscriptionCallbackWorkItem _sensor_fifo_sub{this, ORB_ID(sensor_gyro_fifo)}; calibration::Gyroscope _calibration{}; matrix::Vector3f _bias{}; matrix::Vector3f _angular_velocity{}; matrix::Vector3f _angular_velocity_prev{}; matrix::Vector3f _angular_acceleration{}; matrix::Vector3f _angular_velocity_raw_prev{}; hrt_abstime _timestamp_sample_last{0}; hrt_abstime _publish_interval_min_us{0}; hrt_abstime _last_publish{0}; float _filter_sample_rate_hz{NAN}; static constexpr const float kInitialRateHz{1000.f}; /**< sensor update rate used for initialization */ // angular velocity filters math::LowPassFilter2pArray _lp_filter_velocity[3] {{kInitialRateHz, 30.f}, {kInitialRateHz, 30.f}, {kInitialRateHz, 30.f}}; math::NotchFilter _notch_filter_velocity[3] {}; #if !defined(CONSTRAINED_FLASH) enum DynamicNotch { EscRpm = 1, FFT = 2, }; static constexpr hrt_abstime DYNAMIC_NOTCH_FITLER_TIMEOUT = 1_s; static constexpr int MAX_NUM_ESC_RPM = sizeof(esc_status_s::esc) / sizeof(esc_status_s::esc[0]); static constexpr int MAX_NUM_ESC_RPM_HARMONICS = 3; static constexpr int MAX_NUM_FFT_PEAKS = sizeof(sensor_gyro_fft_s::peak_frequencies_x) / sizeof( sensor_gyro_fft_s::peak_frequencies_x[0]); math::NotchFilter _dynamic_notch_filter_esc_rpm[3][MAX_NUM_ESC_RPM][MAX_NUM_ESC_RPM_HARMONICS] {}; math::NotchFilter _dynamic_notch_filter_fft[3][MAX_NUM_FFT_PEAKS] {}; px4::Bitset _esc_available{}; hrt_abstime _last_esc_rpm_notch_update[MAX_NUM_ESC_RPM] {}; perf_counter_t _dynamic_notch_filter_esc_rpm_update_perf{nullptr}; perf_counter_t _dynamic_notch_filter_fft_update_perf{nullptr}; perf_counter_t _dynamic_notch_filter_esc_rpm_perf{nullptr}; perf_counter_t _dynamic_notch_filter_fft_perf{nullptr}; bool _dynamic_notch_esc_rpm_available{false}; bool _dynamic_notch_fft_available{false}; #endif // !CONSTRAINED_FLASH // angular acceleration filter math::LowPassFilter2p _lp_filter_acceleration[3] {{kInitialRateHz, 30.f}, {kInitialRateHz, 30.f}, {kInitialRateHz, 30.f}}; uint32_t _selected_sensor_device_id{0}; bool _reset_filters{true}; bool _fifo_available{false}; perf_counter_t _filter_reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": gyro filter reset")}; perf_counter_t _selection_changed_perf{perf_alloc(PC_COUNT, MODULE_NAME": gyro selection changed")}; DEFINE_PARAMETERS( #if !defined(CONSTRAINED_FLASH) (ParamInt) _param_imu_gyro_dyn_nf, #endif // !CONSTRAINED_FLASH (ParamFloat) _param_imu_gyro_cutoff, (ParamFloat) _param_imu_gyro_nf_freq, (ParamFloat) _param_imu_gyro_nf_bw, (ParamInt) _param_imu_gyro_ratemax, (ParamFloat) _param_imu_dgyro_cutoff ) }; } // namespace sensors