PX4 Firmware
PX4 Autopilot Software http://px4.io
gps_checks.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2013 Estimation and Control Library (ECL). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name ECL nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file gps_checks.cpp
36  * Perform pre-flight and in-flight GPS quality checks
37  *
38  * @author Paul Riseborough <p_riseborough@live.com.au>
39  *
40  */
41 
42 #include "ekf.h"
43 
44 #include <ecl.h>
46 #include <mathlib/mathlib.h>
47 
48 // GPS pre-flight check bit locations
49 #define MASK_GPS_NSATS (1<<0)
50 #define MASK_GPS_PDOP (1<<1)
51 #define MASK_GPS_HACC (1<<2)
52 #define MASK_GPS_VACC (1<<3)
53 #define MASK_GPS_SACC (1<<4)
54 #define MASK_GPS_HDRIFT (1<<5)
55 #define MASK_GPS_VDRIFT (1<<6)
56 #define MASK_GPS_HSPD (1<<7)
57 #define MASK_GPS_VSPD (1<<8)
58 
59 bool Ekf::collect_gps(const gps_message &gps)
60 {
61  // Run GPS checks always
64  // If we have good GPS data set the origin's WGS-84 position to the last gps fix
65  double lat = gps.lat / 1.0e7;
66  double lon = gps.lon / 1.0e7;
68 
69  // if we are already doing aiding, correct for the change in position since the EKF started navigationg
71  double est_lat, est_lon;
72  map_projection_reproject(&_pos_ref, -_state.pos(0), -_state.pos(1), &est_lat, &est_lon);
74  }
75 
76  // Take the current GPS height and subtract the filter height above origin to estimate the GPS height of the origin
77  _gps_alt_ref = 1e-3f * (float)gps.alt + _state.pos(2);
80 
81  // set the magnetic field data returned by the geo library using the current GPS position
84  _mag_strength_gps = 0.01f * get_mag_strength(lat, lon);
85 
86  // request a reset of the yaw using the new declination
87  _mag_yaw_reset_req = true;
88  // save the horizontal and vertical position uncertainty of the origin
89  _gps_origin_eph = gps.eph;
90  _gps_origin_epv = gps.epv;
91 
92  // if the user has selected GPS as the primary height source, switch across to using it
94  ECL_INFO_TIMESTAMPED("EKF GPS checks passed (WGS-84 origin set, using GPS height)");
98  // zero the sensor offset
99  _hgt_sensor_offset = 0.0f;
100  } else {
101  ECL_INFO_TIMESTAMPED("EKF GPS checks passed (WGS-84 origin set)");
102  }
103  }
104 
105  // start collecting GPS if there is a 3D fix and the NED origin has been set
106  return _NED_origin_initialised && (gps.fix_type >= 3);
107 }
108 
109 /*
110  * Return true if the GPS solution quality is adequate to set an origin for the EKF
111  * and start GPS aiding.
112  * All activated checks must pass for 10 seconds.
113  * Checks are activated using the EKF2_GPS_CHECK bitmask parameter
114  * Checks are adjusted using the EKF2_REQ_* parameters
115 */
117 {
118  // Check the fix type
120 
121  // Check the number of satellites
123 
124  // Check the position dilution of precision
126 
127  // Check the reported horizontal and vertical position accuracy
130 
131  // Check the reported speed accuracy
133 
134  // check if GPS quality is degraded
135  _gps_error_norm = fmaxf((gps.eph / _params.req_hacc) , (gps.epv / _params.req_vacc));
137 
138  // Calculate time lapsed since last update, limit to prevent numerical errors and calculate a lowpass filter coefficient
139  const float filt_time_const = 10.0f;
140  float dt = fminf(fmaxf(float(_time_last_imu - _gps_pos_prev.timestamp) * 1e-6f, 0.001f), filt_time_const);
141  float filter_coef = dt / filt_time_const;
142 
143  // The following checks are only valid when the vehicle is at rest
144  double lat = gps.lat * 1.0e-7;
145  double lon = gps.lon * 1.0e-7;
147  // Calculate position movement since last measurement
148  float delta_posN = 0.0f;
149  float delta_PosE = 0.0f;
150 
151  // calculate position movement since last GPS fix
152  if (_gps_pos_prev.timestamp > 0) {
153  map_projection_project(&_gps_pos_prev, lat, lon, &delta_posN, &delta_PosE);
154 
155  } else {
156  // no previous position has been set
158  _gps_alt_prev = 1e-3f * (float)gps.alt;
159 
160  }
161 
162  // Calculate the horizontal drift velocity components and limit to 10x the threshold
163  float vel_limit = 10.0f * _params.req_hdrift;
164  float velN = fminf(fmaxf(delta_posN / dt, -vel_limit), vel_limit);
165  float velE = fminf(fmaxf(delta_PosE / dt, -vel_limit), vel_limit);
166 
167  // Apply a low pass filter
168  _gpsDriftVelN = velN * filter_coef + _gpsDriftVelN * (1.0f - filter_coef);
169  _gpsDriftVelE = velE * filter_coef + _gpsDriftVelE * (1.0f - filter_coef);
170 
171  // Calculate the horizontal drift speed and fail if too high
172  _gps_drift_metrics[0] = sqrtf(_gpsDriftVelN * _gpsDriftVelN + _gpsDriftVelE * _gpsDriftVelE);
173  _gps_check_fail_status.flags.hdrift = (_gps_drift_metrics[0] > _params.req_hdrift);
174 
175  // Calculate the vertical drift velocity and limit to 10x the threshold
176  float vz_drift_limit = 10.0f * _params.req_vdrift;
177  float gps_alt_m = 1e-3f * (float)gps.alt;
178  float velD = math::constrain(((_gps_alt_prev - gps_alt_m) / dt), -vz_drift_limit, vz_drift_limit);
179 
180  // Apply a low pass filter to the vertical velocity
181  _gps_drift_velD = velD * filter_coef + _gps_drift_velD * (1.0f - filter_coef);
182 
183  // Fail if the vertical drift speed is too high
184  _gps_drift_metrics[1] = fabsf(_gps_drift_velD);
185  _gps_check_fail_status.flags.vdrift = (_gps_drift_metrics[1] > _params.req_vdrift);
186 
187  // Check the magnitude of the filtered horizontal GPS velocity
188  float vxy_drift_limit = 10.0f * _params.req_hdrift;
189  float gps_velN = fminf(fmaxf(gps.vel_ned[0], -vxy_drift_limit), vxy_drift_limit);
190  float gps_velE = fminf(fmaxf(gps.vel_ned[1], -vxy_drift_limit), vxy_drift_limit);
191  _gps_velN_filt = gps_velN * filter_coef + _gps_velN_filt * (1.0f - filter_coef);
192  _gps_velE_filt = gps_velE * filter_coef + _gps_velE_filt * (1.0f - filter_coef);
193  _gps_drift_metrics[2] = sqrtf(_gps_velN_filt * _gps_velN_filt + _gps_velE_filt * _gps_velE_filt);
194  _gps_check_fail_status.flags.hspeed = (_gps_drift_metrics[2] > _params.req_hdrift);
195 
196  _gps_drift_updated = true;
197 
198  } else if (_control_status.flags.in_air) {
199  // These checks are always declared as passed when flying
200  // If on ground and moving, the last result before movement commenced is kept
204  _gps_drift_updated = false;
205 
206  } else {
207  // This is the case where the vehicle is on ground and IMU movement is blocking the drift calculation
208  _gps_drift_updated = true;
209 
210  }
211 
212  // save GPS fix for next time
214  _gps_alt_prev = 1e-3f * (float)gps.alt;
215 
216  // Check the filtered difference between GPS and EKF vertical velocity
217  float vz_diff_limit = 10.0f * _params.req_vdrift;
218  float vertVel = fminf(fmaxf((gps.vel_ned[2] - _state.vel(2)), -vz_diff_limit), vz_diff_limit);
219  _gps_velD_diff_filt = vertVel * filter_coef + _gps_velD_diff_filt * (1.0f - filter_coef);
221 
222  // assume failed first time through
223  if (_last_gps_fail_us == 0) {
225  }
226 
227  // if any user selected checks have failed, record the fail time
228  if (
239  ) {
241  } else {
243  }
244 
245  // continuous period without fail of x seconds required to return a healthy status
247 }
#define MASK_GPS_VDRIFT
Definition: gps_checks.cpp:55
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
struct estimator::filter_control_status_u::@60 flags
float eph
GPS horizontal position accuracy in m.
Definition: common.h:65
float req_hdrift
maximum acceptable horizontal drift speed (m/s)
Definition: common.h:321
Adapter / shim layer for system calls needed by ECL.
float _gpsDriftVelN
GPS north position derivative (m/sec)
Definition: ekf.h:411
#define MASK_GPS_HDRIFT
Definition: gps_checks.cpp:54
stateSample _state
state struct of the ekf running at the delayed time horizon
Definition: ekf.h:288
float epv
GPS vertical position accuracy in m.
Definition: common.h:66
#define VDIST_SENSOR_GPS
Use GPS height.
Definition: common.h:179
uint8_t nsats
number of satellites used
Definition: common.h:71
uint16_t nsats
1 - true if number of satellites used is insufficient
Definition: common.h:425
bool _mag_yaw_reset_req
true when a reset of the yaw using the magnetometer data has been requested
Definition: ekf.h:363
float _gps_alt_ref
WGS-84 height (m)
Definition: ekf.h:425
uint32_t _min_gps_health_time_us
GPS is marked as healthy only after this amount of time.
Definition: ekf.h:420
uint64_t _last_gps_pass_us
last system time in usec that the GPS passed it&#39;s checks
Definition: ekf.h:418
float sacc
GPS speed accuracy in m/s.
Definition: common.h:67
float _hgt_sensor_offset
set as necessary if desired to maintain the same height after a height reset (m)
Definition: ekf.h:435
uint64_t _last_gps_origin_time_us
true when all active GPS checks have passed
Definition: ekf.h:424
uint16_t hdrift
6 - true if horizontal drift is excessive (can only be used when stationary on ground) ...
Definition: common.h:430
uint32_t rng_hgt
10 - true when range finder height is being fused as a primary height reference
Definition: common.h:451
uint8_t fix_type
0-1: no fix, 2: 2D fix, 3: 3D fix, 4: RTCM code differential, 5: Real-Time Kinematic ...
Definition: common.h:64
uint32_t baro_hgt
9 - true when baro height is being fused as a primary height reference
Definition: common.h:450
uint64_t _last_gps_fail_us
last system time in usec that the GPS failed it&#39;s checks
Definition: ekf.h:417
float pdop
position dilution of precision
Definition: common.h:72
uint16_t sacc
5 - true if reported speed accuracy is insufficient
Definition: common.h:429
#define MASK_GPS_HSPD
Definition: gps_checks.cpp:56
bool gps_is_good(const gps_message &gps)
Definition: gps_checks.cpp:116
float _gps_velE_filt
GPS filtered East velocity (m/sec)
Definition: ekf.h:416
uint16_t vacc
4 - true if reported vertical accuracy is insufficient
Definition: common.h:428
float vel_ned[3]
GPS ground speed NED.
Definition: common.h:69
bool collect_gps(const gps_message &gps) override
Definition: gps_checks.cpp:59
uint16_t vspeed
9 - true if vertical speed error is excessive
Definition: common.h:433
float req_hacc
maximum acceptable horizontal position error (m)
Definition: common.h:316
int map_projection_init_timestamped(struct map_projection_reference_s *ref, double lat_0, double lon_0, uint64_t timestamp)
Initializes the map transformation given by the argument.
Definition: geo.cpp:90
float req_sacc
maximum acceptable speed error (m/s)
Definition: common.h:318
gps_check_fail_status_u _gps_check_fail_status
Definition: ekf.h:447
uint32_t ev_vel
24 - true when local earth frame velocity data from external vision measurements are being fused ...
Definition: common.h:465
uint16_t pdop
2 - true if position dilution of precision is insufficient
Definition: common.h:426
uint16_t vdrift
7 - true if vertical drift is excessive (can only be used when stationary on ground) ...
Definition: common.h:431
int _primary_hgt_source
specifies primary source of height data
Definition: ekf.h:473
#define MASK_GPS_VACC
Definition: gps_checks.cpp:52
bool _gps_checks_passed
Definition: ekf.h:421
int map_projection_reproject(const struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon)
Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system using...
Definition: geo.cpp:166
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
uint16_t hspeed
8 - true if horizontal speed is excessive (can only be used when stationary on ground) ...
Definition: common.h:432
float req_vacc
maximum acceptable vertical position error (m)
Definition: common.h:317
filter_control_status_u _control_status
Vector3f vel
NED velocity in earth frame in m/s.
Definition: common.h:369
int32_t lat
Latitude in 1E-7 degrees.
Definition: common.h:59
float _gps_drift_velD
GPS down position derivative (m/sec)
Definition: ekf.h:413
float req_vdrift
maximum acceptable vertical drift speed (m/s)
Definition: common.h:322
#define MASK_GPS_HACC
Definition: gps_checks.cpp:51
#define MASK_GPS_NSATS
Definition: gps_checks.cpp:49
struct estimator::gps_check_fail_status_u::@59 flags
float req_pdop
maximum acceptable position dilution of precision
Definition: common.h:320
#define MASK_GPS_SACC
Definition: gps_checks.cpp:53
Calculation / lookup table for Earth&#39;s magnetic field declination, inclination and strength...
Vector3f pos
NED position in earth frame in m.
Definition: common.h:370
float get_mag_inclination(float lat, float lon)
uint32_t opt_flow
3 - true if optical flow measurements are being fused
Definition: common.h:444
float get_mag_strength(float lat, float lon)
uint16_t fix
0 - true if the fix type is insufficient (no 3D solution)
Definition: common.h:424
float _gps_velD_diff_filt
GPS filtered Down velocity (m/sec)
Definition: ekf.h:414
#define MASK_GPS_PDOP
Definition: gps_checks.cpp:50
int map_projection_project(const struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
Definition: geo.cpp:132
float dt
Definition: px4io.c:73
uint32_t in_air
7 - true when the vehicle is airborne
Definition: common.h:448
uint16_t hacc
3 - true if reported horizontal accuracy is insufficient
Definition: common.h:427
int32_t alt
Altitude in 1E-3 meters (millimeters) above MSL.
Definition: common.h:61
uint32_t ev_pos
12 - true when local position data from external vision is being fused
Definition: common.h:453
uint32_t gps_hgt
11 - true when GPS height is being fused as a primary height reference
Definition: common.h:452
int32_t req_nsats
minimum acceptable satellite count
Definition: common.h:319
uint32_t gps
2 - true if GPS measurements are being fused
Definition: common.h:443
float _gpsDriftVelE
GPS east position derivative (m/sec)
Definition: ekf.h:412
float _gps_velN_filt
GPS filtered North velocity (m/sec)
Definition: ekf.h:415
float get_mag_declination(float lat, float lon)
#define MASK_GPS_VSPD
Definition: gps_checks.cpp:57
Class for core functions for ekf attitude and position estimator.
#define ECL_INFO_TIMESTAMPED
Definition: ecl.h:93
float _gps_error_norm
normalised gps error
Definition: ekf.h:419
int32_t gps_check_mask
bitmask used to control which GPS quality checks are used
Definition: common.h:315
int32_t lon
Longitude in 1E-7 degrees.
Definition: common.h:60