ekf2: enable multiple height sources fusion

Instead of having a single height source fused into the EKF and the
other ones "waiting" for a failure or the primary sensor, fuse all
sources in EKF2 at the same time. To prevent the sources from fighting against each
other, the "primary" source is set as reference and the other ones are
running a bias estimator in order to make all the secondary height
sources converge to the primary one.

If the reference isn't available, another one is automatically selected
from a priority list. This secondary reference keeps its current bias
estimate but stops updating it in order to be the new reference as close
as possible to the primary one.
This commit is contained in:
bresch
2022-08-24 09:16:11 -04:00
committed by Daniel Agar
parent f5f31006a0
commit 8fd79688c0
17 changed files with 573 additions and 456 deletions
+13 -2
View File
@@ -102,12 +102,23 @@ void Ekf::updateGpsPos(const gpsSample &gps_sample)
auto &gps_pos = _aid_src_gnss_pos;
resetEstimatorAidStatus(gps_pos);
const float height_measurement = gps_sample.hgt - getEkfGlobalOriginAltitude();
const float height_measurement_var = getGpsHeightVariance();
// save current bias and update bias estimator
const float bias = _gps_hgt_b_est.getBias();
const float bias_var = _gps_hgt_b_est.getBiasVar();
_gps_hgt_b_est.setMaxStateNoise(height_measurement_var);
_gps_hgt_b_est.setProcessNoiseStdDev(height_measurement_var); //TODO: update this
_gps_hgt_b_est.fuseBias(height_measurement - (-_state.pos(2)), height_measurement_var + P(9, 9));
Vector3f position;
position(0) = gps_sample.pos(0);
position(1) = gps_sample.pos(1);
// vertical position - gps measurement has opposite sign to earth z axis
position(2) = -(gps_sample.hgt - getEkfGlobalOriginAltitude() - _gps_hgt_offset);
position(2) = -(height_measurement - bias);
const float lower_limit = fmaxf(_params.gps_pos_noise, 0.01f);
@@ -125,7 +136,7 @@ void Ekf::updateGpsPos(const gpsSample &gps_sample)
obs_var(0) = obs_var(1) = sq(math::constrain(gps_sample.hacc, lower_limit, upper_limit));
}
obs_var(2) = getGpsHeightVariance();
obs_var(2) = height_measurement_var + bias_var;
// innovation gate size
float innov_gate = fmaxf(_params.gps_pos_innov_gate, 1.f);