Skip to content

Commit b740a43

Browse files
committed
ekf2: reset manual position update through fusion
This provides a position reset-like behavior while still updating the correlated states through fusion of position information.
1 parent 582b8f0 commit b740a43

File tree

1 file changed

+23
-7
lines changed

1 file changed

+23
-7
lines changed

src/modules/ekf2/EKF/ekf.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ bool Ekf::resetGlobalPosToExternalObservation(const double latitude, const doubl
336336
const bool innov_rejected = (test_ratio > 1.f);
337337

338338
if (!_control_status.flags.in_air || (eph > 0.f && eph < 1.f) || innov_rejected) {
339-
// when on ground or accuracy chosen to be very low, we hard reset position
339+
// When on ground or accuracy chosen to be very low, we hard reset position
340340
// this allows the user to still send hard resets at any time
341341
ECL_INFO("reset position to external observation");
342342
_information_events.flags.reset_pos_to_ext_obs = true;
@@ -346,13 +346,29 @@ bool Ekf::resetGlobalPosToExternalObservation(const double latitude, const doubl
346346

347347
} else {
348348
ECL_INFO("fuse external observation as position measurement");
349-
fuseDirectStateMeasurement(innov(0), innov_var(0), obs_var, State::pos.idx + 0);
350-
fuseDirectStateMeasurement(innov(1), innov_var(1), obs_var, State::pos.idx + 1);
351349

352-
// Use the reset counters to inform the controllers about a potential large position jump
353-
// TODO: compute the actual position change
354-
_state_reset_status.reset_count.posNE++;
355-
_state_reset_status.posNE_change.zero();
350+
VectorState H;
351+
VectorState K;
352+
353+
for (unsigned index = 0; index < 2; index++) {
354+
K = VectorState(P.row(State::pos.idx + index)) / innov_var(index);
355+
H(State::pos.idx + index) = 1.f;
356+
357+
// Artificially set the position Kalman gain to 1 in order to force a reset
358+
// of the position through fusion. This allows the EKF to use part of the information
359+
// to continue learning the correlated states (e.g.: velocity, heading, wind) while
360+
// performing a position reset.
361+
K(State::pos.idx + index) = 1.f;
362+
measurementUpdate(K, H, obs_var, innov(index));
363+
H(State::pos.idx + index) = 0.f; // Reset the whole vector to 0
364+
}
365+
366+
// Use the reset counters to inform the controllers about a position jump
367+
updateHorizontalPositionResetStatus(-innov);
368+
369+
// Reset the positon of the output predictor to avoid a transient that would disturb the
370+
// position controller
371+
_output_predictor.resetLatLonTo(_gpos.latitude_deg(), _gpos.longitude_deg());
356372

357373
_time_last_hor_pos_fuse = _time_delayed_us;
358374
_last_known_gpos.setLatLon(gpos_corrected);

0 commit comments

Comments
 (0)