#pragma once12/*3This program is free software: you can redistribute it and/or modify4it under the terms of the GNU General Public License as published by5the Free Software Foundation, either version 3 of the License, or6(at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program. If not, see <http://www.gnu.org/licenses/>.15*/1617/*18* DCM based AHRS (Attitude Heading Reference System) interface for19* ArduPilot20*21*/2223#include "AP_AHRS_config.h"2425#if AP_AHRS_DCM_ENABLED2627#include "AP_AHRS_Backend.h"2829class AP_AHRS_DCM : public AP_AHRS_Backend {30public:3132AP_AHRS_DCM(AP_Float &kp_yaw,33AP_Float &kp,34AP_Float &_gps_gain,35AP_Float &_beta,36AP_Enum<GPSUse> &gps_use,37AP_Int8 &gps_minsats)38: AP_AHRS_Backend(),39_kp_yaw(kp_yaw),40_kp(kp),41gps_gain(_gps_gain),42beta(_beta),43_gps_minsats(gps_minsats),44_gps_use(gps_use)45{46_dcm_matrix.identity();47}4849/* Do not allow copies */50CLASS_NO_COPY(AP_AHRS_DCM);5152// reset the current gyro drift estimate53// should be called if gyro offsets are recalculated54void reset_gyro_drift() override;5556// Methods57void update() override;58void get_results(Estimates &results) override;59void reset() override { reset(false); }6061// return true if yaw has been initialised62bool yaw_initialised(void) const {63return have_initial_yaw;64}6566// status reporting67float get_error_rp() const {68return _error_rp;69}70float get_error_yaw() const {71return _error_yaw;72}7374// return a wind estimation vector, in m/s75bool wind_estimate(Vector3f &wind) const override {76wind = _wind;77return true;78}7980void set_external_wind_estimate(float speed, float direction);8182// return an airspeed estimate if available. return true83// if we have an estimate84bool airspeed_EAS(float &airspeed_ret) const override;8586// return an airspeed estimate if available. return true87// if we have an estimate from a specific sensor index88bool airspeed_EAS(uint8_t airspeed_index, float &airspeed_ret) const override;8990// return a ground vector estimate in meters/second, in North/East order91Vector2f groundspeed_vector() override;9293bool use_compass() override;9495void estimate_wind(void);9697// is the AHRS subsystem healthy?98bool healthy() const override;99100// returns false if we fail arming checks, in which case the buffer will be populated with a failure message101// requires_position should be true if horizontal position configuration should be checked (not used)102bool pre_arm_check(bool requires_position, char *failure_msg, uint8_t failure_msg_len) const override;103104// relative-origin functions for fallback in AP_InertialNav105bool get_origin(Location &ret) const override;106bool get_relative_position_NED_origin(Vector3p &vec) const override;107bool get_relative_position_NE_origin(Vector2p &posNE) const override;108bool get_relative_position_D_origin(postype_t &posD) const override;109110void send_ekf_status_report(class GCS_MAVLINK &link) const override;111112// return true if DCM has a yaw source113bool yaw_source_available(void) const;114115void get_control_limits(float &ekfGndSpdLimit, float &controlScaleXY) const override;116117private:118119// Get a derivative of the vertical position in m/s which is kinematically consistent with the vertical position is required by some control loops.120// This is different to the vertical velocity from the EKF which is not always consistent with the vertical position due to the various errors that are being corrected for.121bool get_vert_pos_rate_D(float &velocity) const;122123bool get_velocity_NED(Vector3f &vec) const;124125// dead-reckoning support126bool get_location(Location &loc) const;127128// settable parameters129AP_Float &_kp_yaw;130AP_Float &_kp;131AP_Float &gps_gain;132133AP_Float β134135AP_Int8 &_gps_minsats;136137AP_Enum<GPSUse> &_gps_use;138139// these are experimentally derived from the simulator140// with large drift levels141static constexpr float _ki = 0.0087f;142static constexpr float _ki_yaw = 0.01f;143144// accelerometer values in the earth frame in m/s/s145Vector3f _accel_ef;146147// Methods148void matrix_update(void);149void normalize(void);150void check_matrix(void);151bool renorm(Vector3f const &a, Vector3f &result);152void drift_correction(float deltat);153void drift_correction_yaw(void);154float yaw_error_compass(class Compass &compass);155bool have_gps(void) const;156bool use_fast_gains(void) const;157void backup_attitude(void);158159// internal reset function. Called externally, we never reset the160// DCM matrix from the eulers. Called internally we may.161void reset(bool recover_eulers);162163// airspeed_ret: will always be filled-in by get_unconstrained_airspeed_EAS which fills in airspeed_ret in this order:164// airspeed as filled-in by an enabled airspeed sensor165// if no airspeed sensor: airspeed estimated using the GPS speed & wind_speed_estimation166// Or if none of the above, fills-in using the previous airspeed estimate167// Return false: if we are using the previous airspeed estimate168bool get_unconstrained_airspeed_EAS(uint8_t airspeed_index, float &airspeed_ret) const;169170// primary representation of attitude of board used for all inertial calculations171Matrix3f _dcm_matrix;172173// primary representation of attitude of flight vehicle body174Matrix3f _body_dcm_matrix;175176// euler angles - used for recovering if the DCM177// matrix becomes ill-conditioned and watchdog storage178float roll;179float pitch;180float yaw;181182Vector3f _omega_P; // accel Omega proportional correction183Vector3f _omega_yaw_P; // proportional yaw correction184Vector3f _omega_I; // Omega Integrator correction185Vector3f _omega_I_sum;186float _omega_I_sum_time;187Vector3f _omega; // Corrected Gyro_Vector data188189bool have_initial_yaw; // true if the yaw value has been initialised with a reference190191// variables to cope with delaying the GA sum to match GPS lag192Vector3f ra_delayed(uint8_t instance, const Vector3f &ra);193Vector3f _ra_delay_buffer[INS_MAX_INSTANCES];194195// P term gain based on spin rate196float _P_gain(float spin_rate);197198// P term yaw gain based on rate of change of horiz velocity199float _yaw_gain(void) const;200201/* returns true if attitude should be corrected from GPS-derived202* velocity-deltas. We turn this off for Copter and other similar203* vehicles while the vehicle is disarmed to avoid the HUD bobbing204* around while the vehicle is disarmed.205*/206bool should_correct_centrifugal() const;207208// state to support status reporting209float _renorm_val_sum;210uint16_t _renorm_val_count;211float _error_rp{1.0f};212float _error_yaw{1.0f};213214// time in microseconds of last compass update215uint32_t _compass_last_update;216217// time in millis when we last got a GPS heading218uint32_t _gps_last_update;219220// state of accel drift correction221Vector3f _ra_sum[INS_MAX_INSTANCES];222Vector3f _last_velocity;223float _ra_deltat;224uint32_t _ra_sum_start;225226// which accelerometer instance is active227uint8_t _active_accel_instance;228229// the earths magnetic field230float _last_declination;231Vector2f _mag_earth{1, 0};232233// whether we have GPS lock234bool _have_gps_lock;235236// the lat/lng where we last had GPS lock237int32_t _last_lat;238int32_t _last_lng;239uint32_t _last_pos_ms;240241// position offset from last GPS lock242float _position_offset_north;243float _position_offset_east;244245// whether we have a position estimate246bool _have_position;247248// support for wind estimation249Vector3f _last_fuse;250Vector3f _last_vel;251uint32_t _last_wind_time;252float _last_airspeed_TAS;253uint32_t _last_consistent_heading;254255// estimated wind in m/s256Vector3f _wind;257258// last time AHRS failed in milliseconds259uint32_t _last_failure_ms;260261// time when DCM was last reset262uint32_t _last_startup_ms;263264// last origin we returned, for DCM fallback from EKF265Location last_origin;266267// Declare filter states for HPF and LPF used by complementary268// filter in AP_AHRS::groundspeed_vector269Vector2f _lp; // ground vector low-pass filter270Vector2f _hp; // ground vector high-pass filter271Vector2f _lastGndVelADS; // previous HPF input272273// pre-calculated trig cache:274float _sin_yaw;275float _cos_yaw;276277uint32_t last_log_ms;278};279280#endif // AP_AHRS_DCM_ENABLED281282283