@@ -330,7 +330,7 @@ bool Ekf::resetGlobalPosToExternalObservation(const double latitude, const doubl
330330 const Vector2f innov = (_gpos - gpos_corrected).xy ();
331331 const Vector2f innov_var = Vector2f (getStateVariance<State::pos>()) + obs_var;
332332
333- const float sq_gate = sq (5 .f ); // magic hardcoded gate
333+ const float sq_gate = sq (10 .f ); // magic hardcoded gate
334334 const float test_ratio = sq (innov (0 )) / (sq_gate * innov_var (0 )) + sq (innov (1 )) / (sq_gate * innov_var (1 ));
335335
336336 const bool innov_rejected = (test_ratio > 1 .f );
@@ -344,24 +344,38 @@ bool Ekf::resetGlobalPosToExternalObservation(const double latitude, const doubl
344344 _information_events.flags .reset_pos_to_ext_obs = true ;
345345
346346 resetHorizontalPositionTo (gpos_corrected.latitude_deg (), gpos_corrected.longitude_deg (), obs_var);
347+
348+ Vector2f new_vel = _state.vel .xy () - _state.wind_vel ;
349+ resetHorizontalVelocityTo (new_vel, Vector2f (P (State::vel.idx , State::vel.idx ), P (State::vel.idx + 1 , State::vel.idx + 1 )));
350+
351+ // bump up wind uncertainty to ensure velocity remains correct
352+ // eventual reset-by-fusion will have larger effect on wind state
353+ P.uncorrelateCovarianceSetVariance <2 >(State::wind_vel.idx , 10 .f );
354+ _state.wind_vel .setZero ();
347355 _last_known_gpos.setLatLon (gpos_corrected);
348356
349357 } else {
350358 ECL_INFO (" fuse external observation as position measurement" );
351359
352360 VectorState H;
353361 VectorState K;
362+ Vector2f innov_var_temp = Vector2f (getStateVariance<State::pos>()) + 0 .1f ;
354363
355364 for (unsigned index = 0 ; index < 2 ; index++) {
356- K = VectorState (P.row (State::pos.idx + index)) / innov_var (index);
365+ // Artificially setting the observation variance to a small value to
366+ // increase the Kalman gain to basically 1 to force a reset of the position
367+ // through fusion. This also enforces a strong correction of the correlated states
368+ // (e.g.: velocity, heading, wind)
369+ // The update of the covariance matrix is still performed with the correct observation variance
370+ // to not artificially reduce the state uncertainty and cross-correlations.
371+ K = VectorState (P.row (State::pos.idx + index)) / innov_var_temp (index);
357372 H (State::pos.idx + index) = 1 .f ;
358373
359- // Artificially set the position Kalman gain to 1 in order to force a reset
360- // of the position through fusion. This allows the EKF to use part of the information
361- // to continue learning the correlated states (e.g.: velocity, heading, wind) while
362- // performing a position reset.
363- K (State::pos.idx + index) = 1 .f ;
364- measurementUpdate (K, H, obs_var, innov (index));
374+ clearInhibitedStateKalmanGains (K);
375+ fuse (K, innov (index));
376+
377+ K = VectorState (P.row (State::pos.idx + index)) / innov_var (index);
378+ measurementUpdate (K, H, obs_var, 0 .f );
365379 H (State::pos.idx + index) = 0 .f ; // Reset the whole vector to 0
366380 }
367381
0 commit comments