Line data Source code
1 : /*
2 : 24 state EKF based on the derivation in https://github.com/PX4/ecl/
3 : blob/master/matlab/scripts/Inertial%20Nav%20EKF/GenerateNavFilterEquations.m
4 :
5 : Converted from Matlab to C++ by Paul Riseborough
6 :
7 : This program is free software: you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation, either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 : #pragma once
21 :
22 :
23 : #if !defined(HAL_DEBUG_BUILD) || !HAL_DEBUG_BUILD
24 : #pragma GCC optimize("O2")
25 : #endif
26 :
27 : #include "AP_NavEKF3_feature.h"
28 : #include <AP_Common/Location.h>
29 : #include <AP_Math/AP_Math.h>
30 : #include <AP_Math/vectorN.h>
31 : #include <AP_NavEKF/AP_NavEKF_core_common.h>
32 : #include <AP_NavEKF/AP_NavEKF_Source.h>
33 : #include <AP_NavEKF/EKF_Buffer.h>
34 : #include <AP_InertialSensor/AP_InertialSensor.h>
35 : #include <AP_RangeFinder/AP_RangeFinder.h>
36 :
37 : #include "AP_NavEKF/EKFGSF_yaw.h"
38 :
39 : // GPS pre-flight check bit locations
40 : #define MASK_GPS_NSATS (1<<0)
41 : #define MASK_GPS_HDOP (1<<1)
42 : #define MASK_GPS_SPD_ERR (1<<2)
43 : #define MASK_GPS_POS_ERR (1<<3)
44 : #define MASK_GPS_YAW_ERR (1<<4)
45 : #define MASK_GPS_POS_DRIFT (1<<5)
46 : #define MASK_GPS_VERT_SPD (1<<6)
47 : #define MASK_GPS_HORIZ_SPD (1<<7)
48 :
49 : #define earthRate 0.000072921f // earth rotation rate (rad/sec)
50 :
51 : // initial accel bias uncertainty as a fraction of the state limit
52 : #define ACCEL_BIAS_LIM_SCALER 0.2f
53 :
54 : // target update time for the EKF in msec and sec
55 : #define EKF_TARGET_DT_MS 12
56 : #define EKF_TARGET_DT 0.012f
57 :
58 : // mag fusion final reset altitude (using NED frame so altitude is negative)
59 : #define EKF3_MAG_FINAL_RESET_ALT 2.5f
60 : #define EKF3_MAG_FINAL_RESET_ALT_SUB 0.5f
61 :
62 : // learning rate for mag biases when using GPS yaw
63 : #define EK3_GPS_MAG_LEARN_RATE 0.005f
64 :
65 : // learning limit for mag biases when using GPS yaw (Gauss)
66 : #define EK3_GPS_MAG_LEARN_LIMIT 0.02f
67 :
68 : // maximum number of yaw resets due to detected magnetic anomaly allowed per flight
69 : #define MAG_ANOMALY_RESET_MAX 2
70 :
71 : // number of seconds a request to reset the yaw to the GSF estimate is active before it times out
72 : #define YAW_RESET_TO_GSF_TIMEOUT_MS 5000
73 :
74 : // accuracy threshold applied to GSF yaw estimate use
75 : #define GSF_YAW_ACCURACY_THRESHOLD_DEG 15.0f
76 :
77 : // number of continuous valid GSF yaw estimates required to confirm valid hostory
78 : #define GSF_YAW_VALID_HISTORY_THRESHOLD 5
79 :
80 : // minimum variances allowed for velocity and position states
81 : #define VEL_STATE_MIN_VARIANCE 1E-4
82 : #define POS_STATE_MIN_VARIANCE 1E-4
83 :
84 : // maximum number of times the vertical velocity variance can hit the lower limit before the
85 : // associated states, variances and covariances are reset
86 : #define EKF_TARGET_RATE_HZ uint32_t(1.0 / EKF_TARGET_DT)
87 : #define VERT_VEL_VAR_CLIP_COUNT_LIM (5 * EKF_TARGET_RATE_HZ)
88 :
89 : // limit on horizontal position states
90 : #if HAL_WITH_EKF_DOUBLE
91 : #define EK3_POSXY_STATE_LIMIT 50.0e6
92 : #else
93 : #define EK3_POSXY_STATE_LIMIT 1.0e6
94 : #endif
95 :
96 : // IMU acceleration process noise in m/s/s used when bad vibration affected IMU accel is detected
97 : #define BAD_IMU_DATA_ACC_P_NSE 5.0f
98 :
99 : // Number of milliseconds of bad IMU data before a reset to vertical position and velocity height sources is performed
100 : #define BAD_IMU_DATA_TIMEOUT_MS 1000
101 :
102 : // number of milliseconds the bad IMU data response settings will be held after the last bad IMU data is detected
103 : #define BAD_IMU_DATA_HOLD_MS 10000
104 :
105 : // wind state variance limits
106 : #define WIND_VEL_VARIANCE_MAX 400.0f
107 : #define WIND_VEL_VARIANCE_MIN 0.25f
108 :
109 : // maximum number of downward facing rangefinder instances available
110 : #if EK3_FEATURE_RANGEFINDER_MEASUREMENTS
111 : #if RANGEFINDER_MAX_INSTANCES > 1
112 : #define DOWNWARD_RANGEFINDER_MAX_INSTANCES 2
113 : #else
114 : #define DOWNWARD_RANGEFINDER_MAX_INSTANCES 1
115 : #endif
116 : #endif
117 :
118 : // number of continuous valid GPS velocity samples required to reset yaw
119 : #define GPS_VEL_YAW_ALIGN_COUNT_THRESHOLD 5
120 :
121 : // maximum GPs ground course uncertainty allowed for yaw alignment (deg)
122 : #define GPS_VEL_YAW_ALIGN_MAX_ANG_ERR 15.0F
123 :
124 : class NavEKF3_core : public NavEKF_core_common
125 : {
126 : public:
127 : // Constructor
128 : NavEKF3_core(class NavEKF3 *_frontend, class AP_DAL &dal);
129 :
130 : // setup this core backend
131 : bool setup_core(uint8_t _imu_index, uint8_t _core_index);
132 :
133 : // Initialise the states from accelerometer and magnetometer data (if present)
134 : // This method can only be used when the vehicle is static
135 : bool InitialiseFilterBootstrap(void);
136 :
137 : // Update Filter States - this should be called whenever new IMU data is available
138 : // The predict flag is set true when a new prediction cycle can be started
139 : void UpdateFilter(bool predict);
140 :
141 : // Check basic filter health metrics and return a consolidated health status
142 : bool healthy(void) const;
143 :
144 : // Return a consolidated error score where higher numbers are less healthy
145 : // Intended to be used by the front-end to determine which is the primary EKF
146 : float errorScore(void) const;
147 :
148 : // Write the last calculated NE position relative to the reference point (m).
149 : // If a calculated solution is not available, use the best available data and return false
150 : // If false returned, do not use for flight control
151 : bool getPosNE(Vector2p &posNE) const;
152 :
153 : // get position D from local origin
154 : bool getPosD_local(postype_t &posD) const;
155 :
156 : // Write the last calculated D position relative to the public origin
157 : // If a calculated solution is not available, use the best available data and return false
158 : // If false returned, do not use for flight control
159 : bool getPosD(postype_t &posD) const;
160 :
161 : // return NED velocity in m/s
162 : void getVelNED(Vector3f &vel) const;
163 :
164 : // return estimate of true airspeed vector in body frame in m/s
165 : // returns false if estimate is unavailable
166 : bool getAirSpdVec(Vector3f &vel) const;
167 :
168 : // return the innovation in m/s, innovation variance in (m/s)^2 and age in msec of the last TAS measurement processed
169 : // returns false if the data is unavailable
170 : bool getAirSpdHealthData(float &innovation, float &innovationVariance, uint32_t &age_ms) const;
171 :
172 : // Return the rate of change of vertical position in the down direction (dPosD/dt) in m/s
173 : // This can be different to the z component of the EKF velocity state because it will fluctuate with height errors and corrections in the EKF
174 : // but will always be kinematically consistent with the z component of the EKF position state
175 : float getPosDownDerivative(void) const;
176 :
177 : // return body axis gyro bias estimates in rad/sec
178 : void getGyroBias(Vector3f &gyroBias) const;
179 :
180 : // return accelerometer bias in m/s/s
181 : void getAccelBias(Vector3f &accelBias) const;
182 :
183 : // reset body axis gyro bias estimates
184 : void resetGyroBias(void);
185 :
186 : // Resets the baro so that it reads zero at the current height
187 : // Resets the EKF height to zero
188 : // Adjusts the EKF origin height so that the EKF height + origin height is the same as before
189 : // Returns true if the height datum reset has been performed
190 : // If using a range finder for height no reset is performed and it returns false
191 : bool resetHeightDatum(void);
192 :
193 : // return the horizontal speed limit in m/s set by optical flow sensor limits
194 : // return the scale factor to be applied to navigation velocity gains to compensate for increase in velocity noise with height when using optical flow
195 : void getEkfControlLimits(float &ekfGndSpdLimit, float &ekfNavVelGainScaler) const;
196 :
197 : // return the NED wind speed estimates in m/s (positive is air moving in the direction of the axis)
198 : // returns true if wind state estimation is active
199 : bool getWind(Vector3f &wind) const;
200 :
201 : // return earth magnetic field estimates in measurement units / 1000
202 : void getMagNED(Vector3f &magNED) const;
203 :
204 : // return body magnetic field estimates in measurement units / 1000
205 : void getMagXYZ(Vector3f &magXYZ) const;
206 :
207 : // return the index for the active sensors
208 : uint8_t getActiveAirspeed() const;
209 :
210 : // Return estimated magnetometer offsets
211 : // Return true if magnetometer offsets are valid
212 : bool getMagOffsets(uint8_t mag_idx, Vector3f &magOffsets) const;
213 :
214 : // Return the last calculated latitude, longitude and height in WGS-84
215 : // If a calculated location isn't available and position source is GPS, return a raw GPS measurement
216 : // The status will return true if a calculation or raw measurement is available
217 : // The getFilterStatus() function provides a more detailed description of data health and must be checked if data is to be used for flight control
218 : bool getLLH(Location &loc) const;
219 :
220 : // return the latitude and longitude and height used to set the NED origin
221 : // All NED positions calculated by the filter are relative to this location
222 : // Returns false if the origin has not been set
223 : bool getOriginLLH(Location &loc) const;
224 :
225 : // set the latitude and longitude and height used to set the NED origin
226 : // All NED positions calculated by the filter will be relative to this location
227 : // returns false if the origin has already been set
228 : bool setOriginLLH(const Location &loc);
229 :
230 : // Set the EKF's NE horizontal position states and their corresponding variances from a supplied WGS-84 location and uncertainty
231 : // The altitude element of the location is not used.
232 : // Returns true if the set was successful
233 : bool setLatLng(const Location &loc, float posAccuracy, uint32_t timestamp_ms);
234 :
235 : // Popoluates the WMM data structure with the field at the given location
236 : void setEarthFieldFromLocation(const Location &loc);
237 :
238 : // return estimated height above ground level
239 : // return false if ground height is not being estimated.
240 : bool getHAGL(float &HAGL) const;
241 :
242 : // return the Euler roll, pitch and yaw angle in radians
243 : void getEulerAngles(Vector3f &eulers) const;
244 :
245 : // return the transformation matrix from XYZ (body) to NED axes
246 : void getRotationBodyToNED(Matrix3f &mat) const;
247 :
248 : // return the quaternions defining the rotation from NED to XYZ (body) axes
249 : void getQuaternion(Quaternion &quat) const;
250 :
251 : // return the innovations for the NED Pos, NED Vel, XYZ Mag and Vtas measurements
252 : bool getInnovations(Vector3f &velInnov, Vector3f &posInnov, Vector3f &magInnov, float &tasInnov, float &yawInnov) const;
253 :
254 : // return the synthetic air data drag and sideslip innovations
255 : void getSynthAirDataInnovations(Vector2f &dragInnov, float &betaInnov) const;
256 :
257 : // return the innovation consistency test ratios for the velocity, position, magnetometer and true airspeed measurements
258 : bool getVariances(float &velVar, float &posVar, float &hgtVar, Vector3f &magVar, float &tasVar, Vector2f &offset) const;
259 :
260 : // return 1-sigma position and velocity uncertainty derived from the EKF state error covariance matrix P
261 : // pos_horiz_m: 2D RMS horizontal position uncertainty (m)
262 : // pos_vert_m: 1-sigma vertical position uncertainty (m)
263 : // vel_m_s: 1-sigma worst-case NED velocity uncertainty (m/s)
264 : // returns false if EKF is not yet initialised
265 : bool getPosVelUncertainty(float &pos_horiz_m, float &pos_vert_m, float &vel_m_s) const;
266 :
267 : // get a particular source's velocity innovations
268 : // returns true on success and results are placed in innovations and variances arguments
269 : bool getVelInnovationsAndVariancesForSource(AP_NavEKF_Source::SourceXY source, Vector3f &innovations, Vector3f &variances) const WARN_IF_UNUSED;
270 :
271 : // should we use the compass? This is public so it can be used for
272 : // reporting via ahrs.use_compass()
273 : bool use_compass(void) const;
274 :
275 : // write the raw optical flow measurements
276 : // rawFlowQuality is a measured of quality between 0 and 255, with 255 being the best quality
277 : // rawFlowRates are the optical flow rates in rad/sec about the X and Y sensor axes.
278 : // rawGyroRates are the sensor rotation rates in rad/sec measured by the sensors internal gyro
279 : // The sign convention is that a RH physical rotation of the sensor about an axis produces both a positive flow and gyro rate
280 : // msecFlowMeas is the scheduler time in msec when the optical flow data was received from the sensor.
281 : // posOffset is the XYZ flow sensor position in the body frame in m
282 : // heightOverride is the fixed height of the sensor above ground in m, when on rover vehicles. 0 if not used
283 : void writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &rawFlowRates, const Vector2f &rawGyroRates, const uint32_t msecFlowMeas, const Vector3f &posOffset, float heightOverride);
284 :
285 : // retrieve latest corrected optical flow samples (used for calibration)
286 : bool getOptFlowSample(uint32_t& timeStamp_ms, Vector2f& flowRate, Vector2f& bodyRate, Vector2f& losPred) const;
287 :
288 : /*
289 : * Write body frame linear and angular displacement measurements from a visual odometry sensor
290 : *
291 : * quality is a normalised confidence value from 0 to 100
292 : * delPos is the XYZ change in linear position measured in body frame and relative to the inertial reference at time_ms (m)
293 : * delAng is the XYZ angular rotation measured in body frame and relative to the inertial reference at time_ms (rad)
294 : * delTime is the time interval for the measurement of delPos and delAng (sec)
295 : * timeStamp_ms is the timestamp of the last image used to calculate delPos and delAng (msec)
296 : * delay_ms is the average delay of external nav system measurements relative to inertial measurements
297 : * posOffset is the XYZ body frame position of the camera focal point (m)
298 : */
299 : void writeBodyFrameOdom(float quality, const Vector3f &delPos, const Vector3f &delAng, float delTime, uint32_t timeStamp_ms, uint16_t delay_ms, const Vector3f &posOffset);
300 :
301 : /*
302 : * Write odometry data from a wheel encoder. The axis of rotation is assumed to be parallel to the vehicle body axis
303 : *
304 : * delAng is the measured change in angular position from the previous measurement where a positive rotation is produced by forward motion of the vehicle (rad)
305 : * delTime is the time interval for the measurement of delAng (sec)
306 : * timeStamp_ms is the time when the rotation was last measured (msec)
307 : * posOffset is the XYZ body frame position of the wheel hub (m)
308 : * radius is the effective rolling radius of the wheel (m)
309 : */
310 : void writeWheelOdom(float delAng, float delTime, uint32_t timeStamp_ms, const Vector3f &posOffset, float radius);
311 :
312 : /*
313 : * Return data for debugging body frame odometry fusion:
314 : *
315 : * velInnov are the XYZ body frame velocity innovations (m/s)
316 : * velInnovVar are the XYZ body frame velocity innovation variances (m/s)**2
317 : *
318 : * Return the time stamp of the last odometry fusion update (msec)
319 : */
320 : uint32_t getBodyFrameOdomDebug(Vector3f &velInnov, Vector3f &velInnovVar);
321 :
322 : /*
323 : * Writes the measurement from a yaw angle sensor
324 : *
325 : * yawAngle: Yaw angle of the vehicle relative to true north in radians where a positive angle is
326 : * produced by a RH rotation about the Z body axis. The Yaw rotation is the first rotation in a
327 : * 321 (ZYX) or a 312 (ZXY) rotation sequence as specified by the 'type' argument.
328 : * yawAngleErr is the 1SD accuracy of the yaw angle measurement in radians.
329 : * timeStamp_ms: System time in msec when the yaw measurement was taken. This time stamp must include
330 : * all measurement lag and transmission delays.
331 : * type: An integer specifying Euler rotation order used to define the yaw angle.
332 : * type = 1 specifies a 312 (ZXY) rotation order, type = 2 specifies a 321 (ZYX) rotation order.
333 : * antOffset: body-frame antenna offset the yaw angle was calculated from assuming the vehicle was
334 : * level, zero (the default) when the measurement does not require attitude correction (m)
335 : */
336 : void writeEulerYawAngle(float yawAngle, float yawAngleErr, uint32_t timeStamp_ms, uint8_t type, const Vector3f &antOffset=Vector3f());
337 :
338 : /*
339 : * Write position and quaternion data from an external navigation system
340 : *
341 : * pos : position in the RH navigation frame. Frame is assumed to be NED if frameIsNED is true. (m)
342 : * quat : quaternion desribing the rotation from navigation frame to body frame
343 : * posErr : 1-sigma spherical position error (m)
344 : * angErr : 1-sigma spherical angle error (rad)
345 : * timeStamp_ms : system time the measurement was taken, not the time it was received (mSec)
346 : * delay_ms : average delay of external nav system measurements relative to inertial measurements
347 : * resetTime_ms : system time of the last position reset request (mSec)
348 : *
349 : */
350 : void writeExtNavData(const Vector3f &pos, const Quaternion &quat, float posErr, float angErr, uint32_t timeStamp_ms, uint16_t delay_ms, uint32_t resetTime_ms);
351 :
352 : /*
353 : * Write velocity data from an external navigation system
354 : *
355 : * vel : velocity in NED (m)
356 : * err : velocity error (m/s)
357 : * timeStamp_ms : system time the measurement was taken, not the time it was received (mSec)
358 : * delay_ms : average delay of external nav system measurements relative to inertial measurements
359 : */
360 : void writeExtNavVelData(const Vector3f &vel, float err, uint32_t timeStamp_ms, uint16_t delay_ms);
361 :
362 : /*
363 : * Write terrain altitude (derived from SRTM) in meters above the origin
364 : * only used by optical flow when out of rangefinder range
365 : */
366 : #if EK3_FEATURE_OPTFLOW_SRTM
367 : void writeTerrainData(float alt_m);
368 : #endif
369 :
370 : // Set to true if the terrain underneath is stable enough to be used as a height reference
371 : // in combination with a range finder. Set to false if the terrain underneath the vehicle
372 : // cannot be used as a height reference. Use to prevent range finder operation otherwise
373 : // enabled by the combination of EK3_RNG_USE_HGT and EK3_RNG_USE_SPD parameters.
374 : void setTerrainHgtStable(bool val);
375 :
376 : /*
377 : return the filter fault status as a bitmasked integer
378 : 0 = quaternions are NaN
379 : 1 = velocities are NaN
380 : 2 = badly conditioned X magnetometer fusion
381 : 3 = badly conditioned Y magnetometer fusion
382 : 5 = badly conditioned Z magnetometer fusion
383 : 6 = badly conditioned airspeed fusion
384 : 7 = badly conditioned synthetic sideslip fusion
385 : 7 = filter is not initialised
386 : */
387 : void getFilterFaults(uint16_t &faults) const;
388 :
389 : /*
390 : Return a filter function status that indicates:
391 : Which outputs are valid
392 : If the filter has detected takeoff
393 : If the filter has activated the mode that mitigates against ground effect static pressure errors
394 : If GPS data is being used
395 : */
396 : void getFilterStatus(nav_filter_status &status) const;
397 :
398 : // return a terrain altitude variance
399 : bool getTerrainAltVariance(float &terrain_alt_variance) const;
400 :
401 : // provides the height limit to be observed by the control loops
402 : // returns false if no height limiting is required
403 : // this is needed to ensure the vehicle does not fly too high when using optical flow navigation
404 : bool getHeightControlLimit(float &height) const;
405 :
406 : // return the number of yaw resets performed by this core
407 39298429 : uint16_t getYawResetCount(void) const { return yawResetCount; }
408 :
409 : // return the number of NE position resets performed by this core
410 39298429 : uint16_t getPosNorthEastResetCount(void) const { return posNEResetCount; }
411 :
412 : // return the number of D position resets performed by this core
413 39298429 : uint16_t getPosDownResetCount(void) const { return posDResetCount; }
414 :
415 : // report any reason for why the backend is refusing to initialise
416 : const char *prearm_failure_reason(void) const;
417 :
418 : // report the number of frames lapsed since the last state prediction
419 : // this is used by other instances to level load
420 : uint8_t getFramesSincePredict(void) const;
421 :
422 : // get the IMU index. For now we return the gyro index, as that is most
423 : // critical for use by other subsystems.
424 80106038 : uint8_t getIMUIndex(void) const { return gyro_index_active; }
425 :
426 : // values for EK3_MAG_CAL
427 : enum class MagCal {
428 : WHEN_FLYING = 0,
429 : WHEN_MANOEUVRING = 1,
430 : NEVER = 2,
431 : AFTER_FIRST_CLIMB = 3,
432 : ALWAYS = 4,
433 : // 5 was EXTERNAL_YAW (do not use)
434 : // 6 was EXTERNAL_YAW_FALLBACK (do not use)
435 : GROUND_AND_INFLIGHT = 7,
436 : };
437 :
438 : // magnetometer fusion selections
439 : enum class MagFuseSel {
440 : NOT_FUSING = 0,
441 : FUSE_YAW = 1,
442 : FUSE_MAG = 2,
443 : FUSE_MAG_ANCHORED = 3
444 : };
445 :
446 : // are we using (aka fusing) a non-compass yaw?
447 : bool using_noncompass_for_yaw(void) const;
448 :
449 : // are we using (aka fusing) external nav for yaw?
450 : bool using_extnav_for_yaw() const;
451 :
452 : // are we using a gps?
453 : bool using_gps() const;
454 :
455 : // Writes the default equivalent airspeed and 1-sigma uncertainty in m/s to be used in forward flight if a measured airspeed is required and not available.
456 : void writeDefaultAirSpeed(float airspeed, float uncertainty);
457 :
458 : // request a reset the yaw to the EKF-GSF value
459 : void EKFGSF_requestYawReset();
460 :
461 : // return true if we are tilt aligned
462 53084008 : bool have_aligned_tilt(void) const {
463 53084008 : return tiltAlignComplete;
464 : }
465 :
466 : // return true if we are yaw aligned
467 53209147 : bool have_aligned_yaw(void) const {
468 53209147 : return yawAlignComplete;
469 : }
470 :
471 : void Log_Write(uint64_t time_us);
472 :
473 : // returns true when the state estimates are significantly degraded by vibration
474 40053019 : bool isVibrationAffected() const { return badIMUdata; }
475 :
476 : // get a yaw estimator instance
477 479 : const EKFGSF_yaw *get_yawEstimator(void) const { return yawEstimator; }
478 :
479 : // per-core pre-arm checks. returns false if we fail arming
480 : // checks, in which case the buffer will be populated with a
481 : // failure message
482 : // requires_position should be true if horizontal position configuration should be checked
483 : bool pre_arm_check(bool requires_position, char *failure_msg, uint8_t failure_msg_len) const;
484 :
485 : // clear the statesInitialised status which allows a reset and bootstrap alignment
486 2 : void clearStatesInitialised(void) { statesInitialised = false; }
487 :
488 : // return true if states have been initialised by a bootstrap alignment
489 2 : bool isStatesInitialised(void) const { return statesInitialised; }
490 :
491 : private:
492 : EKFGSF_yaw *yawEstimator;
493 : AP_DAL &dal;
494 :
495 : // Reference to the global EKF frontend for parameters
496 : class NavEKF3 *frontend;
497 : uint8_t imu_index; // preferred IMU index
498 : uint8_t gyro_index_active; // active gyro index (in case preferred fails)
499 : uint8_t accel_index_active; // active accel index (in case preferred fails)
500 : uint8_t core_index;
501 : uint8_t imu_buffer_length;
502 : uint8_t obs_buffer_length;
503 :
504 : #if MATH_CHECK_INDEXES
505 : class Vector9 : public VectorN<ftype, 9> {
506 : public:
507 : Vector9(ftype p0, ftype p1, ftype p2,
508 : ftype p3, ftype p4, ftype p5,
509 : ftype p6, ftype p7, ftype p8) {
510 : _v[0] = p0; _v[1] = p1; _v[2] = p2;
511 : _v[3] = p3; _v[4] = p4; _v[5] = p5;
512 : _v[6] = p6; _v[7] = p7; _v[8] = p8;
513 : }
514 : };
515 : class Vector5 : public VectorN<ftype, 5> {
516 : public:
517 : Vector5(ftype p0, ftype p1, ftype p2,
518 : ftype p3, ftype p4) {
519 : _v[0] = p0; _v[1] = p1; _v[2] = p2;
520 : _v[3] = p3; _v[4] = p4;
521 : }
522 : };
523 :
524 : typedef VectorN<ftype,2> Vector2;
525 : typedef VectorN<ftype,3> Vector3;
526 : typedef VectorN<ftype,4> Vector4;
527 : typedef VectorN<ftype,6> Vector6;
528 : typedef VectorN<ftype,7> Vector7;
529 : typedef VectorN<ftype,8> Vector8;
530 : typedef VectorN<ftype,10> Vector10;
531 : typedef VectorN<ftype,11> Vector11;
532 : typedef VectorN<ftype,13> Vector13;
533 : typedef VectorN<ftype,14> Vector14;
534 : typedef VectorN<ftype,15> Vector15;
535 : typedef VectorN<ftype,21> Vector21;
536 : typedef VectorN<ftype,22> Vector22;
537 : typedef VectorN<ftype,23> Vector23;
538 : typedef VectorN<ftype,24> Vector24;
539 : typedef VectorN<ftype,25> Vector25;
540 : typedef VectorN<ftype,31> Vector31;
541 : typedef VectorN<VectorN<ftype,3>,3> Matrix3;
542 : typedef VectorN<VectorN<ftype,24>,24> Matrix24;
543 : typedef VectorN<VectorN<ftype,34>,50> Matrix34_50;
544 : typedef VectorN<uint32_t,50> Vector_u32_50;
545 : #else
546 : typedef ftype Vector2[2];
547 : typedef ftype Vector3[3];
548 : typedef ftype Vector4[4];
549 : typedef ftype Vector5[5];
550 : typedef ftype Vector6[6];
551 : typedef ftype Vector7[7];
552 : typedef ftype Vector8[8];
553 : typedef ftype Vector9[9];
554 : typedef ftype Vector10[10];
555 : typedef ftype Vector11[11];
556 : typedef ftype Vector13[13];
557 : typedef ftype Vector14[14];
558 : typedef ftype Vector15[15];
559 : typedef ftype Vector21[21];
560 : typedef ftype Vector22[22];
561 : typedef ftype Vector23[23];
562 : typedef ftype Vector24[24];
563 : typedef ftype Vector25[25];
564 : typedef ftype Matrix3[3][3];
565 : typedef ftype Matrix24[24][24];
566 : typedef ftype Matrix34_50[34][50];
567 : typedef uint32_t Vector_u32_50[50];
568 : #endif
569 :
570 : // the states are available in two forms, either as a Vector24, or
571 : // broken down as individual elements. Both are equivalent (same
572 : // memory)
573 : struct state_elements {
574 : QuaternionF quat; // quaternion defining rotation from local NED earth frame to body frame 0..3
575 : Vector3F velocity; // velocity of IMU in local NED earth frame (m/sec) 4..6
576 : Vector3F position; // position of IMU in local NED earth frame (m) 7..9
577 : Vector3F gyro_bias; // body frame delta angle IMU bias vector (rad) 10..12
578 : Vector3F accel_bias; // body frame delta velocity IMU bias vector (m/sec) 13..15
579 : Vector3F earth_magfield; // earth frame magnetic field vector (Gauss) 16..18
580 : Vector3F body_magfield; // body frame magnetic field vector (Gauss) 19..21
581 : Vector2F wind_vel; // horizontal North East wind velocity vector in local NED earth frame (m/sec) 22..23
582 : };
583 :
584 : union {
585 : Vector24 statesArray;
586 : struct state_elements stateStruct;
587 : };
588 :
589 : struct output_elements {
590 : QuaternionF quat; // quaternion defining rotation from local NED earth frame to body frame
591 : Vector3F velocity; // velocity of body frame origin in local NED earth frame (m/sec)
592 : Vector3F position; // position of body frame origin in local NED earth frame (m)
593 : };
594 :
595 : struct imu_elements {
596 : Vector3F delAng; // IMU delta angle measurements in body frame (rad)
597 : Vector3F delVel; // IMU delta velocity measurements in body frame (m/sec)
598 : ftype delAngDT; // time interval over which delAng has been measured (sec)
599 : ftype delVelDT; // time interval over which delVelDT has been measured (sec)
600 : uint32_t time_ms; // measurement timestamp (msec)
601 : uint8_t gyro_index;
602 : uint8_t accel_index;
603 : };
604 :
605 : struct gps_elements : EKF_obs_element_t {
606 : int32_t lat, lng; // latitude and longitude in 1e7 degrees
607 : ftype hgt; // height of the GPS antenna in local NED earth frame (m)
608 : Vector3F vel; // velocity of the GPS antenna in local NED earth frame (m/sec)
609 : uint8_t sensor_idx; // unique integer identifying the GPS sensor
610 : bool corrected; // true when the position and velocity have been corrected for sensor position
611 : bool have_vz; // true when vertical velocity is valid
612 : };
613 :
614 : struct mag_elements : EKF_obs_element_t {
615 : Vector3F mag; // body frame magnetic field measurements (Gauss)
616 : };
617 :
618 : struct baro_elements : EKF_obs_element_t {
619 : ftype hgt; // height of the pressure sensor in local NED earth frame (m)
620 : };
621 :
622 : struct range_elements : EKF_obs_element_t {
623 : ftype rng; // distance measured by the range sensor (m)
624 : uint8_t sensor_idx; // integer either 0 or 1 uniquely identifying up to two range sensors
625 : };
626 :
627 : struct rng_bcn_elements : EKF_obs_element_t {
628 : ftype rng; // range measurement to each beacon (m)
629 : Vector3F beacon_posNED; // NED position of the beacon (m)
630 : ftype rngErr; // range measurement error 1-std (m)
631 : uint8_t beacon_ID; // beacon identification number
632 : };
633 :
634 : struct tas_elements : EKF_obs_element_t {
635 : ftype tas; // true airspeed measurement (m/sec)
636 : ftype tasVariance; // variance of true airspeed measurement (m/sec)^2
637 : bool allowFusion; // true if measurement can be allowed to modify EKF states.
638 : };
639 :
640 : struct of_elements : EKF_obs_element_t {
641 : Vector2F flowRadXY; // raw (non motion compensated) optical flow angular rates about the XY body axes (rad/sec)
642 : Vector2F flowRadXYcomp; // motion compensated XY optical flow angular rates about the XY body axes (rad/sec)
643 : Vector3F bodyRadXYZ; // body frame XYZ axis angular rates averaged across the optical flow measurement interval (rad/sec)
644 : Vector3F body_offset; // XYZ position of the optical flow sensor in body frame (m)
645 : float heightOverride; // The fixed height of the sensor above ground in m, when on rover vehicles. 0 if not used
646 : };
647 :
648 : struct vel_odm_elements : EKF_obs_element_t {
649 : Vector3F vel; // XYZ velocity measured in body frame (m/s)
650 : ftype velErr; // velocity measurement error 1-std (m/s)
651 : Vector3F body_offset;// XYZ position of the velocity sensor in body frame (m)
652 : Vector3F angRate; // angular rate estimated from odometry (rad/sec)
653 : };
654 :
655 : struct wheel_odm_elements : EKF_obs_element_t {
656 : ftype delAng; // wheel rotation angle measured in body frame - positive is forward movement of vehicle (rad/s)
657 : ftype radius; // wheel radius (m)
658 : Vector3F hub_offset; // XYZ position of the wheel hub in body frame (m)
659 : ftype delTime; // time interval that the measurement was accumulated over (sec)
660 : };
661 :
662 : // Specifies the rotation order used for the Tait-Bryan or Euler angles where alternative rotation orders are available
663 : enum class rotationOrder {
664 : TAIT_BRYAN_321=0,
665 : TAIT_BRYAN_312=1
666 : };
667 :
668 : struct yaw_elements : EKF_obs_element_t {
669 : ftype yawAng; // yaw angle measurement (rad)
670 : ftype yawAngErr; // yaw angle 1SD measurement accuracy (rad)
671 : rotationOrder order; // type specifiying Euler rotation order used, 0 = 321 (ZYX), 1 = 312 (ZXY)
672 : #if EK3_FEATURE_MOVING_BASELINE
673 : Vector3F antOffset; // body-frame antenna offset the yaw measurement was calculated from assuming the
674 : // vehicle was level, zero when the measurement does not require attitude correction (m)
675 : #endif
676 : };
677 :
678 : struct ext_nav_elements : EKF_obs_element_t {
679 : Vector3F pos; // XYZ position measured in a RH navigation frame (m)
680 : ftype posErr; // spherical position measurement error 1-std (m)
681 : bool posReset; // true when the position measurement has been reset
682 : bool corrected; // true when the position has been corrected for sensor position
683 : };
684 :
685 : struct ext_nav_vel_elements : EKF_obs_element_t {
686 : Vector3F vel; // velocity in NED (m/s)
687 : ftype err; // velocity measurement error (m/s)
688 : bool corrected; // true when the velocity has been corrected for sensor position
689 : };
690 :
691 : struct drag_elements : EKF_obs_element_t {
692 : Vector2f accelXY; // measured specific force along the X and Y body axes (m/sec**2)
693 : };
694 :
695 : // bias estimates for the IMUs that are enabled but not being used
696 : // by this core.
697 : struct {
698 : Vector3F gyro_bias;
699 : Vector3F accel_bias;
700 : } inactiveBias[INS_MAX_INSTANCES];
701 :
702 : // Specify source of data to be used for a partial state reset
703 : // Checking the availability and quality of the data source specified is the responsibility of the caller
704 : enum class resetDataSource {
705 : DEFAULT=0, // Use data source selected by reset function internal rules
706 : GPS=1, // Use GPS
707 : RNGBCN=2, // Use beacon range data
708 : FLOW=3, // Use optical flow rates
709 : BARO=4, // Use Baro height
710 : MAG=5, // Use magnetometer data
711 : RNGFND=6, // Use rangefinder data
712 : EXTNAV=7 // Use external nav data
713 : };
714 :
715 : // specifies the method to be used when fusing yaw observations
716 : enum class yawFusionMethod {
717 : MAGNETOMETER=0,
718 : GPS=1,
719 : GSF=2,
720 : STATIC=3,
721 : PREDICTED=4,
722 : EXTNAV=5,
723 : };
724 :
725 : // update the navigation filter status
726 : void updateFilterStatus(void);
727 :
728 : // update the quaternion, velocity and position states using IMU measurements
729 : void UpdateStrapdownEquationsNED();
730 :
731 : // calculate the predicted state covariance matrix
732 : // Argument rotVarVecPtr is pointer to a vector defining the earth frame uncertainty variance of the quaternion states
733 : // used to perform a reset of the quaternion state covariances only. Set to null for normal operation.
734 : void CovariancePrediction(Vector3F *rotVarVecPtr);
735 :
736 : // constrain variances (diagonal terms) in the state covariance matrix
737 : void ConstrainVariances();
738 :
739 : // actually do fusion to update statesArray from Kfusion and P from KHP.
740 : // returns true and skips fusion if variances would be driven negative.
741 : // force skips this negative check; passing true is probably a bug!
742 : bool FinishFusion(ftype innov, bool force = false);
743 :
744 : // constrain states
745 : void ConstrainStates();
746 :
747 : // constrain earth field using WMM tables
748 : void MagTableConstrain(void);
749 :
750 : // fuse selected position, velocity and height measurements
751 : void FuseVelPosNED();
752 :
753 : // fuse body frame velocity measurements
754 : void FuseBodyVel();
755 :
756 : #if EK3_FEATURE_BEACON_FUSION
757 : // fuse range beacon measurements
758 : void FuseRngBcn();
759 : #endif
760 :
761 : // use range beacon measurements to calculate a static position
762 : void FuseRngBcnStatic();
763 :
764 : // calculate the offset from EKF vertical position datum to the range beacon system datum
765 : void CalcRangeBeaconPosDownOffset(ftype obsVar, Vector3F &vehiclePosNED, bool aligning);
766 :
767 : // fuse magnetometer measurements
768 : void FuseMagnetometer();
769 :
770 : // fuse true airspeed measurements
771 : void FuseAirspeed();
772 :
773 : // fuse synthetic sideslip measurement of zero
774 : void FuseSideslip();
775 :
776 : // zero specified state variances and covariances in state covariance matrix
777 : void zeroStatesVarCov(uint8_t first, uint8_t last);
778 :
779 : // Reset the stored output history to current data
780 : void StoreOutputReset(void);
781 :
782 : // Reset the stored output quaternion history to current EKF state
783 : void StoreQuatReset(void);
784 :
785 : // Rotate the stored output quaternion history through a quaternion rotation
786 : void StoreQuatRotate(const QuaternionF &deltaQuat);
787 :
788 : // calculate the NED earth spin vector in rad/sec
789 : void calcEarthRateNED(Vector3F &omega, int32_t latitude) const;
790 :
791 : // initialise the covariance matrix
792 : void CovarianceInit();
793 :
794 : // helper functions for readIMUData
795 : bool readDeltaVelocity(uint8_t ins_index, Vector3F &dVel, ftype &dVel_dt);
796 : bool readDeltaAngle(uint8_t ins_index, Vector3F &dAng, ftype &dAng_dt);
797 :
798 : // helper functions for correcting IMU data
799 : void correctDeltaAngle(Vector3F &delAng, ftype delAngDT, uint8_t gyro_index);
800 : void correctDeltaVelocity(Vector3F &delVel, ftype delVelDT, uint8_t accel_index);
801 :
802 : // update IMU delta angle and delta velocity measurements
803 : void readIMUData(bool startPredictEnabled);
804 :
805 : // update estimate of inactive bias states
806 : void learnInactiveBiases();
807 :
808 : // check for new valid GPS data and update stored measurement if available
809 : void readGpsData();
810 :
811 : // check for new valid GPS yaw data
812 : void readGpsYawData();
813 :
814 : // check for new altitude measurement data and update stored measurement if available
815 : void readBaroData();
816 :
817 : // check for new magnetometer data and update store measurements if available
818 : void readMagData();
819 :
820 : // try changing compasses on compass failure or timeout
821 : void tryChangeCompass(void);
822 :
823 : // try changing to a specific compass index
824 : void tryChangeCompass(uint8_t compass_index);
825 :
826 : // check for new airspeed data and update stored measurements if available
827 : void readAirSpdData();
828 :
829 : #if EK3_FEATURE_BEACON_FUSION
830 : // check for new range beacon data and update stored measurements if available
831 : void readRngBcnData();
832 : #endif
833 :
834 : // determine when to perform fusion of GPS position and velocity measurements
835 : void SelectVelPosFusion();
836 :
837 : #if EK3_FEATURE_BEACON_FUSION
838 : // determine when to perform fusion of range measurements take relative to a beacon at a known NED position
839 : void SelectRngBcnFusion();
840 : #endif
841 :
842 : // determine when to perform fusion of magnetometer measurements
843 : void SelectMagFusion();
844 :
845 : // determine when to perform fusion of true airspeed measurements
846 : void SelectTasFusion();
847 :
848 : // determine when to perform fusion of drag or synthetic sideslip measurements
849 : void SelectBetaDragFusion();
850 :
851 : // force alignment of the yaw angle using GPS velocity data
852 : void realignYawGPS(bool emergency_reset);
853 :
854 : // initialise the earth magnetic field states using declination and current attitude and magnetometer measurements
855 :
856 : // align the yaw angle for the quaternion states to the given yaw angle which should be at the fusion horizon
857 : void alignYawAngle(const yaw_elements &yawAngData);
858 :
859 : // build the body-to-earth rotation matrix at the current state attitude with yaw
860 : // set to zero, using the given Euler rotation order. Optionally returns the yaw
861 : // angle removed. Returns false if the rotation order is not supported
862 : bool buildTbnZeroYaw(rotationOrder order, Matrix3F &Tbn, ftype *yawAng=nullptr) const;
863 :
864 : #if EK3_FEATURE_MOVING_BASELINE
865 : // correct a yaw measurement calculated from a moving baseline antenna offset for
866 : // vehicle attitude using this core's attitude estimate at the fusion time horizon,
867 : // inflating yawAngErr by the attitude uncertainty the correction introduces.
868 : // returns false when the baseline is too close to vertical at the estimated
869 : // attitude for the measurement to contain usable yaw information, or when the
870 : // rotation order is not supported
871 : bool correctGPSYawForAntennaOffset(yaw_elements &yawAngData) const;
872 : #endif // EK3_FEATURE_MOVING_BASELINE
873 :
874 : // update mag field states and associated variances using magnetomer and declination data
875 : void resetMagFieldStates();
876 :
877 : // reset yaw based on magnetic field sample
878 : void setYawFromMag();
879 :
880 : // zero stored variables
881 : void InitialiseVariables();
882 :
883 : // zero stored variables related to mag
884 : void InitialiseVariablesMag();
885 :
886 : // reset the horizontal position states uing the last GPS measurement
887 : void ResetPosition(resetDataSource posResetSource);
888 :
889 : // reset the stateStruct's NE position to the specified position
890 : void ResetPositionNE(ftype posN, ftype posE);
891 :
892 : // reset the stateStruct's D position
893 : void ResetPositionD(ftype posD);
894 :
895 : // reset velocity states using the last GPS measurement
896 : void ResetVelocity(resetDataSource velResetSource);
897 :
898 : // reset the vertical position state using the last height measurement
899 : void ResetHeight(void);
900 :
901 : // return true if we should use the airspeed sensor
902 : bool useAirspeed(void) const;
903 :
904 : // return true if the vehicle code has requested the filter to be ready for flight
905 : bool readyToUseGPS(void) const;
906 :
907 : // return true if the filter to be ready to use the beacon range measurements
908 : bool readyToUseRangeBeacon(void) const;
909 :
910 : // Check for filter divergence
911 : void checkDivergence(void);
912 :
913 : // Calculate weighting that is applied to IMU1 accel data to blend data from IMU's 1 and 2
914 : void calcIMU_Weighting(ftype K1, ftype K2);
915 :
916 : #if EK3_FEATURE_OPTFLOW_FUSION
917 : // return true if the filter is ready to start using optical flow measurements for position and velocity estimation
918 : bool readyToUseOptFlow(void) const;
919 : #endif
920 :
921 : // return true if the filter is ready to start using body frame odometry measurements
922 : bool readyToUseBodyOdm(void) const;
923 :
924 : // return true if the filter to be ready to use external nav data
925 : bool readyToUseExtNav(void) const;
926 :
927 : // return true if we should use the range finder sensor
928 : bool useRngFinder(void) const;
929 :
930 : #if EK3_FEATURE_OPTFLOW_FUSION
931 : // determine when to perform fusion of optical flow measurements
932 : void SelectFlowFusion();
933 : #endif
934 :
935 : // determine when to perform fusion of body frame odometry measurements
936 : void SelectBodyOdomFusion();
937 :
938 : // Estimate terrain offset using a single state EKF
939 : void EstimateTerrainOffset(const of_elements &ofDataDelayed);
940 :
941 : #if EK3_FEATURE_OPTFLOW_AGL_KF
942 : // Update the 2-state IMU-aided AGL Kalman filter (height + vertical velocity above ground)
943 : void UpdateAglKf();
944 : #endif
945 :
946 : #if EK3_FEATURE_OPTFLOW_FUSION
947 : // fuse optical flow measurements into the main filter
948 : // really_fuse should be true to actually fuse into the main filter, false to only calculate variances
949 : void FuseOptFlow(const of_elements &ofDataDelayed, bool really_fuse);
950 : #endif
951 :
952 : // Control filter mode changes
953 : void controlFilterModes();
954 :
955 : // Determine if we are flying or on the ground
956 : void detectFlight();
957 :
958 : // set the default yaw source
959 : void setYawSource();
960 :
961 : // Set inertial navigation aiding mode
962 : void setAidingMode();
963 :
964 : // Determine if learning of wind and magnetic field will be enabled and set corresponding indexing limits to
965 : // avoid unnecessary operations
966 : void setWindMagStateLearningMode();
967 :
968 : // Check the alignmnent status of the tilt attitude
969 : // Used during initial bootstrap alignment of the filter
970 : void checkAttitudeAlignmentStatus();
971 :
972 : // Control reset of yaw and magnetic field states
973 : void controlMagYawReset();
974 :
975 : // Assess GPS data quality and set gpsGoodToAlign
976 : void calcGpsGoodToAlign(void);
977 :
978 : // set the class variable true if the delta angle bias variances are sufficiently small
979 : void checkGyroCalStatus(void);
980 :
981 : // update inflight calculaton that determines if GPS data is good enough for reliable navigation
982 : void calcGpsGoodForFlight(void);
983 :
984 : // Read the range finder and take new measurements if available
985 : // Apply a median filter to range finder data
986 : void readRangeFinder();
987 :
988 : #if EK3_FEATURE_OPTFLOW_FUSION
989 : // check if the vehicle has taken off during optical flow navigation by looking at inertial and range finder data
990 : void detectOptFlowTakeoff(void);
991 : #endif
992 :
993 : // align the NE earth magnetic field states with the published declination
994 : void alignMagStateDeclination();
995 :
996 : // Fuse compass measurements using a direct yaw angle observation (doesn't require magnetic field states)
997 : // Returns true if the fusion was successful
998 : bool fuseEulerYaw(yawFusionMethod method);
999 :
1000 : // return the best Tait-Bryan rotation order to use
1001 : void bestRotationOrder(rotationOrder &order);
1002 :
1003 : // Fuse declination angle to keep earth field declination from changing when we don't have earth relative observations.
1004 : // Input is 1-sigma uncertainty in published declination
1005 : void FuseDeclination(ftype declErr);
1006 :
1007 : // return magnetic declination in radians
1008 : ftype MagDeclination(void) const;
1009 :
1010 : // Propagate PVA solution forward from the fusion time horizon to the current time horizon
1011 : // using a simple observer
1012 : void calcOutputStates();
1013 :
1014 : // calculate a filtered offset between baro height measurement and EKF height estimate
1015 : void calcFiltBaroOffset();
1016 :
1017 : // correct the height of the EKF origin to be consistent with GPS Data using a Bayes filter.
1018 : void correctEkfOriginHeight();
1019 :
1020 : // Select height data to be fused from the available baro, range finder and GPS sources
1021 : void selectHeightForFusion();
1022 :
1023 : // record all requested yaw resets completed
1024 : void recordYawResetsCompleted();
1025 :
1026 : // record a magnetic field state reset event
1027 : void recordMagReset();
1028 :
1029 : // effective value of MAG_CAL
1030 : MagCal effective_magCal(void) const;
1031 :
1032 : // calculate the tilt error variance
1033 : void calcTiltErrorVariance(void);
1034 :
1035 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
1036 : // calculate the tilt error variance using an alternative numerical difference technique
1037 : // and log with value generated by NavEKF3_core::calcTiltErrorVariance()
1038 : void verifyTiltErrorVariance();
1039 : #endif
1040 :
1041 : // update timing statistics structure
1042 : void updateTimingStatistics(void);
1043 :
1044 : // Update the state index limit based on which states are active
1045 : void updateStateIndexLim(void);
1046 :
1047 : // correct GPS data for antenna position
1048 : void CorrectGPSForAntennaOffset(gps_elements &gps_data) const;
1049 :
1050 : // correct external navigation earth-frame position using sensor body-frame offset
1051 : void CorrectExtNavForSensorOffset(ext_nav_elements &ext_nav_data);
1052 :
1053 : // correct external navigation earth-frame velocity using sensor body-frame offset
1054 : void CorrectExtNavVelForSensorOffset(ext_nav_vel_elements &ext_nav_vel_data) const;
1055 :
1056 : // calculate velocity variances and innovations
1057 : // Scale factor applied to NE velocity measurement variance due to manoeuvre acceleration
1058 : // Scale factor applied to vertical velocity measurement variance due to manoeuvre acceleration
1059 : // variances argument is updated with variances for each axis
1060 : void CalculateVelInnovationsAndVariances(const Vector3F &velocity, ftype noise, ftype accel_scale, Vector3F &innovations, Vector3F &variances) const;
1061 :
1062 : // Runs the IMU prediction step for an independent GSF yaw estimator algorithm
1063 : // that uses IMU, GPS horizontal velocity and optionally true airspeed data.
1064 : void runYawEstimatorPrediction(void);
1065 :
1066 : // Run the GPS velocity correction step for the GSF yaw estimator and use the
1067 : // yaw estimate to reset the main EKF yaw if requested
1068 : void runYawEstimatorCorrection(void);
1069 :
1070 : // reset the quaternion states using the supplied yaw angle, maintaining the previous roll and pitch
1071 : // also reset the body to nav frame rotation matrix
1072 : // reset the quaternion state covariances using the supplied yaw variance
1073 : // yaw : new yaw angle (rad)
1074 : // yaw_variance : variance of new yaw angle (rad^2)
1075 : // order : enum defining Tait-Bryan rotation order used in calculation of the yaw angle
1076 : void resetQuatStateYawOnly(ftype yaw, ftype yawVariance, rotationOrder order);
1077 :
1078 : // attempt to reset the yaw to the EKF-GSF value
1079 : // emergency_reset should be true if this reset is triggered by the loss of the yaw estimate
1080 : // returns false if unsuccessful
1081 : bool EKFGSF_resetMainFilterYaw(bool emergency_reset);
1082 :
1083 : // returns true on success and populates yaw (in radians) and yawVariance (rad^2)
1084 : bool EKFGSF_getYaw(ftype &yaw, ftype &yawVariance) const;
1085 :
1086 : // Fusion of body frame X and Y axis drag specific forces for multi-rotor wind estimation
1087 : void FuseDragForces();
1088 : void SelectDragFusion();
1089 : void SampleDragData(const imu_elements &imu);
1090 :
1091 : bool getGPSLLH(Location &loc) const;
1092 :
1093 : // Variables
1094 : bool statesInitialised; // boolean true when filter states have been initialised
1095 : bool magHealth; // boolean true if magnetometer has passed innovation consistency check
1096 : bool velTimeout; // boolean true if velocity measurements have failed innovation consistency check and timed out
1097 : bool posTimeout; // boolean true if position measurements have failed innovation consistency check and timed out
1098 : bool hgtTimeout; // boolean true if height measurements have failed innovation consistency check and timed out
1099 : bool magTimeout; // boolean true if magnetometer measurements have failed for too long and have timed out
1100 : bool tasTimeout; // boolean true if true airspeed measurements have failed for too long and have timed out
1101 : bool dragTimeout; // boolean true if drag measurements have failed for too long and have timed out
1102 : bool badIMUdata; // boolean true if the bad IMU data is detected
1103 : bool velAiding; // boolean true if the velocity drift is constrained by observations
1104 : bool waitingForGpsChecks; // boolean true if the EKF should write GPS data to the buffer until quality checks have passed
1105 : uint32_t badIMUdata_ms; // time stamp bad IMU data was last detected
1106 : uint32_t goodIMUdata_ms; // time stamp good IMU data was last detected
1107 : uint32_t vertVelVarClipCounter; // counter used to control reset of vertical velocity variance following collapse against the lower limit
1108 :
1109 : ftype gpsNoiseScaler; // Used to scale the GPS measurement noise and consistency gates to compensate for operation with small satellite counts
1110 : Matrix24 P; // covariance matrix
1111 : EKF_IMU_buffer_t<imu_elements> storedIMU; // IMU data buffer
1112 : EKF_obs_buffer_t<gps_elements> storedGPS; // GPS data buffer
1113 : EKF_obs_buffer_t<mag_elements> storedMag; // Magnetometer data buffer
1114 : EKF_obs_buffer_t<baro_elements> storedBaro; // Baro data buffer
1115 : EKF_obs_buffer_t<tas_elements> storedTAS; // TAS data buffer
1116 : #if EK3_FEATURE_RANGEFINDER_MEASUREMENTS
1117 : EKF_obs_buffer_t<range_elements> storedRange; // Range finder data buffer
1118 : #endif
1119 : EKF_IMU_buffer_t<output_elements> storedOutput;// output state buffer
1120 : Matrix3F prevTnb; // previous nav to body transformation used for INS earth rotation compensation
1121 : ftype accNavMag; // magnitude of navigation accel - used to adjust GPS obs variance (m/s^2)
1122 : ftype accNavMagHoriz; // magnitude of navigation accel in horizontal plane (m/s^2)
1123 : Vector3F earthRateNED; // earths angular rate vector in NED (rad/s)
1124 : ftype dtIMUavg; // expected time between IMU measurements (sec)
1125 : ftype dtEkfAvg; // expected time between EKF updates (sec)
1126 : ftype dt; // time lapsed since the last covariance prediction (sec)
1127 : ftype hgtRate; // state for rate of change of height filter
1128 : bool onGround; // true when the flight vehicle is definitely on the ground
1129 : bool prevOnGround; // value of onGround from previous frame - used to detect transition
1130 : bool inFlight; // true when the vehicle is definitely flying
1131 : bool prevInFlight; // value inFlight from previous frame - used to detect transition
1132 : bool manoeuvring; // boolean true when the flight vehicle is performing horizontal changes in velocity
1133 : bool fusingStationaryZeroVel; // true when fusing synthetic zero velocity while stationary on ground
1134 : Vector6 innovVelPos; // innovation output for a group of measurements
1135 : Vector6 varInnovVelPos; // innovation variance output for a group of measurements
1136 : Vector6 velPosObs; // observations for combined velocity and positon group of measurements (3x1 m , 3x1 m/s)
1137 : bool fuseVelData; // this boolean causes the velNE measurements to be fused
1138 : bool fuseVelVertData; // this boolean causes the velD measurement to be fused
1139 : bool fusePosData; // this boolean causes the posNE measurements to be fused
1140 : bool fuseHgtData; // this boolean causes the hgtMea measurements to be fused
1141 : Vector3F innovMag; // innovation output from fusion of X,Y,Z compass measurements
1142 : Vector3F varInnovMag; // innovation variance output from fusion of X,Y,Z compass measurements
1143 : ftype innovVtas; // innovation output from fusion of airspeed measurements
1144 : ftype varInnovVtas; // innovation variance output from fusion of airspeed measurements
1145 : ftype defaultAirSpeed; // default equivalent airspeed in m/s to be used if the measurement is unavailable. Do not use if not positive.
1146 : ftype defaultAirSpeedVariance; // default equivalent airspeed variance in (m/s)**2 to be used when defaultAirSpeed is specified.
1147 : bool magFusePerformed; // boolean set to true when magnetometer fusion has been perfomred in that time step
1148 : MagCal effectiveMagCal; // the actual mag calibration being used as the default
1149 : uint32_t prevTasStep_ms; // time stamp of last TAS fusion step
1150 : uint32_t prevBetaDragStep_ms; // time stamp of last synthetic sideslip fusion step
1151 : ftype innovBeta; // synthetic sideslip innovation (rad)
1152 : uint32_t lastMagUpdate_us; // last time compass was updated in usec
1153 : uint32_t lastMagRead_ms; // last time compass data was successfully read
1154 : Vector3F velDotNED; // rate of change of velocity in NED frame
1155 : Vector3F velDotNEDfilt; // low pass filtered velDotNED
1156 : uint32_t imuSampleTime_ms; // time that the last IMU value was taken
1157 : bool tasDataToFuse; // true when new airspeed data is waiting to be fused
1158 : uint32_t lastBaroReceived_ms; // time last time we received baro height data
1159 : uint16_t hgtRetryTime_ms; // time allowed without use of height measurements before a height timeout is declared
1160 : uint32_t lastVelPassTime_ms; // time stamp when GPS velocity measurement last passed innovation consistency check (msec)
1161 : uint32_t lastGpsPosPassTime_ms; // time stamp when GPS position measurement last passed innovation consistency check (msec)
1162 : uint32_t lastHgtPassTime_ms; // time stamp when height measurement last passed innovation consistency check (msec)
1163 : uint32_t lastTasPassTime_ms; // time stamp when airspeed measurement last passed innovation consistency check (msec)
1164 : uint32_t lastTasFailTime_ms; // time stamp when airspeed measurement last failed innovation consistency check (msec)
1165 : uint32_t lastTimeGpsReceived_ms;// last time we received GPS data
1166 : uint32_t timeAtLastAuxEKF_ms; // last time the auxiliary filter was run to fuse range or optical flow measurements
1167 : uint32_t lastHealthyMagTime_ms; // time the magnetometer was last declared healthy
1168 : bool allMagSensorsFailed; // true if all magnetometer sensors have timed out on this flight and we are no longer using magnetometer data
1169 : uint32_t lastSynthYawTime_ms; // time stamp when yaw observation was last fused (msec)
1170 : uint32_t ekfStartTime_ms; // time the EKF was started (msec)
1171 : Vector2F lastKnownPositionNE; // last known position
1172 : float lastKnownPositionD; // last known height
1173 : uint32_t lastLaunchAccelTime_ms;
1174 : ftype velTestRatio; // sum of squares of GPS velocity innovation divided by fail threshold
1175 : ftype posTestRatio; // sum of squares of GPS position innovation divided by fail threshold
1176 : ftype hgtTestRatio; // sum of squares of baro height innovation divided by fail threshold
1177 : Vector3F magTestRatio; // sum of squares of magnetometer innovations divided by fail threshold
1178 : ftype tasTestRatio; // sum of squares of true airspeed innovation divided by fail threshold
1179 : bool inhibitWindStates; // true when wind states and covariances should not be used
1180 : ftype lastAirspeedEstimate; // last true airspeed estimate (m/s)
1181 : bool lastAspdEstIsValid; // true when the last true airspeed estimate is valid (m/s)
1182 : bool windStateIsObservable; // true when wind states are observable from measurements.
1183 : bool treatWindStatesAsTruth; // true when wind states should be used as a truth reference
1184 : bool windStatesAligned; // true when wind states have been aligned
1185 : bool inhibitMagStates; // true when magnetic field states are inactive
1186 : bool lastInhibitMagStates; // previous inhibitMagStates
1187 : bool needMagBodyVarReset; // we need to reset mag body variances at next CovariancePrediction
1188 : bool needEarthBodyVarReset; // we need to reset mag earth variances at next CovariancePrediction
1189 : bool inhibitDelAngBiasStates; // true when IMU delta angle bias states are inactive
1190 : bool gpsIsInUse; // bool true when GPS data is being used to correct states estimates
1191 : Location EKF_origin; // LLH origin of the NED axis system, internal only
1192 : Location &public_origin; // LLH origin of the NED axis system, public functions
1193 : bool validOrigin; // true when the EKF origin is valid
1194 : ftype gpsSpdAccuracy; // estimated speed accuracy in m/s returned by the GPS receiver
1195 : ftype gpsPosAccuracy; // estimated position accuracy in m returned by the GPS receiver
1196 : ftype gpsHgtAccuracy; // estimated height accuracy in m returned by the GPS receiver
1197 : uint32_t lastGpsVelFail_ms; // time of last GPS vertical velocity consistency check fail
1198 : uint32_t lastGpsVelPass_ms; // time of last GPS vertical velocity consistency check pass
1199 : uint32_t lastGpsAidBadTime_ms; // time in msec gps aiding was last detected to be bad
1200 : ftype posDownAtTakeoff; // flight vehicle vertical position sampled at transition from on-ground to in-air and used as a reference (m)
1201 : bool useGpsVertVel; // true if GPS vertical velocity should be used
1202 : uint16_t yawResetCount; // number of yaw resets performed by this core
1203 : bool tiltAlignComplete; // true when tilt alignment is complete
1204 : bool yawAlignComplete; // true when yaw alignment is complete
1205 : uint8_t yawAlignGpsValidCount; // number of continuous good GPS velocity samples used for in flight yaw alignment
1206 : bool magStateInitComplete; // true when the magnetic field states have been initialised
1207 : uint8_t stateIndexLim; // Max state index used during matrix and array operations
1208 : imu_elements imuDataDelayed; // IMU data at the fusion time horizon
1209 : imu_elements imuDataNew; // IMU data at the current time horizon
1210 : imu_elements imuDataDownSampledNew; // IMU data at the current time horizon that has been downsampled to a 100Hz rate
1211 : QuaternionF imuQuatDownSampleNew; // Quaternion obtained by rotating through the IMU delta angles since the start of the current down sampled frame
1212 : baro_elements baroDataNew; // Baro data at the current time horizon
1213 : baro_elements baroDataDelayed; // Baro data at the fusion time horizon
1214 : range_elements rangeDataNew; // Range finder data at the current time horizon
1215 : range_elements rangeDataDelayed;// Range finder data at the fusion time horizon
1216 : tas_elements tasDataNew; // TAS data at the current time horizon
1217 : tas_elements tasDataDelayed; // TAS data at the fusion time horizon
1218 : mag_elements magDataDelayed; // Magnetometer data at the fusion time horizon
1219 : gps_elements gpsDataNew; // GPS data at the current time horizon
1220 : gps_elements gpsDataDelayed; // GPS data at the fusion time horizon
1221 : uint8_t last_gps_idx; // sensor ID of the GPS receiver used for the last fusion or reset
1222 : output_elements outputDataNew; // output state data at the current time step
1223 : output_elements outputDataDelayed; // output state data at the current time step
1224 : Vector3F delAngCorrection; // correction applied to delta angles used by output observer to track the EKF
1225 : Vector3F velErrintegral; // integral of output predictor NED velocity tracking error (m)
1226 : Vector3F posErrintegral; // integral of output predictor NED position tracking error (m.sec)
1227 : ftype badImuVelErrIntegral; // integral of output predictor D velocity tracking error when bad IMU data is detected (m)
1228 : ftype innovYaw; // compass yaw angle innovation (rad)
1229 : uint32_t timeTasReceived_ms; // time last TAS data was received (msec)
1230 : bool gpsGoodToAlign; // true when the GPS quality can be used to initialise the navigation system
1231 : uint32_t magYawResetTimer_ms; // timer in msec used to track how long good magnetometer data is failing innovation consistency checks
1232 : bool consistentMagData; // true when the magnetometers are passing consistency checks
1233 : bool motorsArmed; // true when the motors have been armed
1234 : bool prevMotorsArmed; // value of motorsArmed from previous frame
1235 : bool posVelFusionDelayed; // true when the position and velocity fusion has been delayed
1236 : #if EK3_FEATURE_OPTFLOW_FUSION
1237 : bool optFlowFusionDelayed; // true when the optical flow fusion has been delayed
1238 : #endif
1239 : bool airSpdFusionDelayed; // true when the air speed fusion has been delayed
1240 : bool sideSlipFusionDelayed; // true when the sideslip fusion has been delayed
1241 : bool airDataFusionWindOnly; // true when sideslip and airspeed fusion is only allowed to modify the wind states
1242 : Vector3F lastMagOffsets; // Last magnetometer offsets from COMPASS_ parameters. Used to detect parameter changes.
1243 : bool lastMagOffsetsValid; // True when lastMagOffsets has been initialized
1244 : Vector2F posResetNE; // Change in North/East position due to last in-flight reset in metres
1245 : ftype posResetD; // Change in Down position due to last in-flight reset in metres
1246 : uint16_t posNEResetCount; // number of NE position resets performed by this core
1247 : uint16_t posDResetCount; // number of D position resets performed by this core
1248 : ftype yawTestRatio; // square of magnetometer yaw angle innovation divided by fail threshold
1249 : QuaternionF prevQuatMagReset; // Quaternion from the last time the magnetic field state reset condition test was performed
1250 : ftype hgtInnovFiltState; // state used for fitering of the height innovations used for pre-flight checks
1251 : uint8_t magSelectIndex; // Index of the magnetometer that is being used by the EKF
1252 : bool runUpdates; // boolean true when the EKF updates can be run
1253 : uint32_t framesSincePredict; // number of frames lapsed since EKF instance did a state prediction
1254 : uint8_t localFilterTimeStep_ms; // average number of msec between filter updates
1255 : ftype posDownObsNoise; // observation noise variance on the vertical position used by the state and covariance update step (m^2)
1256 : Vector3F delAngCorrected; // corrected IMU delta angle vector at the EKF time horizon (rad)
1257 : Vector3F delVelCorrected; // corrected IMU delta velocity vector at the EKF time horizon (m/s)
1258 : bool magFieldLearned; // true when the magnetic field has been learned
1259 : uint32_t wasLearningCompass_ms; // time when we were last waiting for compass learn to complete
1260 : Vector3F earthMagFieldVar; // NED earth mag field variances for last learned field (mGauss^2)
1261 : Vector3F bodyMagFieldVar; // XYZ body mag field variances for last learned field (mGauss^2)
1262 : bool delAngBiasLearned; // true when the gyro bias has been learned
1263 : nav_filter_status filterStatus; // contains the status of various filter outputs
1264 : ftype ekfOriginHgtVar; // Variance of the EKF WGS-84 origin height estimate (m^2)
1265 : double ekfGpsRefHgt; // floating point representation of the WGS-84 reference height used to convert GPS height to local height (m)
1266 : uint32_t lastOriginHgtTime_ms; // last time the ekf's WGS-84 origin height was corrected
1267 : Vector3F outputTrackError; // attitude (rad), velocity (m/s) and position (m) tracking error magnitudes from the output observer
1268 : Vector3F velOffsetNED; // This adds to the earth frame velocity estimate at the IMU to give the velocity at the body origin (m/s)
1269 : Vector3F posOffsetNED; // This adds to the earth frame position estimate at the IMU to give the position at the body origin (m)
1270 : uint32_t firstInitTime_ms; // First time the initialise function was called (msec)
1271 : uint32_t lastInitFailReport_ms; // Last time the buffer initialisation failure report was sent (msec)
1272 : ftype tiltErrorVariance; // variance of the angular uncertainty measured perpendicular to the vertical (rad^2)
1273 :
1274 : // variables used to calculate a vertical velocity that is kinematically consistent with the vertical position
1275 : struct {
1276 : ftype pos;
1277 : ftype vel;
1278 : ftype acc;
1279 : } vertCompFiltState;
1280 :
1281 : // variables used by the pre-initialisation GPS checks
1282 : Location gpsloc_prev; // LLH location of previous GPS measurement
1283 : uint32_t lastPreAlignGpsCheckTime_ms; // last time in msec the GPS quality was checked during pre alignment checks
1284 : ftype gpsDriftNE; // amount of drift detected in the GPS position during pre-flight GPs checks
1285 : ftype gpsVertVelFilt; // amount of filtered vertical GPS velocity detected during pre-flight GPS checks
1286 : ftype gpsHorizVelFilt; // amount of filtered horizontal GPS velocity detected during pre-flight GPS checks
1287 :
1288 : // variable used by the in-flight GPS quality check
1289 : bool gpsSpdAccPass; // true when reported GPS speed accuracy passes in-flight checks
1290 : bool gpsVertAccPass; // true when reported GPS vertical accuracy passes in-flight checks
1291 : bool ekfInnovationsPass; // true when GPS innovations pass in-flight checks
1292 : ftype sAccFilterState1; // state variable for LPF applied to reported GPS speed accuracy
1293 : ftype sAccFilterState2; // state variable for peak hold filter applied to reported GPS speed
1294 : uint32_t lastGpsCheckTime_ms; // last time in msec the GPS quality was checked
1295 : uint32_t lastGpsInnovPassTime_ms; // last time in msec the GPS innovations passed
1296 : uint32_t lastGpsInnovFailTime_ms; // last time in msec the GPS innovations failed
1297 : uint32_t lastGpsVertAccPassTime_ms; // last time in msec the GPS vertical accuracy test passed
1298 : uint32_t lastGpsVertAccFailTime_ms; // last time in msec the GPS vertical accuracy test failed
1299 : bool gpsAccuracyGood; // true when the GPS accuracy is considered to be good enough for safe flight.
1300 : bool gpsAccuracyGoodForAltitude; // true when the GPS accuracy is considered to be good enough to use it as an altitude source.
1301 : Vector3F gpsVelInnov; // gps velocity innovations
1302 : Vector3F gpsVelVarInnov; // gps velocity innovation variances
1303 : uint32_t gpsRetrieveTime_ms; // system time that GPS data was retrieved from the buffer (to detect timeouts)
1304 :
1305 : // variables added for optical flow fusion
1306 : EKF_obs_buffer_t<of_elements> storedOF; // OF data buffer
1307 : bool flowDataValid; // true while optical flow data is still fresh
1308 : Vector2F auxFlowObsInnov; // optical flow rate innovation from 1-state terrain offset estimator
1309 : uint32_t flowValidMeaTime_ms; // time stamp from latest valid flow measurement (msec)
1310 : uint32_t rngValidMeaTime_ms; // time stamp from latest valid range measurement (msec)
1311 : uint32_t flowMeaTime_ms; // time stamp from latest flow measurement (msec)
1312 : uint32_t gndHgtValidTime_ms; // time stamp from last terrain offset state update (msec)
1313 : Vector2 flowVarInnov; // optical flow innovations variances (rad/sec)^2
1314 : Vector2 flowInnov; // optical flow LOS innovations (rad/sec)
1315 : uint32_t flowInnovTime_ms; // system time that optical flow innovations and variances were recorded (to detect timeouts)
1316 : #if EK3_FEATURE_OPTFLOW_FUSION
1317 : ftype Popt; // Optical flow terrain height state covariance (m^2)
1318 : #endif
1319 :
1320 : #if EK3_FEATURE_OPTFLOW_AGL_KF
1321 : // ---- 2-state AGL Kalman Filter ----
1322 : // Uses bias-corrected IMU delta-velocity for prediction and downward rangefinder
1323 : // as measurement, decoupled from the main filter's vertical position state.
1324 : // State: x = [aglKfH (m, +up), aglKfV (m/s, +up)]
1325 : ftype aglKfH; // AGL height estimate (m, positive up from ground)
1326 : ftype aglKfV; // AGL velocity estimate (m/s, positive = climbing)
1327 : ftype aglKfP[2][2]; // 2x2 covariance matrix (upper triangle, symmetric)
1328 : bool aglKfValid; // true when RF has been fused within the last 5 s
1329 : uint32_t lastAglRngFuseTime_ms; // timestamp of last successful RF fusion into AGL KF
1330 : #endif
1331 : ftype terrainState; // terrain position state (m)
1332 : ftype prevPosN; // north position at last measurement
1333 : ftype prevPosE; // east position at last measurement
1334 : ftype varInnovRng; // range finder observation innovation variance (m^2)
1335 : ftype innovRng; // range finder observation innovation (m)
1336 : struct {
1337 : uint32_t timestamp_ms; // system timestamp of last correct optical flow sample (used for calibration)
1338 : Vector2f flowRate; // latest corrected optical flow flow rate (used for calibration)
1339 : Vector2f bodyRate; // latest corrected optical flow body rate (used for calibration)
1340 : Vector2f losPred; // EKF estimated component of flowRate that comes from vehicle movement (not rotation)
1341 : } flowCalSample;
1342 :
1343 : #if EK3_FEATURE_OPTFLOW_SRTM
1344 : // terrain altitude from SRTM (only used for optical flow when rangefinder is out-of-range)
1345 : ftype terrain_srtm_alt; // terrain (from SRTM) altitude above the EKF origin (m)
1346 : uint32_t terrain_srtm_alt_ms; // system time when the SRTM terrain altitude was last updated (msec)
1347 : bool terrain_srtm_alt_valid; // true when the SRTM terrain altitude is valid (e.g. has been received within 5 seconds)
1348 : #endif
1349 :
1350 : ftype hgtMea; // height measurement derived from either baro, gps or range finder data (m)
1351 : bool inhibitGndState; // true when the terrain position state is to remain constant
1352 : uint32_t prevFlowFuseTime_ms; // time both flow measurement components passed their innovation consistency checks
1353 : Vector2 flowTestRatio; // square of optical flow innovations divided by fail threshold used by main filter where >1.0 is a fail
1354 : Vector2F auxFlowTestRatio; // sum of squares of optical flow innovation divided by fail threshold used by 1-state terrain offset estimator
1355 : ftype R_LOS; // variance of optical flow rate measurements (rad/sec)^2
1356 : ftype auxRngTestRatio; // square of range finder innovations divided by fail threshold used by main filter where >1.0 is a fail
1357 : Vector2F flowGyroBias; // bias error of optical flow sensor gyro output
1358 : bool rangeDataToFuse; // true when valid range finder height data has arrived at the fusion time horizon.
1359 : bool baroDataToFuse; // true when valid baro height finder data has arrived at the fusion time horizon.
1360 : bool gpsDataToFuse; // true when valid GPS data has arrived at the fusion time horizon.
1361 : bool magDataToFuse; // true when valid magnetometer data has arrived at the fusion time horizon
1362 : enum AidingMode {
1363 : AID_ABSOLUTE=0, // GPS or some other form of absolute position reference aiding is being used (optical flow may also be used in parallel) so position estimates are absolute.
1364 : AID_NONE=1, // no aiding is being used so only attitude and height estimates are available. Either constVelMode or constPosMode must be used to constrain tilt drift.
1365 : AID_RELATIVE=2, // only optical flow aiding is being used so position estimates will be relative
1366 : };
1367 : AidingMode PV_AidingMode; // Defines the preferred mode for aiding of velocity and position estimates from the INS
1368 : AidingMode PV_AidingModePrev; // Value of PV_AidingMode from the previous frame - used to detect transitions
1369 : bool gndOffsetValid; // true when the ground offset state can still be considered valid
1370 : Vector3F delAngBodyOF; // bias corrected delta angle of the vehicle IMU measured summed across the time since the last OF measurement
1371 : ftype delTimeOF; // time that delAngBodyOF is summed across
1372 : bool flowFusionActive; // true when optical flow fusion is active
1373 :
1374 : Vector3F accelPosOffset; // position of IMU accelerometer unit in body frame (m)
1375 :
1376 : // Range finder
1377 : ftype baroHgtOffset; // offset applied when when switching to use of Baro height
1378 : ftype rngOnGnd; // Expected range finder reading in metres when vehicle is on ground
1379 : uint32_t lastRngMeasTime_ms; // Timestamp of last range measurement
1380 : bool terrainHgtStable; // true when the terrain height is stable enough to be used as a height reference
1381 : #if EK3_FEATURE_RANGEFINDER_MEASUREMENTS
1382 : ftype storedRngMeas[DOWNWARD_RANGEFINDER_MAX_INSTANCES][3]; // Ringbuffer of stored range measurements for dual range sensors
1383 : uint32_t storedRngMeasTime_ms[DOWNWARD_RANGEFINDER_MAX_INSTANCES][3]; // Ringbuffers of stored range measurement times for dual range sensors
1384 : uint8_t rngMeasIndex[DOWNWARD_RANGEFINDER_MAX_INSTANCES]; // Current range measurement ringbuffer index for dual range sensors
1385 : #endif
1386 :
1387 : // body frame odometry fusion
1388 : #if EK3_FEATURE_BODY_ODOM
1389 : EKF_obs_buffer_t<vel_odm_elements> storedBodyOdm; // body velocity data buffer
1390 : vel_odm_elements bodyOdmDataNew; // Body frame odometry data at the current time horizon
1391 : vel_odm_elements bodyOdmDataDelayed; // Body frame odometry data at the fusion time horizon
1392 : #endif
1393 : uint32_t lastbodyVelPassTime_ms; // time stamp when the body velocity measurement last passed innovation consistency checks (msec)
1394 : Vector3 bodyVelTestRatio; // Innovation test ratios for body velocity XYZ measurements
1395 : Vector3 varInnovBodyVel; // Body velocity XYZ innovation variances (m/sec)^2
1396 : Vector3 innovBodyVel; // Body velocity XYZ innovations (m/sec)
1397 : uint32_t prevBodyVelFuseTime_ms; // previous time all body velocity measurement components passed their innovation consistency checks (msec)
1398 : uint32_t bodyOdmMeasTime_ms; // time body velocity measurements were accepted for input to the data buffer (msec)
1399 : bool bodyVelFusionDelayed; // true when body frame velocity fusion has been delayed
1400 : bool bodyVelFusionActive; // true when body frame velocity fusion is active
1401 :
1402 : #if EK3_FEATURE_BODY_ODOM
1403 : // wheel sensor fusion
1404 : EKF_obs_buffer_t<wheel_odm_elements> storedWheelOdm; // body velocity data buffer
1405 : wheel_odm_elements wheelOdmDataDelayed; // Body frame odometry data at the fusion time horizon
1406 : #endif
1407 :
1408 : // GPS yaw sensor fusion
1409 : uint32_t yawMeasTime_ms; // system time GPS yaw angle was last input to the data buffer
1410 : EKF_obs_buffer_t<yaw_elements> storedYawAng; // GPS yaw angle buffer
1411 : yaw_elements yawAngDataNew; // GPS yaw angle at the current time horizon
1412 : yaw_elements yawAngDataDelayed; // GPS yaw angle at the fusion time horizon
1413 : yaw_elements yawAngDataStatic; // yaw angle (regardless of yaw source) when the vehicle was last on ground and not moving
1414 :
1415 : // Range Beacon Sensor Fusion
1416 : #if EK3_FEATURE_BEACON_FUSION
1417 : class BeaconFusion {
1418 : public:
1419 3989 : BeaconFusion(AP_DAL &_dal) :
1420 3989 : dal{_dal}
1421 3989 : {}
1422 :
1423 : void InitialiseVariables();
1424 :
1425 : EKF_obs_buffer_t<rng_bcn_elements> storedRange; // Beacon range buffer
1426 : rng_bcn_elements dataDelayed; // Range beacon data at the fusion time horizon
1427 : uint32_t lastPassTime_ms; // time stamp when the range beacon measurement last passed innovation consistency checks (msec)
1428 : ftype testRatio; // Innovation test ratio for range beacon measurements
1429 : bool health; // boolean true if range beacon measurements have passed innovation consistency check
1430 : ftype varInnov; // range beacon observation innovation variance (m^2)
1431 : ftype innov; // range beacon observation innovation (m)
1432 : uint32_t lastTime_ms[4]; // last time we received a range beacon measurement (msec)
1433 : bool dataToFuse; // true when there is new range beacon data to fuse
1434 : Vector3F vehiclePosNED; // NED position estimate from the beacon system (NED)
1435 : ftype vehiclePosErr; // estimated position error from the beacon system (m)
1436 : uint32_t last3DmeasTime_ms; // last time the beacon system returned a 3D fix (msec)
1437 : bool goodToAlign; // true when the range beacon systems 3D fix can be used to align the filter
1438 : uint8_t lastChecked; // index of the last range beacon checked for data
1439 : Vector3F receiverPos; // receiver NED position (m) - alignment 3 state filter
1440 : ftype receiverPosCov[3][3]; // Receiver position covariance (m^2) - alignment 3 state filter (
1441 : bool alignmentStarted; // True when the initial position alignment using range measurements has started
1442 : bool alignmentCompleted; // True when the initial position alignment using range measurements has finished
1443 : uint8_t lastIndex; // Range beacon index last read - used during initialisation of the 3-state filter
1444 : Vector3F posSum; // Sum of range beacon NED position (m) - used during initialisation of the 3-state filter
1445 : uint8_t numMeas; // Number of beacon measurements - used during initialisation of the 3-state filter
1446 : ftype sum; // Sum of range measurements (m) - used during initialisation of the 3-state filter
1447 : uint8_t N; // Number of range beacons in use
1448 : ftype maxPosD; // maximum position of all beacons in the down direction (m)
1449 : ftype minPosD; // minimum position of all beacons in the down direction (m)
1450 : bool usingMinHypothesis; // true when the min beacon constellation offset hypothesis is being used
1451 :
1452 : ftype posDownOffsetMax; // Vertical position offset of the beacon constellation origin relative to the EKF origin (m)
1453 : ftype posOffsetMaxVar; // Variance of the PosDownOffsetMax state (m)
1454 : ftype maxOffsetStateChangeFilt; // Filtered magnitude of the change in PosOffsetHigh
1455 :
1456 : ftype posDownOffsetMin; // Vertical position offset of the beacon constellation origin relative to the EKF origin (m)
1457 : ftype posOffsetMinVar; // Variance of the PosDownOffsetMin state (m)
1458 : ftype minOffsetStateChangeFilt; // Filtered magnitude of the change in PosOffsetLow
1459 :
1460 : Vector3F posOffsetNED; // NED position of the beacon origin in earth frame (m)
1461 : bool originEstInit; // True when the beacon origin has been initialised
1462 :
1463 : // Range Beacon Fusion Debug Reporting
1464 : uint8_t fuseDataReportIndex;// index of range beacon fusion data last reported
1465 : struct FusionReport {
1466 : ftype rng; // measured range to beacon (m)
1467 : ftype innov; // range innovation (m)
1468 : ftype innovVar; // innovation variance (m^2)
1469 : ftype testRatio; // innovation consistency test ratio
1470 : Vector3F beaconPosNED; // beacon NED position
1471 : } *fusionReport;
1472 : uint8_t numFusionReports;
1473 :
1474 : AP_DAL &dal;
1475 : } rngBcn{dal};
1476 : #endif // if EK3_FEATURE_BEACON_FUSION
1477 :
1478 : #if EK3_FEATURE_DRAG_FUSION
1479 : // drag fusion for multicopter wind estimation
1480 : EKF_obs_buffer_t<drag_elements> storedDrag;
1481 : drag_elements dragSampleDelayed;
1482 : drag_elements dragDownSampled; // down sampled from filter prediction rate to observation rate
1483 : uint8_t dragSampleCount; // number of drag specific force samples accumulated at the filter prediction rate
1484 : ftype dragSampleTimeDelta; // time integral across all samples used to form _drag_down_sampled (sec)
1485 : Vector2F innovDrag; // multirotor drag measurement innovation (m/sec**2)
1486 : Vector2F innovDragVar; // multirotor drag measurement innovation variance ((m/sec**2)**2)
1487 : Vector2F dragTestRatio; // drag innovation consistency check ratio
1488 : #endif
1489 : uint32_t lastDragPassTime_ms; // system time that drag samples were last successfully fused
1490 : bool dragFusionEnabled;
1491 :
1492 : // height source selection logic
1493 : AP_NavEKF_Source::SourceZ activeHgtSource; // active height source
1494 : AP_NavEKF_Source::SourceZ prevHgtSource; // previous height source used to detect changes in source
1495 :
1496 : // Movement detector
1497 : bool takeOffDetected; // true when takeoff for optical flow navigation has been detected
1498 : ftype rngAtStartOfFlight; // range finder measurement at start of flight
1499 : uint32_t timeAtArming_ms; // time in msec that the vehicle armed
1500 :
1501 : // baro ground effect
1502 : ftype meaHgtAtTakeOff; // height measured at commencement of takeoff
1503 :
1504 : // control of post takeoff magnetic field and heading resets
1505 : bool finalInflightYawInit; // true when the final post takeoff initialisation of yaw angle has been performed
1506 : uint8_t magYawAnomallyCount; // Number of times the yaw has been reset due to a magnetic anomaly during initial ascent
1507 : bool finalInflightMagInit; // true when the final post takeoff initialisation of magnetic field states been performed
1508 : bool magStateResetRequest; // true if magnetic field states need to be reset using the magnetomter measurements
1509 : bool magYawResetRequest; // true if the vehicle yaw and magnetic field states need to be reset using the magnetometer measurements
1510 : bool gpsYawResetRequest; // true if the vehicle yaw needs to be reset to the GPS course
1511 : ftype posDownAtLastMagReset; // vertical position last time the mag states were reset (m)
1512 : ftype yawInnovAtLastMagReset; // magnetic yaw innovation last time the yaw and mag field states were reset (rad)
1513 : QuaternionF quatAtLastMagReset; // quaternion states last time the mag states were reset
1514 : MagFuseSel magFusionSel; // magnetometer fusion selection
1515 :
1516 : // Used by on ground movement check required when operating on ground without a yaw reference
1517 : ftype gyro_diff; // filtered gyro difference (rad/s)
1518 : ftype accel_diff; // filtered acceerometer difference (m/s/s)
1519 : Vector3F gyro_prev; // gyro vector from previous time step (rad/s)
1520 : Vector3F accel_prev; // accelerometer vector from previous time step (m/s/s)
1521 : bool onGroundNotMoving; // true when on the ground and not moving
1522 : uint32_t lastMoveCheckLogTime_ms; // last time the movement check data was logged (msec)
1523 :
1524 : // variables used to inhibit accel bias learning
1525 : bool inhibitDelVelBiasStates; // true when all IMU delta velocity bias states are de-activated
1526 : bool dvelBiasAxisInhibit[3] {}; // true when IMU delta velocity bias states for a specific axis is de-activated
1527 : Vector3F dvelBiasAxisVarPrev; // saved delta velocity XYZ bias variances (m/sec)**2
1528 :
1529 : #if EK3_FEATURE_EXTERNAL_NAV
1530 : // external navigation fusion
1531 : EKF_obs_buffer_t<ext_nav_elements> storedExtNav; // external navigation data buffer
1532 : ext_nav_elements extNavDataDelayed; // External nav at the fusion time horizon
1533 : uint32_t extNavMeasTime_ms; // time external measurements were accepted for input to the data buffer (msec)
1534 : uint32_t extNavLastPosResetTime_ms; // last time the external nav systen performed a position reset (msec)
1535 : bool extNavDataToFuse; // true when there is new external nav data to fuse
1536 : bool extNavUsedForPos; // true when the external nav data is being used as a position reference.
1537 : EKF_obs_buffer_t<ext_nav_vel_elements> storedExtNavVel; // external navigation velocity data buffer
1538 : ext_nav_vel_elements extNavVelDelayed; // external navigation velocity data at the fusion time horizon. Already corrected for sensor position
1539 : uint32_t extNavVelMeasTime_ms; // time external navigation velocity measurements were accepted for input to the data buffer (msec)
1540 : bool extNavVelToFuse; // true when there is new external navigation velocity to fuse
1541 : Vector3F extNavVelInnov; // external nav velocity innovations
1542 : Vector3F extNavVelVarInnov; // external nav velocity innovation variances
1543 : uint32_t extNavVelInnovTime_ms; // system time that external nav velocity innovations were recorded (to detect timeouts)
1544 : EKF_obs_buffer_t<yaw_elements> storedExtNavYawAng; // external navigation yaw angle buffer
1545 : yaw_elements extNavYawAngDataDelayed; // external navigation yaw angle at the fusion time horizon
1546 : uint32_t last_extnav_yaw_fusion_ms; // system time that external nav yaw was last fused
1547 : #endif // EK3_FEATURE_EXTERNAL_NAV
1548 : bool useExtNavVel; // true if external nav velocity should be used
1549 :
1550 : // flags indicating severe numerical errors in innovation variance calculation for different fusion operations
1551 : struct {
1552 : bool bad_xmag:1;
1553 : bool bad_ymag:1;
1554 : bool bad_zmag:1;
1555 : bool bad_airspeed:1;
1556 : bool bad_sideslip:1;
1557 : bool bad_nvel:1;
1558 : bool bad_evel:1;
1559 : bool bad_dvel:1;
1560 : bool bad_npos:1;
1561 : bool bad_epos:1;
1562 : bool bad_dpos:1;
1563 : bool bad_yaw:1;
1564 : bool bad_decl:1;
1565 : bool bad_xflow:1;
1566 : bool bad_yflow:1;
1567 : bool bad_rngbcn:1;
1568 : bool bad_xvel:1;
1569 : bool bad_yvel:1;
1570 : bool bad_zvel:1;
1571 : } faultStatus;
1572 :
1573 : // flags indicating which GPS quality checks are failing
1574 : union {
1575 : struct {
1576 : bool bad_sAcc:1;
1577 : bool bad_hAcc:1;
1578 : bool bad_vAcc:1;
1579 : bool bad_yaw:1;
1580 : bool bad_sats:1;
1581 : bool bad_VZ:1;
1582 : bool bad_horiz_drift:1;
1583 : bool bad_hdop:1;
1584 : bool bad_vert_vel:1;
1585 : bool bad_fix:1;
1586 : bool bad_horiz_vel:1;
1587 : };
1588 : uint16_t value;
1589 : } gpsCheckStatus;
1590 :
1591 : // string representing last reason for prearm failure
1592 : char prearm_fail_string[40];
1593 :
1594 : // earth field from WMM tables
1595 : bool have_table_earth_field; // true when we have initialised table_earth_field_ga
1596 : Vector3F table_earth_field_ga; // earth field from WMM tables
1597 : ftype table_declination; // declination in radians from the tables
1598 :
1599 : // 1Hz update
1600 : uint32_t last_oneHz_ms;
1601 : void oneHzUpdate(void);
1602 :
1603 : // move EKF origin at 1Hz
1604 : void moveEKFOrigin(void);
1605 :
1606 : // handle earth field updates
1607 : void getEarthFieldTable(const Location &loc);
1608 : void checkUpdateEarthField(void);
1609 :
1610 : // timing statistics
1611 : struct ekf_timing timing;
1612 :
1613 : // when was attitude filter status last non-zero?
1614 : uint32_t last_filter_ok_ms;
1615 :
1616 : // should we assume zero sideslip?
1617 : bool assume_zero_sideslip(void) const;
1618 :
1619 : // vehicle specific initial gyro bias uncertainty
1620 : ftype InitialGyroBiasUncertainty(void) const;
1621 :
1622 : // get the gyro bias limit for this core's IMU
1623 : ftype getGyroBiasLimit(void) const;
1624 :
1625 : /*
1626 : learn magnetometer biases from GPS yaw. Return true if the
1627 : resulting mag vector is close enough to the one predicted by GPS
1628 : yaw to use it for fallback
1629 : */
1630 : bool learnMagBiasFromGPS(void);
1631 :
1632 : uint32_t last_gps_yaw_ms; // last time the EKF attempted to use the GPS yaw
1633 : uint32_t last_gps_yaw_fuse_ms; // last time the EKF successfully fused the GPS yaw
1634 : bool gps_yaw_mag_fallback_ok;
1635 : bool gps_yaw_mag_fallback_active;
1636 : uint8_t gps_yaw_fallback_good_counter;
1637 :
1638 : /*
1639 : Update the on ground and not moving check.
1640 : Should be called once per IMU update.
1641 : Only updates when on ground and when operating with an external yaw sensor
1642 : */
1643 : void updateMovementCheck(void);
1644 :
1645 : // The following declarations are used to control when the main navigation filter resets it's yaw to the estimate provided by the GSF
1646 : uint32_t EKFGSF_yaw_reset_ms; // timestamp of last emergency yaw reset (uSec)
1647 : uint32_t EKFGSF_yaw_reset_request_ms; // timestamp of last emergency yaw reset request (uSec)
1648 : uint8_t EKFGSF_yaw_reset_count; // number of emergency yaw resets performed
1649 : bool EKFGSF_run_filterbank; // true when the filter bank is active
1650 : uint8_t EKFGSF_yaw_valid_count; // number of updates since the last invalid yaw estimate
1651 :
1652 : // logging timestamps
1653 : uint32_t lastLogTime_ms;
1654 : uint32_t lastUpdateTime_ms;
1655 : uint32_t lastEkfStateVarLogTime_ms;
1656 : uint32_t lastTimingLogTime_ms;
1657 :
1658 : // bits in EK3_AFFINITY
1659 : enum ekf_affinity {
1660 : EKF_AFFINITY_GPS = (1U<<0),
1661 : EKF_AFFINITY_BARO = (1U<<1),
1662 : EKF_AFFINITY_MAG = (1U<<2),
1663 : EKF_AFFINITY_ARSP = (1U<<3),
1664 : };
1665 :
1666 : // update selected_sensors for this core
1667 : void update_sensor_selection(void);
1668 : void update_gps_selection(void);
1669 : void update_mag_selection(void);
1670 : void update_baro_selection(void);
1671 : void update_airspeed_selection(void);
1672 :
1673 : // selected and preferred sensor instances. We separate selected
1674 : // from preferred so that calcGpsGoodToAlign() can ensure the
1675 : // preferred sensor is ready. Note that magSelectIndex is used for
1676 : // compass selection
1677 : uint8_t selected_gps;
1678 : uint8_t preferred_gps;
1679 : uint8_t selected_baro;
1680 : uint8_t selected_airspeed;
1681 :
1682 : // source reset handling
1683 : AP_NavEKF_Source::SourceXY posxy_source_last; // horizontal position source on previous iteration (used to detect a changes)
1684 : bool posxy_source_reset; // true when the horizontal position source has changed but the position has not yet been reset
1685 : AP_NavEKF_Source::SourceYaw yaw_source_last; // yaw source on previous iteration (used to detect a change)
1686 : bool yaw_source_reset; // true when the yaw source has changed but the yaw has not yet been reset
1687 :
1688 : // logging functions shared by cores:
1689 : void Log_Write_XKF1(uint64_t time_us) const;
1690 : void Log_Write_XKF2(uint64_t time_us) const;
1691 : void Log_Write_XKF3(uint64_t time_us) const;
1692 : void Log_Write_XKF4(uint64_t time_us) const;
1693 : void Log_Write_XKF5(uint64_t time_us) const;
1694 : void Log_Write_XKFS(uint64_t time_us) const;
1695 : void Log_Write_Quaternion(uint64_t time_us) const;
1696 : void Log_Write_Beacon(uint64_t time_us);
1697 : void Log_Write_BodyOdom(uint64_t time_us);
1698 : void Log_Write_State_Variances(uint64_t time_us);
1699 : void Log_Write_Timing(uint64_t time_us);
1700 : void Log_Write_GSF(uint64_t time_us);
1701 : };
|