AP_AHRS_NavEKF.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #pragma once
  2. /*
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /*
  15. * NavEKF based AHRS (Attitude Heading Reference System) interface for
  16. * ArduPilot
  17. *
  18. */
  19. #include <AP_HAL/AP_HAL.h>
  20. #define AP_AHRS_NAVEKF_AVAILABLE 1
  21. #include "AP_AHRS.h"
  22. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  23. #include <SITL/SITL.h>
  24. #endif
  25. #include <AP_NavEKF2/AP_NavEKF2.h>
  26. #include <AP_NavEKF3/AP_NavEKF3.h>
  27. #include <AP_NavEKF/AP_Nav_Common.h> // definitions shared by inertial and ekf nav filters
  28. #define AP_AHRS_NAVEKF_SETTLE_TIME_MS 20000 // time in milliseconds the ekf needs to settle after being started
  29. class AP_AHRS_NavEKF : public AP_AHRS_DCM {
  30. public:
  31. enum Flags {
  32. FLAG_NONE = 0,
  33. FLAG_ALWAYS_USE_EKF = 0x1,
  34. };
  35. // Constructor
  36. AP_AHRS_NavEKF(NavEKF2 &_EKF2, NavEKF3 &_EKF3, Flags flags = FLAG_NONE);
  37. /* Do not allow copies */
  38. AP_AHRS_NavEKF(const AP_AHRS_NavEKF &other) = delete;
  39. AP_AHRS_NavEKF &operator=(const AP_AHRS_NavEKF&) = delete;
  40. // return the smoothed gyro vector corrected for drift
  41. const Vector3f &get_gyro(void) const override;
  42. const Matrix3f &get_rotation_body_to_ned(void) const override;
  43. // return the current drift correction integrator value
  44. const Vector3f &get_gyro_drift(void) const override;
  45. // reset the current gyro drift estimate
  46. // should be called if gyro offsets are recalculated
  47. void reset_gyro_drift() override;
  48. void update(bool skip_ins_update=false) override;
  49. void reset(bool recover_eulers = false) override;
  50. // reset the current attitude, used on new IMU calibration
  51. void reset_attitude(const float &roll, const float &pitch, const float &yaw) override;
  52. // dead-reckoning support
  53. bool get_position(struct Location &loc) const override;
  54. // get latest altitude estimate above ground level in meters and validity flag
  55. bool get_hagl(float &hagl) const override;
  56. // status reporting of estimated error
  57. float get_error_rp() const override;
  58. float get_error_yaw() const override;
  59. // return a wind estimation vector, in m/s
  60. Vector3f wind_estimate() const override;
  61. // return an airspeed estimate if available. return true
  62. // if we have an estimate
  63. bool airspeed_estimate(float *airspeed_ret) const override;
  64. // true if compass is being used
  65. bool use_compass() override;
  66. // we will need to remove these to fully hide which EKF we are using
  67. NavEKF2 &get_NavEKF2(void) {
  68. return EKF2;
  69. }
  70. const NavEKF2 &get_NavEKF2_const(void) const {
  71. return EKF2;
  72. }
  73. NavEKF3 &get_NavEKF3(void) {
  74. return EKF3;
  75. }
  76. const NavEKF3 &get_NavEKF3_const(void) const {
  77. return EKF3;
  78. }
  79. // return secondary attitude solution if available, as eulers in radians
  80. bool get_secondary_attitude(Vector3f &eulers) const override;
  81. // return secondary attitude solution if available, as quaternion
  82. bool get_secondary_quaternion(Quaternion &quat) const override;
  83. // return secondary position solution if available
  84. bool get_secondary_position(struct Location &loc) const override;
  85. // EKF has a better ground speed vector estimate
  86. Vector2f groundspeed_vector() override;
  87. const Vector3f &get_accel_ef(uint8_t i) const override;
  88. const Vector3f &get_accel_ef() const override;
  89. // Retrieves the corrected NED delta velocity in use by the inertial navigation
  90. void getCorrectedDeltaVelocityNED(Vector3f& ret, float& dt) const override;
  91. // blended accelerometer values in the earth frame in m/s/s
  92. const Vector3f &get_accel_ef_blended() const override;
  93. // set the EKF's origin location in 10e7 degrees. This should only
  94. // be called when the EKF has no absolute position reference (i.e. GPS)
  95. // from which to decide the origin on its own
  96. bool set_origin(const Location &loc) override;
  97. // returns the inertial navigation origin in lat/lon/alt
  98. bool get_origin(Location &ret) const override;
  99. bool have_inertial_nav() const override;
  100. bool get_velocity_NED(Vector3f &vec) const override;
  101. // return the relative position NED to either home or origin
  102. // return true if the estimate is valid
  103. bool get_relative_position_NED_home(Vector3f &vec) const override;
  104. bool get_relative_position_NED_origin(Vector3f &vec) const override;
  105. // return the relative position NE to either home or origin
  106. // return true if the estimate is valid
  107. bool get_relative_position_NE_home(Vector2f &posNE) const override;
  108. bool get_relative_position_NE_origin(Vector2f &posNE) const override;
  109. // return the relative position down to either home or origin
  110. // baro will be used for the _home relative one if the EKF isn't
  111. void get_relative_position_D_home(float &posD) const override;
  112. bool get_relative_position_D_origin(float &posD) const override;
  113. // Get a derivative of the vertical position in m/s which is kinematically consistent with the vertical position is required by some control loops.
  114. // 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.
  115. bool get_vert_pos_rate(float &velocity) const;
  116. // write optical flow measurements to EKF
  117. void writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &rawFlowRates, const Vector2f &rawGyroRates, const uint32_t msecFlowMeas, const Vector3f &posOffset);
  118. // write body odometry measurements to the EKF
  119. void writeBodyFrameOdom(float quality, const Vector3f &delPos, const Vector3f &delAng, float delTime, uint32_t timeStamp_ms, const Vector3f &posOffset);
  120. // Write position and quaternion data from an external navigation system
  121. void writeExtNavData(const Vector3f &sensOffset, const Vector3f &pos, const Quaternion &quat, float posErr, float angErr, uint32_t timeStamp_ms, uint32_t resetTime_ms) override;
  122. // inhibit GPS usage
  123. uint8_t setInhibitGPS(void);
  124. // get speed limit
  125. void getEkfControlLimits(float &ekfGndSpdLimit, float &ekfNavVelGainScaler) const;
  126. void set_ekf_use(bool setting);
  127. // is the AHRS subsystem healthy?
  128. bool healthy() const override;
  129. bool prearm_healthy() const override;
  130. // true if the AHRS has completed initialisation
  131. bool initialised() const override;
  132. // get_filter_status - returns filter status as a series of flags
  133. bool get_filter_status(nav_filter_status &status) const;
  134. // get compass offset estimates
  135. // true if offsets are valid
  136. bool getMagOffsets(uint8_t mag_idx, Vector3f &magOffsets) const;
  137. // report any reason for why the backend is refusing to initialise
  138. const char *prearm_failure_reason(void) const override;
  139. // check all cores providing consistent attitudes for prearm checks
  140. bool attitudes_consistent(char *failure_msg, const uint8_t failure_msg_len) const override;
  141. // return the amount of yaw angle change due to the last yaw angle reset in radians
  142. // returns the time of the last yaw angle reset or 0 if no reset has ever occurred
  143. uint32_t getLastYawResetAngle(float &yawAng) const override;
  144. // return the amount of NE position change in meters due to the last reset
  145. // returns the time of the last reset or 0 if no reset has ever occurred
  146. uint32_t getLastPosNorthEastReset(Vector2f &pos) const override;
  147. // return the amount of NE velocity change in meters/sec due to the last reset
  148. // returns the time of the last reset or 0 if no reset has ever occurred
  149. uint32_t getLastVelNorthEastReset(Vector2f &vel) const override;
  150. // return the amount of vertical position change due to the last reset in meters
  151. // returns the time of the last reset or 0 if no reset has ever occurred
  152. uint32_t getLastPosDownReset(float &posDelta) const override;
  153. // Resets the baro so that it reads zero at the current height
  154. // Resets the EKF height to zero
  155. // Adjusts the EKf origin height so that the EKF height + origin height is the same as before
  156. // Returns true if the height datum reset has been performed
  157. // If using a range finder for height no reset is performed and it returns false
  158. bool resetHeightDatum() override;
  159. // send a EKF_STATUS_REPORT for current EKF
  160. void send_ekf_status_report(mavlink_channel_t chan) const;
  161. // get_hgt_ctrl_limit - get maximum height to be observed by the control loops in meters and a validity flag
  162. // this is used to limit height during optical flow navigation
  163. // it will return invalid when no limiting is required
  164. bool get_hgt_ctrl_limit(float &limit) const override;
  165. // get_location - updates the provided location with the latest
  166. // calculated location including absolute altitude
  167. // returns true on success (i.e. the EKF knows it's latest
  168. // position), false on failure
  169. bool get_location(struct Location &loc) const;
  170. // get_variances - provides the innovations normalised using the innovation variance where a value of 0
  171. // indicates perfect consistency between the measurement and the EKF solution and a value of of 1 is the maximum
  172. // inconsistency that will be accepted by the filter
  173. // boolean false is returned if variances are not available
  174. bool get_variances(float &velVar, float &posVar, float &hgtVar, Vector3f &magVar, float &tasVar, Vector2f &offset) const override;
  175. // returns the expected NED magnetic field
  176. bool get_mag_field_NED(Vector3f& ret) const;
  177. // returns the estimated magnetic field offsets in body frame
  178. bool get_mag_field_correction(Vector3f &ret) const override;
  179. void setTakeoffExpected(bool val);
  180. void setTouchdownExpected(bool val);
  181. bool getGpsGlitchStatus() const;
  182. // used by Replay to force start at right timestamp
  183. void force_ekf_start(void) { _force_ekf = true; }
  184. // is the EKF backend doing its own sensor logging?
  185. bool have_ekf_logging(void) const override;
  186. // get the index of the current primary accelerometer sensor
  187. uint8_t get_primary_accel_index(void) const override;
  188. // get the index of the current primary gyro sensor
  189. uint8_t get_primary_gyro_index(void) const override;
  190. // see if EKF lane switching is possible to avoid EKF failsafe
  191. void check_lane_switch(void) override;
  192. void Log_Write();
  193. // check whether compass can be bypassed for arming check in case when external navigation data is available
  194. bool is_ext_nav_used_for_yaw(void) const;
  195. private:
  196. enum EKF_TYPE {EKF_TYPE_NONE=0,
  197. EKF_TYPE3=3,
  198. EKF_TYPE2=2
  199. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  200. ,EKF_TYPE_SITL=10
  201. #endif
  202. };
  203. EKF_TYPE active_EKF_type(void) const;
  204. bool always_use_EKF() const {
  205. return _ekf_flags & FLAG_ALWAYS_USE_EKF;
  206. }
  207. NavEKF2 &EKF2;
  208. NavEKF3 &EKF3;
  209. bool _ekf2_started;
  210. bool _ekf3_started;
  211. bool _force_ekf;
  212. // rotation from vehicle body to NED frame
  213. Matrix3f _dcm_matrix;
  214. Vector3f _dcm_attitude;
  215. Vector3f _gyro_drift;
  216. Vector3f _gyro_estimate;
  217. Vector3f _accel_ef_ekf[INS_MAX_INSTANCES];
  218. Vector3f _accel_ef_ekf_blended;
  219. const uint16_t startup_delay_ms = 1000;
  220. uint32_t start_time_ms = 0;
  221. Flags _ekf_flags;
  222. uint8_t ekf_type(void) const;
  223. void update_DCM(bool skip_ins_update);
  224. void update_EKF2(void);
  225. void update_EKF3(void);
  226. // get the index of the current primary IMU
  227. uint8_t get_primary_IMU_index(void) const;
  228. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  229. SITL::SITL *_sitl;
  230. uint32_t _last_body_odm_update_ms = 0;
  231. void update_SITL(void);
  232. #endif
  233. };