PX4 Firmware
PX4 Autopilot Software http://px4.io
gps.cpp
Go to the documentation of this file.
1 #include "../BlockLocalPositionEstimator.hpp"
3 #include <matrix/math.hpp>
4 
6 
7 // required number of samples for sensor
8 // to initialize
9 static const uint32_t REQ_GPS_INIT_COUNT = 10;
10 static const uint32_t GPS_TIMEOUT = 1000000; // 1.0 s
11 
13 {
14  // check for good gps signal
15  uint8_t nSat = _sub_gps.get().satellites_used;
16  float eph = _sub_gps.get().eph;
17  float epv = _sub_gps.get().epv;
18  uint8_t fix_type = _sub_gps.get().fix_type;
19 
20  if (
21  nSat < 6 ||
22  eph > _param_lpe_eph_max.get() ||
23  epv > _param_lpe_epv_max.get() ||
24  fix_type < 3
25  ) {
26  _gpsStats.reset();
27  return;
28  }
29 
30  // measure
32 
33  if (gpsMeasure(y) != OK) {
34  _gpsStats.reset();
35  return;
36  }
37 
38  // if finished
40  // get mean gps values
41  double gpsLat = _gpsStats.getMean()(0);
42  double gpsLon = _gpsStats.getMean()(1);
43  float gpsAlt = _gpsStats.getMean()(2);
44 
47  _gpsStats.reset();
48 
49  if (!_receivedGps) {
50  // this is the first time we have received gps
51  _receivedGps = true;
52 
53  // note we subtract X_z which is in down directon so it is
54  // an addition
55  _gpsAltOrigin = gpsAlt + _x(X_z);
56 
57  // find lat, lon of current origin by subtracting x and y
58  // if not using vision position since vision will
59  // have it's own origin, not necessarily where vehicle starts
60  if (!_map_ref.init_done) {
61  double gpsLatOrigin = 0;
62  double gpsLonOrigin = 0;
63  // reproject at current coordinates
64  map_projection_init(&_map_ref, gpsLat, gpsLon);
65  // find origin
66  map_projection_reproject(&_map_ref, -_x(X_x), -_x(X_y), &gpsLatOrigin, &gpsLonOrigin);
67  // reinit origin
68  map_projection_init(&_map_ref, gpsLatOrigin, gpsLonOrigin);
69  // set timestamp when origin was set to current time
71 
72  // always override alt origin on first GPS to fix
73  // possible baro offset in global altitude at init
75  _altOriginInitialized = true;
76  _altOriginGlobal = true;
77 
78  mavlink_and_console_log_info(&mavlink_log_pub, "[lpe] global origin init (gps) : lat %6.2f lon %6.2f alt %5.1f m",
79  gpsLatOrigin, gpsLonOrigin, double(_gpsAltOrigin));
80  }
81 
82  PX4_INFO("[lpe] gps init "
83  "lat %6.2f lon %6.2f alt %5.1f m",
84  gpsLat,
85  gpsLon,
86  double(gpsAlt));
87  }
88  }
89 }
90 
92 {
93  // gps measurement
94  y.setZero();
95  y(0) = _sub_gps.get().lat * 1e-7;
96  y(1) = _sub_gps.get().lon * 1e-7;
97  y(2) = _sub_gps.get().alt * 1e-3;
98  y(3) = (double)_sub_gps.get().vel_n_m_s;
99  y(4) = (double)_sub_gps.get().vel_e_m_s;
100  y(5) = (double)_sub_gps.get().vel_d_m_s;
101 
102  // increament sums for mean
103  _gpsStats.update(y);
105  return OK;
106 }
107 
109 {
110  // measure
111  Vector<double, n_y_gps> y_global;
112 
113  if (gpsMeasure(y_global) != OK) { return; }
114 
115  // gps measurement in local frame
116  double lat = y_global(Y_gps_x);
117  double lon = y_global(Y_gps_y);
118  float alt = y_global(Y_gps_z);
119  float px = 0;
120  float py = 0;
121  float pz = -(alt - _gpsAltOrigin);
122  map_projection_project(&_map_ref, lat, lon, &px, &py);
124  y.setZero();
125  y(Y_gps_x) = px;
126  y(Y_gps_y) = py;
127  y(Y_gps_z) = pz;
128  y(Y_gps_vx) = y_global(Y_gps_vx);
129  y(Y_gps_vy) = y_global(Y_gps_vy);
130  y(Y_gps_vz) = y_global(Y_gps_vz);
131 
132  // gps measurement matrix, measures position and velocity
134  C.setZero();
135  C(Y_gps_x, X_x) = 1;
136  C(Y_gps_y, X_y) = 1;
137  C(Y_gps_z, X_z) = 1;
138  C(Y_gps_vx, X_vx) = 1;
139  C(Y_gps_vy, X_vy) = 1;
140  C(Y_gps_vz, X_vz) = 1;
141 
142  // gps covariance matrix
144  R.setZero();
145 
146  // default to parameter, use gps cov if provided
147  float var_xy = _param_lpe_gps_xy.get() * _param_lpe_gps_xy.get();
148  float var_z = _param_lpe_gps_z.get() * _param_lpe_gps_z.get();
149  float var_vxy = _param_lpe_gps_vxy.get() * _param_lpe_gps_vxy.get();
150  float var_vz = _param_lpe_gps_vz.get() * _param_lpe_gps_vz.get();
151 
152  // if field is not below minimum, set it to the value provided
153  if (_sub_gps.get().eph > _param_lpe_gps_xy.get()) {
154  var_xy = _sub_gps.get().eph * _sub_gps.get().eph;
155  }
156 
157  if (_sub_gps.get().epv > _param_lpe_gps_z.get()) {
158  var_z = _sub_gps.get().epv * _sub_gps.get().epv;
159  }
160 
161  float gps_s_stddev = _sub_gps.get().s_variance_m_s;
162 
163  if (gps_s_stddev > _param_lpe_gps_vxy.get()) {
164  var_vxy = gps_s_stddev * gps_s_stddev;
165  }
166 
167  if (gps_s_stddev > _param_lpe_gps_vz.get()) {
168  var_vz = gps_s_stddev * gps_s_stddev;
169  }
170 
171  R(0, 0) = var_xy;
172  R(1, 1) = var_xy;
173  R(2, 2) = var_z;
174  R(3, 3) = var_vxy;
175  R(4, 4) = var_vxy;
176  R(5, 5) = var_vz;
177 
178  // get delayed x
179  uint8_t i_hist = 0;
180 
181  if (getDelayPeriods(_param_lpe_gps_delay.get(), &i_hist) < 0) { return; }
182 
183  Vector<float, n_x> x0 = _xDelay.get(i_hist);
184 
185  // residual
186  Vector<float, n_y_gps> r = y - C * x0;
187 
188  // residual covariance
190 
191  // publish innovations
192  for (size_t i = 0; i < 6; i++) {
193  _pub_innov.get().vel_pos_innov[i] = r(i);
194  _pub_innov.get().vel_pos_innov_var[i] = S(i, i);
195  }
196 
197  // residual covariance, (inverse)
198  Matrix<float, n_y_gps, n_y_gps> S_I = inv<float, n_y_gps>(S);
199 
200  // fault detection
201  float beta = (r.transpose() * (S_I * r))(0, 0);
202 
203  // artifically increase beta threshhold to prevent fault during landing
204  float beta_thresh = 1e2f;
205 
206  if (beta / BETA_TABLE[n_y_gps] > beta_thresh) {
207  if (!(_sensorFault & SENSOR_GPS)) {
208  mavlink_log_critical(&mavlink_log_pub, "[lpe] gps fault %3g %3g %3g %3g %3g %3g",
209  double(r(0) * r(0) / S_I(0, 0)), double(r(1) * r(1) / S_I(1, 1)), double(r(2) * r(2) / S_I(2, 2)),
210  double(r(3) * r(3) / S_I(3, 3)), double(r(4) * r(4) / S_I(4, 4)), double(r(5) * r(5) / S_I(5, 5)));
212  }
213 
214  } else if (_sensorFault & SENSOR_GPS) {
215  _sensorFault &= ~SENSOR_GPS;
217  }
218 
219  // kalman filter correction always for GPS
220  Matrix<float, n_x, n_y_gps> K = m_P * C.transpose() * S_I;
221  Vector<float, n_x> dx = K * r;
222  _x += dx;
223  m_P -= K * C * m_P;
224 }
225 
227 {
229  if (!(_sensorTimeout & SENSOR_GPS)) {
231  _gpsStats.reset();
232  mavlink_log_critical(&mavlink_log_pub, "[lpe] GPS timeout ");
233  }
234  }
235 }
static const float BETA_TABLE[7]
static const uint32_t REQ_GPS_INIT_COUNT
Definition: gps.cpp:9
matrix::Vector< Type, M > getMean()
Definition: BlockStats.hpp:85
int getDelayPeriods(float delay, uint8_t *periods)
int gpsMeasure(Vector< double, n_y_gps > &y)
Definition: gps.cpp:91
static const uint32_t GPS_TIMEOUT
Definition: gps.cpp:10
BlockStats< double, n_y_gps > _gpsStats
Matrix< Type, N, M > transpose() const
Definition: Matrix.hpp:353
struct map_projection_reference_s _map_ref
orb_advert_t mavlink_log_pub
uORB::SubscriptionData< vehicle_gps_position_s > _sub_gps
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
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
const T & get() const
int map_projection_project(const struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
Definition: geo.cpp:132
matrix::Matrix< Type, M, N > get(size_t delay)
Definition: BlockDelay.hpp:99
#define OK
Definition: uavcan_main.cpp:71
BlockDelay< float, n_x, 1, HIST_LEN > _xDelay
int map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0)
Initializes the map transformation given by the argument and sets the timestamp to now...
Definition: geo.cpp:105
uORB::PublicationData< ekf2_innovations_s > _pub_innov
void update(const matrix::Vector< Type, M > &u)
Definition: BlockStats.hpp:71