LCOV - code coverage report
Current view: top level - AP_InertialSensor - AP_InertialSensor.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 73 75 97.3 %
Date: 2026-09-09 11:02:08 Functions: 64 67 95.5 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AP_HAL/AP_HAL_Boards.h>
       4             : 
       5             : #ifndef INS_AUX_INSTANCES
       6             : #define INS_AUX_INSTANCES 0
       7             : #endif
       8             : 
       9             : #ifndef INS_MAX_INSTANCES
      10             : #define INS_MAX_INSTANCES (3+INS_AUX_INSTANCES)
      11             : #endif
      12             : 
      13             : #if INS_MAX_INSTANCES < 3 && INS_AUX_INSTANCES > 0
      14             : #error "INS_AUX_INSTANCES must be zero if INS_MAX_INSTANCES is less than 3"
      15             : #endif
      16             : 
      17             : #if INS_MAX_INSTANCES > 3 && INS_AUX_INSTANCES == 0
      18             : #error "INS_AUX_INSTANCES must be non-zero if INS_MAX_INSTANCES is greater than 3"
      19             : #endif
      20             : 
      21             : #define INS_MAX_BACKENDS  2*INS_MAX_INSTANCES
      22             : #define INS_MAX_NOTCHES 12
      23             : #ifndef INS_VIBRATION_CHECK_INSTANCES
      24             :   #if HAL_MEM_CLASS >= HAL_MEM_CLASS_300
      25             :     #define INS_VIBRATION_CHECK_INSTANCES INS_MAX_INSTANCES
      26             :   #else
      27             :     #define INS_VIBRATION_CHECK_INSTANCES 1
      28             :   #endif
      29             : #endif
      30             : #define XYZ_AXIS_COUNT    3
      31             : // The maximum we need to store is gyro-rate / loop-rate, worst case ArduCopter with BMI088 is 2000/400
      32             : #define INS_MAX_GYRO_WINDOW_SAMPLES 8
      33             : 
      34             : #define DEFAULT_IMU_LOG_BAT_MASK 0
      35             : 
      36             : #include "AP_InertialSensor_config.h"
      37             : 
      38             : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
      39             : #ifndef HAL_INS_NUM_HARMONIC_NOTCH_FILTERS
      40             : #if HAL_PROGRAM_SIZE_LIMIT_KB > 1024
      41             : # define HAL_INS_NUM_HARMONIC_NOTCH_FILTERS 3
      42             : #else
      43             : # define HAL_INS_NUM_HARMONIC_NOTCH_FILTERS 2
      44             : #endif
      45             : #endif
      46             : #endif
      47             : 
      48             : // time for the estimated gyro rates to converge
      49             : #ifndef HAL_INS_CONVERGANCE_MS
      50             : #define HAL_INS_CONVERGANCE_MS 30000
      51             : #endif
      52             : 
      53             : // Gyro and Accelerometer calibration criteria
      54             : #define AP_INERTIAL_SENSOR_ACCEL_VIBE_FLOOR_FILT_HZ     5.0f    // accel vibration floor filter hz
      55             : #define AP_INERTIAL_SENSOR_ACCEL_VIBE_FILT_HZ           2.0f    // accel vibration filter hz
      56             : #define AP_INERTIAL_SENSOR_ACCEL_PEAK_DETECT_TIMEOUT_MS 500     // peak-hold detector timeout
      57             : 
      58             : #include <AP_HAL/AP_HAL_Boards.h>
      59             : 
      60             : #include <stdint.h>
      61             : 
      62             : #include <AP_AccelCal/AP_AccelCal.h>
      63             : #include <AP_HAL/utility/RingBuffer.h>
      64             : #include <AP_Math/AP_Math.h>
      65             : #include <AP_ExternalAHRS/AP_ExternalAHRS.h>
      66             : #include <Filter/LowPassFilter.h>
      67             : #include <Filter/HarmonicNotchFilter.h>
      68             : #include <AP_SerialManager/AP_SerialManager_config.h>
      69             : #include "AP_InertialSensor_Params.h"
      70             : #include "AP_InertialSensor_tempcal.h"
      71             : 
      72             : #ifndef AP_SIM_INS_ENABLED
      73             : #define AP_SIM_INS_ENABLED AP_SIM_ENABLED
      74             : #endif
      75             : 
      76             : #ifndef AP_SIM_INS_FILE_ENABLED
      77             : #define AP_SIM_INS_FILE_ENABLED AP_SIM_ENABLED
      78             : #endif
      79             : 
      80             : class AP_InertialSensor_Backend;
      81             : class AuxiliaryBus;
      82             : class AP_AHRS;
      83             : class FastRateBuffer;
      84             : 
      85             : /*
      86             :   forward declare AP_Logger class. We can't include logger.h
      87             :   because of mutual dependencies
      88             :  */
      89             : class AP_Logger;
      90             : 
      91             : /* AP_InertialSensor is an abstraction for gyro and accel measurements
      92             :  * which are correctly aligned to the body axes and scaled to SI units.
      93             :  *
      94             :  * Gauss-Newton accel calibration routines borrowed from Rolfe Schmidt
      95             :  * blog post describing the method: http://chionophilous.wordpress.com/2011/10/24/accelerometer-calibration-iv-1-implementing-gauss-newton-on-an-atmega/
      96             :  * original sketch available at http://rolfeschmidt.com/mathtools/skimetrics/adxl_gn_calibration.pde
      97             :  */
      98             : class AP_InertialSensor : AP_AccelCal_Client
      99             : {
     100             :     friend class AP_InertialSensor_Backend;
     101             :     friend class FastRateBuffer;
     102             : 
     103             : public:
     104             :     AP_InertialSensor();
     105             : 
     106             :     /* Do not allow copies */
     107             :     CLASS_NO_COPY(AP_InertialSensor);
     108             : 
     109             :     static AP_InertialSensor *get_singleton();
     110             : 
     111             :     enum Gyro_Calibration_Timing {
     112             :         GYRO_CAL_NEVER = 0,
     113             :         GYRO_CAL_STARTUP_ONLY = 1
     114             :     };
     115             : 
     116             :     /// Perform startup initialisation.
     117             :     ///
     118             :     /// Called to initialise the state of the IMU.
     119             :     ///
     120             :     /// Gyros will be calibrated unless INS_GYRO_CAL is zero
     121             :     ///
     122             :     /// @param style    The initialisation startup style.
     123             :     ///
     124             :     __INITFUNC__ void init(uint16_t sample_rate_hz);
     125             : 
     126             :     // get accel/gyro instance numbers that a backend will get when they register
     127             :     bool get_accel_instance(uint8_t &instance) const;
     128             :     bool get_gyro_instance(uint8_t &instance) const;
     129             : 
     130             :     /// Register a new gyro/accel driver, allocating an instance
     131             :     /// number
     132             :     bool register_gyro(uint8_t &instance, uint16_t raw_sample_rate_hz, uint32_t id);
     133             :     bool register_accel(uint8_t &instance, uint16_t raw_sample_rate_hz, uint32_t id);
     134             : 
     135             :     // a function called by the main thread at the main loop rate:
     136             :     void periodic();
     137             : 
     138             :     /// calibrating - returns true if the gyros or accels are currently being calibrated
     139             :     bool calibrating() const;
     140             : 
     141             :     /// calibrating - returns true if a temperature calibration is running
     142             :     bool temperature_cal_running() const;
     143             :     
     144             :     /// Perform cold-start initialisation for just the gyros.
     145             :     ///
     146             :     /// @note This should not be called unless ::init has previously
     147             :     ///       been called, as ::init may perform other work
     148             :     ///
     149             :     void init_gyro(void);
     150             : 
     151             :     // get startup messages to output to the GCS
     152             :     bool get_output_banner(uint8_t instance_id, char* banner, uint8_t banner_len);
     153             : 
     154             :     /// Fetch the current gyro values
     155             :     ///
     156             :     /// @returns        vector of rotational rates in radians/sec
     157             :     ///
     158   229588803 :     const Vector3f     &get_gyro(uint8_t i) const { return _gyro[i]; }
     159    84570008 :     const Vector3f     &get_gyro(void) const { return get_gyro(_first_usable_gyro); }
     160             : 
     161             :     // set gyro offsets in radians/sec
     162             :     const Vector3f &get_gyro_offsets(uint8_t i) const { return _gyro_offset(i); }
     163             :     const Vector3f &get_gyro_offsets(void) const { return get_gyro_offsets(_first_usable_gyro); }
     164             : 
     165             :     //get delta angle if available
     166             :     bool get_delta_angle(uint8_t i, Vector3f &delta_angle, float &delta_angle_dt) const;
     167    41686716 :     bool get_delta_angle(Vector3f &delta_angle, float &delta_angle_dt) const {
     168    41686716 :         return get_delta_angle(_first_usable_gyro, delta_angle, delta_angle_dt);
     169             :     }
     170             : 
     171             :     //get delta velocity if available
     172             :     bool get_delta_velocity(uint8_t i, Vector3f &delta_velocity, float &delta_velocity_dt) const;
     173       47918 :     bool get_delta_velocity(Vector3f &delta_velocity, float &delta_velocity_dt) const {
     174       47918 :         return get_delta_velocity(_first_usable_accel, delta_velocity, delta_velocity_dt);
     175             :     }
     176             : 
     177             :     /// Fetch the current accelerometer values
     178             :     ///
     179             :     /// @returns        vector of current accelerations in m/s/s
     180             :     ///
     181   199771948 :     const Vector3f     &get_accel(uint8_t i) const { return _accel[i]; }
     182    92800162 :     const Vector3f     &get_accel(void) const { return get_accel(_first_usable_accel); }
     183             : 
     184             :     // multi-device interface
     185   147934773 :     bool get_gyro_health(uint8_t instance) const { return (instance<_gyro_count) ? _gyro_healthy[instance] : false; }
     186      758815 :     bool get_gyro_health(void) const { return get_gyro_health(_first_usable_gyro); }
     187             :     bool get_gyro_health_all(void) const;
     188             :     bool gyros_consistent(uint8_t threshold) const;
     189    65569551 :     uint8_t get_gyro_count(void) const { return MIN(INS_MAX_INSTANCES, _gyro_count); }
     190     2580509 :     bool gyro_calibrated_ok(uint8_t instance) const { return _gyro_cal_ok[instance]; }
     191             :     bool gyro_calibrated_ok_all() const;
     192             :     bool use_gyro(uint8_t instance) const;
     193             :     Gyro_Calibration_Timing gyro_calibration_timing();
     194             : 
     195   239378691 :     bool get_accel_health(uint8_t instance) const { return (instance<_accel_count) ? _accel_healthy[instance] : false; }
     196      758815 :     bool get_accel_health(void) const { return get_accel_health(_first_usable_accel); }
     197             :     bool get_accel_health_all(void) const;
     198             :     bool accels_consistent(float accel_error_threshold) const;
     199   200586132 :     uint8_t get_accel_count(void) const { return MIN(INS_MAX_INSTANCES, _accel_count); }
     200             :     bool accel_calibrated_ok_all() const;
     201             :     bool use_accel(uint8_t instance) const;
     202             : 
     203             :     // get observed sensor rates, including any internal sampling multiplier
     204    20832976 :     uint16_t get_gyro_rate_hz(uint8_t instance) const { return uint16_t(_gyro_raw_sample_rates[instance] * _gyro_over_sampling[instance]); }
     205    20832976 :     uint16_t get_accel_rate_hz(uint8_t instance) const { return uint16_t(_accel_raw_sample_rates[instance] * _accel_over_sampling[instance]); }
     206             : 
     207             :     // validate backend sample rates
     208             :     bool pre_arm_check_gyro_backend_rate_hz(char* fail_msg, uint16_t fail_msg_len) const;
     209             : 
     210             :     // FFT support access
     211             : #if HAL_GYROFFT_ENABLED
     212       31554 :     const Vector3f& get_gyro_for_fft(void) const { return _gyro_for_fft[_primary]; }
     213   502270225 :     FloatBuffer&  get_raw_gyro_window(uint8_t instance, uint8_t axis) { return _gyro_window[instance][axis]; }
     214   502270225 :     FloatBuffer&  get_raw_gyro_window(uint8_t axis) { return get_raw_gyro_window(_primary, axis); }
     215             : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
     216             :     bool has_fft_notch() const;
     217             : #endif
     218             : #endif
     219      579405 :     uint16_t get_raw_gyro_rate_hz(uint8_t instance) const { return _gyro_raw_sample_rates[_first_usable_gyro]; }
     220      579405 :     uint16_t get_raw_gyro_rate_hz() const { return get_raw_gyro_rate_hz(_first_usable_gyro); }
     221             :     bool set_gyro_window_size(uint16_t size);
     222             :     // get accel offsets in m/s/s
     223             :     const Vector3f &get_accel_offsets(uint8_t i) const { return _accel_offset(i); }
     224             :     const Vector3f &get_accel_offsets(void) const { return get_accel_offsets(_first_usable_accel); }
     225             : 
     226             :     // get accel scale
     227             :     const Vector3f &get_accel_scale(uint8_t i) const { return _accel_scale(i); }
     228             :     const Vector3f &get_accel_scale(void) const { return get_accel_scale(_first_usable_accel); }
     229             : 
     230             :     // return a 3D vector defining the position offset of the IMU accelerometer in metres relative to the body frame origin
     231   123595814 :     const Vector3f &get_imu_pos_offset(uint8_t instance) const {
     232   123595814 :         return _accel_pos(instance);
     233             :     }
     234             :     const Vector3f &get_imu_pos_offset(void) const {
     235             :         return _accel_pos(_first_usable_accel);
     236             :     }
     237             : 
     238             :     // return the gyro bias limit (rad/s) for this IMU instance.
     239             :     // The EKF clamps its gyro bias state to this value.
     240             :     float get_gyro_bias_limit_rads(uint8_t instance) const;
     241             : 
     242             :     // return the initial gyro bias 1-sigma uncertainty (deg/s) for this
     243             :     // IMU instance, used to seed the EKF's gyro bias covariance.
     244             :     float get_gyro_bias_init_dps(uint8_t instance) const;
     245             : 
     246             :     // return the temperature if supported. Zero is returned if no
     247             :     // temperature is available
     248   567639076 :     float get_temperature(uint8_t instance) const { return _temperature[instance]; }
     249             : 
     250             :     /* get_delta_time returns the time period in seconds
     251             :      * overwhich the sensor data was collected
     252             :      */
     253    41686717 :     float get_delta_time() const { return MIN(_delta_time, _loop_delta_t_max); }
     254             : 
     255             :     // return the maximum gyro drift rate in radians/s/s. This
     256             :     // depends on what gyro chips are being used
     257       25788 :     float get_gyro_drift_rate(void) const { return radians(0.5f/60); }
     258             : 
     259             :     // update gyro and accel values from accumulated samples
     260             :     void update(void) __RAMFUNC__;
     261             : 
     262             :     // wait for a sample to be available
     263             :     void wait_for_sample(void) __RAMFUNC__;
     264             : 
     265             :     // class level parameters
     266             :     static const struct AP_Param::GroupInfo var_info[];
     267             : #if INS_AUX_INSTANCES
     268             :     AP_InertialSensor_Params params[INS_AUX_INSTANCES];
     269             : #endif
     270             : 
     271             :     // set overall board orientation
     272       54325 :     void set_board_orientation(enum Rotation orientation) {
     273       54325 :         _board_orientation = orientation;
     274       54325 :     }
     275             : 
     276             :     // return the selected loop rate at which samples are made avilable
     277    41156288 :     uint16_t get_loop_rate_hz(void) const { return _loop_rate; }
     278             : 
     279             :     // return the main loop delta_t in seconds
     280   123688019 :     float get_loop_delta_t(void) const { return _loop_delta_t; }
     281             : 
     282      758815 :     bool healthy(void) const { return get_gyro_health() && get_accel_health(); }
     283             : 
     284   207326397 :     uint8_t get_first_usable_accel(void) const { return _first_usable_accel; }
     285   207326397 :     uint8_t get_first_usable_gyro(void) const { return _first_usable_gyro; }
     286             : 
     287             :     // get the gyro filter rate in Hz
     288          83 :     uint16_t get_gyro_filter_hz(void) const { return _gyro_filter_cutoff; }
     289             : 
     290             :     // get the accel filter rate in Hz
     291             :     uint16_t get_accel_filter_hz(void) const { return _accel_filter_cutoff; }
     292             : 
     293             : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
     294             :     // setup the notch for throttle based tracking
     295             :     bool setup_throttle_gyro_harmonic_notch(float center_freq_hz, float lower_freq_hz, float ref, uint8_t harmonics);
     296             : 
     297             :     // write out harmonic notch log messages
     298             :     void write_notch_log_messages() const;
     299             : #endif
     300             : 
     301             :     // indicate which bit in LOG_BITMASK indicates raw logging enabled
     302        2055 :     void set_log_raw_bit(uint32_t log_raw_bit) { _log_raw_bit = log_raw_bit; }
     303             : 
     304             :     // Logging Functions
     305             :     void Write_IMU() const;
     306             :     void Write_Vibration() const;
     307             : 
     308             :     // calculate vibration levels and check for accelerometer clipping (called by a backends)
     309             :     void calc_vibration_and_clipping(uint8_t instance, const Vector3f &accel, float dt);
     310             : 
     311             :     // retrieve latest calculated vibration levels
     312     1553651 :     Vector3f get_vibration_levels() const { return get_vibration_levels(_first_usable_accel); }
     313             :     Vector3f get_vibration_levels(uint8_t instance) const;
     314             : 
     315             :     // retrieve and clear accelerometer clipping count
     316             :     uint32_t get_accel_clip_count(uint8_t instance) const;
     317             : 
     318             :     // check for vibration movement. True when all axis show nearly zero movement
     319             :     bool is_still();
     320             : 
     321           0 :     AuxiliaryBus *get_auxiliary_bus(int16_t backend_id) { return get_auxiliary_bus(backend_id, 0); }
     322             :     AuxiliaryBus *get_auxiliary_bus(int16_t backend_id, uint8_t instance);
     323             : 
     324             :     void detect_backends(void);
     325             :     void update_backends();
     326             : 
     327             :     // accel peak hold detector
     328             :     void set_accel_peak_hold(uint8_t instance, const Vector3f &accel);
     329           0 :     float get_accel_peak_hold_neg_x() const { return _peak_hold_state.accel_peak_hold_neg_x; }
     330             : 
     331             :     //Returns accel calibrator interface object pointer
     332        7456 :     AP_AccelCal* get_acal() const { return _acal; }
     333             : 
     334             :     // Returns body fixed accelerometer level data averaged during accel calibration's first step
     335             :     bool get_fixed_mount_accel_cal_sample(uint8_t sample_num, Vector3f& ret) const;
     336             : 
     337             :     // Returns primary accelerometer level data averaged during accel calibration's first step
     338             :     bool get_first_usable_accel_cal_sample_avg(uint8_t sample_num, Vector3f& ret) const;
     339             : 
     340             :     // Returns newly calculated trim values if calculated
     341             :     bool get_new_trim(Vector3f &trim_rad);
     342             : 
     343             :     // notify IMUs of the new primary
     344             :     void set_primary(uint8_t instance);
     345             : 
     346             : #if HAL_INS_ACCELCAL_ENABLED
     347             :     // initialise and register accel calibrator
     348             :     // called during the startup of accel cal
     349             :     void acal_init();
     350             : 
     351             :     // update accel calibrator
     352             :     void acal_update();
     353             : #endif
     354             : 
     355             : #if HAL_GCS_ENABLED
     356             :     bool calibrate_gyros();
     357             : 
     358             :     MAV_RESULT calibrate_trim();
     359             : 
     360             :     // simple accel calibration
     361             :     MAV_RESULT simple_accel_cal();
     362             : private:
     363             :     uint32_t last_accel_cal_ms;
     364             : public:
     365             : #endif
     366             : 
     367       64813 :     bool accel_cal_requires_reboot() const { return _accel_cal_requires_reboot; }
     368             : 
     369             :     // return time in microseconds of last update() call
     370   166918840 :     uint32_t get_last_update_usec(void) const { return _last_update_usec; }
     371             : 
     372             :     // for killing an IMU for testing purposes
     373             :     void kill_imu(uint8_t imu_idx, bool kill_it);
     374             : 
     375             : #if AP_SERIALMANAGER_IMUOUT_ENABLED
     376             :     // optional UART for sending IMU data to an external process
     377             :     void set_imu_out_uart(AP_HAL::UARTDriver *uart);
     378             :     void send_uart_data(void);
     379             : 
     380             :     struct {
     381             :         uint16_t counter;
     382             :         AP_HAL::UARTDriver *imu_out_uart;
     383             :     } uart;
     384             : #endif // AP_SERIALMANAGER_IMUOUT_ENABLED
     385             : 
     386             :     enum IMU_SENSOR_TYPE {
     387             :         IMU_SENSOR_TYPE_ACCEL = 0,
     388             :         IMU_SENSOR_TYPE_GYRO = 1,
     389             :     };
     390             : 
     391             : #if AP_INERTIALSENSOR_BATCHSAMPLER_ENABLED
     392             :     class BatchSampler {
     393             :     public:
     394        2098 :         BatchSampler(const AP_InertialSensor &imu) :
     395        2098 :             type(IMU_SENSOR_TYPE_ACCEL),
     396        2098 :             _imu(imu) {
     397        2098 :             AP_Param::setup_object_defaults(this, var_info);
     398        2098 :         };
     399             : 
     400             :         void init();
     401             :         void sample(uint8_t instance, IMU_SENSOR_TYPE _type, uint64_t sample_us, const Vector3f &sample) __RAMFUNC__;
     402             : 
     403             :         // a function called by the main thread at the main loop rate:
     404             :         void periodic();
     405             : 
     406  2600657042 :         bool doing_sensor_rate_logging() const { return _doing_sensor_rate_logging; }
     407   545430875 :         bool doing_post_filter_logging() const {
     408     4462518 :             return (_doing_post_filter_logging && (post_filter || !_doing_sensor_rate_logging))
     409   549893393 :                 || (_doing_pre_post_filter_logging && post_filter);
     410             :         }
     411             : 
     412             :         // Getters for arming check
     413       11865 :         bool is_initialised() const { return initialised; }
     414       45832 :         bool enabled() const { return _sensor_mask > 0; }
     415             : 
     416             :         // class level parameters
     417             :         static const struct AP_Param::GroupInfo var_info[];
     418             :     
     419             : 
     420             :         // Parameters
     421             :         AP_Int16 _required_count;
     422             :         uint16_t _real_required_count;
     423             :         AP_Int8 _sensor_mask;
     424             :         AP_Int8 _batch_options_mask;
     425             : 
     426             :         // Parameters controlling pushing data to AP_Logger:
     427             :         // Each DF message is ~ 108 bytes in size, so we use about 1kB/s of
     428             :         // logging bandwidth with a 100ms interval.  If we are taking
     429             :         // 1024 samples then we need to send 32 packets, so it will
     430             :         // take ~3 seconds to push a complete batch to the log.  If
     431             :         // you are running a on an FMU with three IMUs then you
     432             :         // will loop back around to the first sensor after about
     433             :         // twenty seconds.
     434             :         AP_Int16 samples_per_msg;
     435             :         AP_Int8 push_interval_ms;
     436             : 
     437             :         // end Parameters
     438             : 
     439             :     private:
     440             : 
     441             :         enum batch_opt_t {
     442             :             BATCH_OPT_SENSOR_RATE = (1<<0),
     443             :             BATCH_OPT_POST_FILTER = (1<<1),
     444             :             BATCH_OPT_PRE_POST_FILTER = (1<<2),
     445             :         };
     446             : 
     447             :         void rotate_to_next_sensor();
     448             :         void update_doing_sensor_rate_logging();
     449             : 
     450             :         bool should_log(uint8_t instance, IMU_SENSOR_TYPE type) __RAMFUNC__;
     451             :         void push_data_to_log();
     452             : 
     453             :         // Logging functions
     454             :         bool Write_ISBH(const float sample_rate_hz) const;
     455             :         bool Write_ISBD() const;
     456             : 
     457       39384 :         bool has_option(batch_opt_t option) const { return _batch_options_mask & uint16_t(option); }
     458             : 
     459             :         uint64_t measurement_started_us;
     460             : 
     461             :         bool initialised;
     462             :         bool isbh_sent;
     463             :         bool _doing_sensor_rate_logging;
     464             :         bool _doing_post_filter_logging;
     465             :         bool _doing_pre_post_filter_logging;
     466             :         uint8_t instance; // instance we are sending data for
     467             :         bool post_filter; // whether we are sending post-filter data
     468             :         AP_InertialSensor::IMU_SENSOR_TYPE type;
     469             :         uint16_t isb_seqnum;
     470             :         int16_t *data_x;
     471             :         int16_t *data_y;
     472             :         int16_t *data_z;
     473             :         uint16_t data_write_offset; // units: samples
     474             :         uint16_t data_read_offset; // units: samples
     475             :         uint32_t last_sent_ms;
     476             : 
     477             :         // all samples are multiplied by this
     478             :         uint16_t multiplier; // initialised as part of init()
     479             : 
     480             :         const AP_InertialSensor &_imu;
     481             :     };
     482             :     BatchSampler batchsampler{*this};
     483             : #endif
     484             : 
     485             : #if AP_EXTERNAL_AHRS_ENABLED
     486             :     // handle external AHRS data
     487             :     void handle_external(const AP_ExternalAHRS::ins_data_message_t &pkt);
     488             : #endif
     489             : 
     490             : #if HAL_INS_TEMPERATURE_CAL_ENABLE
     491             :     /*
     492             :       get a string representation of parameters that should be made
     493             :       persistent across changes of firmware type
     494             :      */
     495             :     void get_persistent_params(ExpandingString &str) const;
     496             : #endif
     497             : 
     498             :     // force save of current calibration as valid
     499             :     void force_save_calibration(void);
     500             : 
     501             : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
     502             :     // structure per harmonic notch filter. This is public to allow for
     503             :     // easy iteration
     504             :     class HarmonicNotch {
     505             :     public:
     506             :         HarmonicNotchFilterParams params;
     507             :         HarmonicNotchFilterVector3f filter[INS_MAX_INSTANCES];
     508             : 
     509             :         uint8_t num_dynamic_notches;
     510             : 
     511             :         // the current center frequency for the notch
     512             :         float calculated_notch_freq_hz[INS_MAX_NOTCHES];
     513             :         uint8_t num_calculated_notch_frequencies;
     514             : 
     515             :         // runtime update of notch parameters
     516             :         void update_params(uint8_t instance, bool converging, float gyro_rate);
     517             : 
     518             :         // Update the harmonic notch frequencies
     519             :         void update_freq_hz(float scaled_freq);
     520             :         void update_frequencies_hz(uint8_t num_freqs, const float scaled_freq[]);
     521             : 
     522             :         // enable/disable the notch
     523       44424 :         void set_inactive(bool _inactive) {
     524       44424 :             inactive = _inactive;
     525       44424 :         }
     526             : 
     527     4309615 :         bool is_inactive(void) const {
     528     4309615 :             return inactive;
     529             :         }
     530             : 
     531             :     private:
     532             :         // support for updating harmonic filter at runtime
     533             :         float last_center_freq_hz[INS_MAX_INSTANCES];
     534             :         float last_bandwidth_hz[INS_MAX_INSTANCES];
     535             :         float last_attenuation_dB[INS_MAX_INSTANCES];
     536             :         bool inactive;
     537             :     } harmonic_notches[HAL_INS_NUM_HARMONIC_NOTCH_FILTERS];
     538             : #endif  // AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
     539             : 
     540             : private:
     541             :     // load backend drivers
     542             :     bool _add_backend(AP_InertialSensor_Backend *backend);
     543             :     void _start_backends();
     544             :     AP_InertialSensor_Backend *_find_backend(int16_t backend_id, uint8_t instance);
     545             : 
     546             :     // gyro initialisation
     547             :     void _init_gyro();
     548             : 
     549             :     // Calibration routines borrowed from Rolfe Schmidt
     550             :     // blog post describing the method: http://chionophilous.wordpress.com/2011/10/24/accelerometer-calibration-iv-1-implementing-gauss-newton-on-an-atmega/
     551             :     // original sketch available at http://rolfeschmidt.com/mathtools/skimetrics/adxl_gn_calibration.pde
     552             : 
     553             :     bool _calculate_trim(const Vector3f &accel_sample, Vector3f &trim_rad);
     554             : 
     555             :     // save gyro calibration values to eeprom
     556             :     void _save_gyro_calibration();
     557             : 
     558             :     // Logging function
     559             :     void Write_IMU_instance(const uint64_t time_us, const uint8_t imu_instance) const;
     560             : 
     561             :     // look up the backend that owns the given gyro instance, or nullptr
     562             :     const AP_InertialSensor_Backend *_find_gyro_backend(uint8_t instance) const;
     563             : 
     564             :     // backend objects
     565             :     AP_InertialSensor_Backend *_backends[INS_MAX_BACKENDS];
     566             : 
     567             :     // number of gyros and accel drivers. Note that most backends
     568             :     // provide both accel and gyro data, so will increment both
     569             :     // counters on initialisation
     570             :     uint8_t _gyro_count;
     571             :     uint8_t _accel_count;
     572             :     uint8_t _backend_count;
     573             : 
     574             :     // the selected loop rate at which samples are made available
     575             :     uint16_t _loop_rate;
     576             :     float _loop_delta_t;
     577             :     float _loop_delta_t_max;
     578             : 
     579             :     // Most recent accelerometer reading
     580             :     Vector3f _accel[INS_MAX_INSTANCES];
     581             :     Vector3f _delta_velocity[INS_MAX_INSTANCES];
     582             :     float _delta_velocity_dt[INS_MAX_INSTANCES];
     583             :     bool _delta_velocity_valid[INS_MAX_INSTANCES];
     584             :     // delta velocity accumulator
     585             :     Vector3f _delta_velocity_acc[INS_MAX_INSTANCES];
     586             :     // time accumulator for delta velocity accumulator
     587             :     float _delta_velocity_acc_dt[INS_MAX_INSTANCES];
     588             : 
     589             :     // Low Pass filters for gyro and accel
     590             :     LowPassFilter2pVector3f _accel_filter[INS_MAX_INSTANCES];
     591             :     LowPassFilter2pVector3f _gyro_filter[INS_MAX_INSTANCES];
     592             :     Vector3f _accel_filtered[INS_MAX_INSTANCES];
     593             :     Vector3f _gyro_filtered[INS_MAX_INSTANCES];
     594             : #if HAL_GYROFFT_ENABLED
     595             :     // Thread-safe public version of _last_raw_gyro
     596             :     Vector3f _gyro_for_fft[INS_MAX_INSTANCES];
     597             :     Vector3f _last_gyro_for_fft[INS_MAX_INSTANCES];
     598             :     FloatBuffer _gyro_window[INS_MAX_INSTANCES][XYZ_AXIS_COUNT];
     599             :     uint16_t _gyro_window_size;
     600             :     // capture a gyro window after the filters
     601             :     LowPassFilter2pVector3f _post_filter_gyro_filter[INS_MAX_INSTANCES];
     602             :     bool _post_filter_fft;
     603             :     uint8_t _fft_window_phase;
     604             : #endif
     605             :     bool _new_accel_data[INS_MAX_INSTANCES];
     606             :     bool _new_gyro_data[INS_MAX_INSTANCES];
     607             : 
     608             :     // Most recent gyro reading
     609             :     Vector3f _gyro[INS_MAX_INSTANCES];
     610             :     Vector3f _delta_angle[INS_MAX_INSTANCES];
     611             :     float _delta_angle_dt[INS_MAX_INSTANCES];
     612             :     bool _delta_angle_valid[INS_MAX_INSTANCES];
     613             :     // time accumulator for delta angle accumulator
     614             :     float _delta_angle_acc_dt[INS_MAX_INSTANCES];
     615             :     Vector3f _delta_angle_acc[INS_MAX_INSTANCES];
     616             :     Vector3f _last_delta_angle[INS_MAX_INSTANCES];
     617             :     Vector3f _last_raw_gyro[INS_MAX_INSTANCES];
     618             : 
     619             :     // bitmask indicating if a sensor is doing sensor-rate sampling:
     620             :     uint8_t _accel_sensor_rate_sampling_enabled;
     621             :     uint8_t _gyro_sensor_rate_sampling_enabled;
     622             : 
     623             :     // multipliers for data supplied via sensor-rate logging:
     624             :     uint16_t _accel_raw_sampling_multiplier[INS_MAX_INSTANCES];
     625             :     uint16_t _gyro_raw_sampling_multiplier[INS_MAX_INSTANCES];
     626             : 
     627             :     // IDs to uniquely identify each sensor: shall remain
     628             :     // the same across reboots
     629             :     AP_Int32 _accel_id_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     630             :     AP_Int32 _gyro_id_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     631             : 
     632             :     // accelerometer scaling and offsets
     633             :     AP_Vector3f _accel_scale_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     634             :     AP_Vector3f _accel_offset_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     635             :     AP_Vector3f _gyro_offset_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     636             : 
     637             :     // accelerometer position offset in body frame
     638             :     AP_Vector3f _accel_pos_old_param[INS_MAX_INSTANCES-INS_AUX_INSTANCES];
     639             : 
     640             :     // Use Accessor methods to access above variables
     641             : #if INS_AUX_INSTANCES
     642             :     #define INS_PARAM_WRAPPER(var) \
     643             :         inline decltype(var##_old_param[0])& var(uint8_t i) { \
     644             :             if (i<(INS_MAX_INSTANCES-INS_AUX_INSTANCES)) { \
     645             :                 return var##_old_param[i]; \
     646             :             } else { \
     647             :                 return params[i-(INS_MAX_INSTANCES-INS_AUX_INSTANCES)].var; \
     648             :             } \
     649             :         } \
     650             :         inline decltype(var##_old_param[0])& var(uint8_t i) const { \
     651             :             return const_cast<AP_InertialSensor*>(this)->var(i); \
     652             :         }
     653             : #else
     654             :     #define INS_PARAM_WRAPPER(var) \
     655             :         inline decltype(var##_old_param[0])& var(uint8_t i) { \
     656             :             return var##_old_param[i]; \
     657             :         } \
     658             :         inline decltype(var##_old_param[0])& var(uint8_t i) const { \
     659             :             return const_cast<AP_InertialSensor*>(this)->var(i); \
     660             :         }
     661             : #endif
     662             : 
     663             :     // Accessor methods for old parameters
     664     2059436 :     INS_PARAM_WRAPPER(_accel_id);
     665     2380962 :     INS_PARAM_WRAPPER(_gyro_id);
     666   281982727 :     INS_PARAM_WRAPPER(_accel_scale);
     667   282122870 :     INS_PARAM_WRAPPER(_accel_offset);
     668   268253928 :     INS_PARAM_WRAPPER(_gyro_offset);
     669   247191628 :     INS_PARAM_WRAPPER(_accel_pos);
     670             : 
     671             :     // accelerometer and gyro raw sample rate in units of Hz
     672             :     float  _accel_raw_sample_rates[INS_MAX_INSTANCES];
     673             :     float  _gyro_raw_sample_rates[INS_MAX_INSTANCES];
     674             : 
     675             :     // how many sensors samples per notify to the backend
     676             :     uint8_t _accel_over_sampling[INS_MAX_INSTANCES];
     677             :     uint8_t _gyro_over_sampling[INS_MAX_INSTANCES];
     678             : 
     679             :     // last sample time in microseconds. Use for deltaT calculations
     680             :     // on non-FIFO sensors
     681             :     uint64_t _accel_last_sample_us[INS_MAX_INSTANCES];
     682             :     uint64_t _gyro_last_sample_us[INS_MAX_INSTANCES];
     683             : 
     684             :     // sample times for checking real sensor rate for FIFO sensors
     685             :     uint16_t _sample_accel_count[INS_MAX_INSTANCES];
     686             :     uint32_t _sample_accel_start_us[INS_MAX_INSTANCES];
     687             :     uint16_t _sample_gyro_count[INS_MAX_INSTANCES];
     688             :     uint32_t _sample_gyro_start_us[INS_MAX_INSTANCES];
     689             :     
     690             :     // temperatures for an instance if available
     691             :     float _temperature[INS_MAX_INSTANCES];
     692             : 
     693             :     // filtering frequency (0 means default)
     694             :     AP_Int16    _accel_filter_cutoff;
     695             :     AP_Int16    _gyro_filter_cutoff;
     696             :     AP_Int8     _gyro_cal_timing;
     697             : 
     698             :     // use for attitude, velocity, position estimates
     699             :     AP_Int8     _use_old_param[INS_MAX_INSTANCES - INS_AUX_INSTANCES];
     700   759662112 :     INS_PARAM_WRAPPER(_use);
     701             : 
     702             :     // control enable of fast sampling
     703             :     AP_Int8     _fast_sampling_mask;
     704             : 
     705             :     // control enable of fast sampling
     706             :     AP_Int8     _fast_sampling_rate;
     707             : 
     708             :     // control enable of detected sensors
     709             :     AP_Int8     _enable_mask;
     710             :     
     711             :     // board orientation from AHRS
     712             :     enum Rotation _board_orientation;
     713             : 
     714             :     // per-sensor orientation to allow for board type defaults at runtime
     715             :     enum Rotation _gyro_orientation[INS_MAX_INSTANCES];
     716             :     enum Rotation _accel_orientation[INS_MAX_INSTANCES];
     717             : 
     718             :     // calibrated_ok/id_ok flags
     719             :     bool _gyro_cal_ok[INS_MAX_INSTANCES];
     720             :     bool _accel_id_ok[INS_MAX_INSTANCES];
     721             : 
     722             :     // first usable gyro and accel
     723             :     uint8_t _first_usable_gyro;
     724             :     uint8_t _first_usable_accel;
     725             : 
     726             :     // primary instance
     727             :     uint8_t _primary;
     728             : 
     729             :     // mask of accels and gyros which we will be actively using
     730             :     // and this should wait for in wait_for_sample()
     731             :     uint8_t _gyro_wait_mask;
     732             :     uint8_t _accel_wait_mask;
     733             : 
     734             :     // bitmask bit which indicates if we should log raw accel and gyro data
     735             :     uint32_t _log_raw_bit;
     736             : 
     737             :     // has wait_for_sample() found a sample?
     738             :     bool _have_sample:1;
     739             : 
     740             :     bool _backends_detected:1;
     741             : 
     742             :     // are gyros or accels currently being calibrated
     743             :     bool _calibrating_accel;
     744             :     bool _calibrating_gyro;
     745             :     bool _trimming_accel;
     746             : 
     747             :     // the delta time in seconds for the last sample
     748             :     float _delta_time;
     749             : 
     750             :     // last time a wait_for_sample() returned a sample
     751             :     uint32_t _last_sample_usec;
     752             : 
     753             :     // target time for next wait_for_sample() return
     754             :     uint32_t _next_sample_usec;
     755             : 
     756             :     // time between samples in microseconds
     757             :     uint32_t _sample_period_usec;
     758             : 
     759             :     // last time update() completed
     760             :     uint32_t _last_update_usec;
     761             : 
     762             :     // health of gyros and accels
     763             :     bool _gyro_healthy[INS_MAX_INSTANCES];
     764             :     bool _accel_healthy[INS_MAX_INSTANCES];
     765             : 
     766             :     uint32_t _accel_error_count[INS_MAX_INSTANCES];
     767             :     uint32_t _gyro_error_count[INS_MAX_INSTANCES];
     768             : 
     769             :     // vibration and clipping
     770             :     uint32_t _accel_clip_count[INS_MAX_INSTANCES];
     771             :     LowPassFilterVector3f _accel_vibe_floor_filter[INS_VIBRATION_CHECK_INSTANCES];
     772             :     LowPassFilterVector3f _accel_vibe_filter[INS_VIBRATION_CHECK_INSTANCES];
     773             : 
     774             :     // peak hold detector state for primary accel
     775             :     struct PeakHoldState {
     776             :         float accel_peak_hold_neg_x;
     777             :         uint32_t accel_peak_hold_neg_x_age;
     778             :     } _peak_hold_state;
     779             : 
     780             :     // threshold for detecting stillness
     781             :     AP_Float _still_threshold;
     782             : 
     783             :     // Trim options
     784             :     AP_Int8 _acc_body_aligned;
     785             :     AP_Int8 _trim_option;
     786             : 
     787             :     static AP_InertialSensor *_singleton;
     788             :     AP_AccelCal* _acal;
     789             : 
     790             :     AccelCalibrator *_accel_calibrator;
     791             : 
     792             :     //save accelerometer bias and scale factors
     793             :     void _acal_save_calibrations() override;
     794             :     void _acal_event_failure() override;
     795             : 
     796             :     // Returns AccelCalibrator objects pointer for specified acceleromter
     797       13142 :     AccelCalibrator* _acal_get_calibrator(uint8_t i) override { return i<get_accel_count()?&(_accel_calibrator[i]):nullptr; }
     798             : 
     799             :     Vector3f _trim_rad;
     800             :     bool _new_trim;
     801             : 
     802             :     bool _accel_cal_requires_reboot;
     803             : 
     804             :     // sensor error count at startup (used to ignore errors within 2 seconds of startup)
     805             :     uint32_t _accel_startup_error_count[INS_MAX_INSTANCES];
     806             :     uint32_t _gyro_startup_error_count[INS_MAX_INSTANCES];
     807             :     bool _startup_error_counts_set;
     808             :     uint32_t _startup_ms;
     809             : 
     810             : #if AP_INERTIALSENSOR_KILL_IMU_ENABLED
     811             :     uint8_t imu_kill_mask;
     812             : #endif
     813             : 
     814             : #if HAL_INS_TEMPERATURE_CAL_ENABLE
     815             : public:
     816             :     // instance number for logging
     817             : #if INS_AUX_INSTANCES
     818             :     uint8_t tcal_instance(const AP_InertialSensor_TCal &tc) const {
     819             :         for (uint8_t i=0; i<INS_MAX_INSTANCES - INS_AUX_INSTANCES; i++) {
     820             :             if (&tc == &tcal_old_param[i]) {
     821             :                 return i;
     822             :             }
     823             :         }
     824             :         for (uint8_t i=0; i<INS_AUX_INSTANCES; i++) {
     825             :             if (&tc == &params[i].tcal) {
     826             :                 return i + INS_MAX_INSTANCES;
     827             :             }
     828             :         }
     829             :         return 0;
     830             :     }
     831             : #else
     832         310 :     uint8_t tcal_instance(const AP_InertialSensor_TCal &tc) const {
     833         310 :         return &tc - &tcal(0);
     834             :     }
     835             : #endif
     836             : private:
     837             :     AP_InertialSensor_TCal tcal_old_param[INS_MAX_INSTANCES - INS_AUX_INSTANCES];
     838             : 
     839             :     enum class TCalOptions : uint8_t {
     840             :         PERSIST_TEMP_CAL = (1U<<0),
     841             :         PERSIST_ACCEL_CAL = (1U<<1),
     842             :     };
     843             : 
     844             :     // temperature that last calibration was run at
     845             :     AP_Float caltemp_accel_old_param[INS_MAX_INSTANCES - INS_AUX_INSTANCES];
     846             :     AP_Float caltemp_gyro_old_param[INS_MAX_INSTANCES - INS_AUX_INSTANCES];
     847             : 
     848   275561233 :     INS_PARAM_WRAPPER(caltemp_accel);
     849   268251176 :     INS_PARAM_WRAPPER(caltemp_gyro);
     850   544868612 :     INS_PARAM_WRAPPER(tcal);
     851             : 
     852             :     AP_Int32 tcal_options;
     853             :     bool tcal_learning;
     854             : #endif
     855             : 
     856             :     // Raw logging options bitmask and parameter
     857             :     enum class RAW_LOGGING_OPTION {
     858             :         PRIMARY_GYRO_ONLY   = (1U<<0),
     859             :         ALL_GYROS           = (1U<<1),
     860             :         POST_FILTER         = (1U<<2),
     861             :         PRE_AND_POST_FILTER = (1U<<3),
     862             :     };
     863             :     AP_Int16 raw_logging_options;
     864   539379140 :     bool raw_logging_option_set(RAW_LOGGING_OPTION option) const {
     865   539379140 :         return (raw_logging_options.get() & int32_t(option)) != 0;
     866             :     }
     867             :     // if AP_INERTIALSENSOR_FAST_SAMPLE_WINDOW_ENABLED
     868             :     // Support for the fast rate thread in copter
     869             :     FastRateBuffer* fast_rate_buffer;
     870             :     bool fast_rate_buffer_enabled;
     871             : 
     872             : public:
     873             :     // enable the fast rate buffer and start pushing samples to it
     874             :     void enable_fast_rate_buffer();
     875             :     // disable the fast rate buffer and stop pushing samples to it
     876             :     void disable_fast_rate_buffer();
     877             :     // get the next available gyro sample from the fast rate buffer
     878             :     bool get_next_gyro_sample(Vector3f& gyro);
     879             :     // get the number of available gyro samples in the fast rate buffer
     880             :     uint32_t get_num_gyro_samples();
     881             :     // set the rate at which samples are collected, unused samples are dropped
     882             :     void set_rate_decimation(uint8_t rdec);
     883             :     // push a new gyro sample into the fast rate buffer
     884             :     bool push_next_gyro_sample(const Vector3f& gyro);
     885             :     // run the filter parmeter update code.
     886             :     void update_backend_filters();
     887             :     // are rate loop samples enabled for this instance?
     888             :     bool is_rate_loop_gyro_enabled(uint8_t instance) const;
     889             :     // is dynamic fifo enabled for this instance
     890             :     bool is_dynamic_fifo_enabled(uint8_t instance) const;
     891             :     // endif AP_INERTIALSENSOR_FAST_SAMPLE_WINDOW_ENABLED
     892             : 
     893             :     uint8_t get_first_onboard_imu_instance() const { return _first_onboard_imu_instance; }
     894             : private:
     895             :     uint8_t _first_onboard_imu_instance;
     896             : };
     897             : 
     898             : namespace AP {
     899             :     AP_InertialSensor &ins();
     900             : };

Generated by: LCOV version 1.14