Skip to content

Commit

Permalink
ekf2: only allow ref sensor to reset height
Browse files Browse the repository at this point in the history
  • Loading branch information
bresch authored and dagar committed Aug 6, 2024
1 parent 8ed3489 commit d2478d0
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void Ekf::controlBaroHeightFusion(const imuSample &imu_sample)

const bool is_fusion_failing = isTimedOut(aid_src.time_last_fuse, _params.hgt_fusion_timeout_max);

if (isHeightResetRequired()) {
if (isHeightResetRequired() && (_height_sensor_ref == HeightSensor::BARO)) {
// All height sources are failing
ECL_WARN("%s height fusion reset required, all height sources failing", HGT_SRC_NAME);

Expand All @@ -142,10 +142,13 @@ void Ekf::controlBaroHeightFusion(const imuSample &imu_sample)
aid_src.time_last_fuse = imu_sample.time_us;

} else if (is_fusion_failing) {
// Some other height source is still working
ECL_WARN("stopping %s height fusion, fusion failing", HGT_SRC_NAME);
stopBaroHgtFusion();
_baro_hgt_faulty = true;

if (isRecent(_time_last_hgt_fuse, _params.hgt_fusion_timeout_max)) {
// Some other height source is still working
_baro_hgt_faulty = true;
}
}

} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void Ekf::controlEvHeightFusion(const imuSample &imu_sample, const extVisionSamp

const bool is_fusion_failing = isTimedOut(aid_src.time_last_fuse, _params.hgt_fusion_timeout_max);

if (isHeightResetRequired() && quality_sufficient) {
if (isHeightResetRequired() && quality_sufficient && (_height_sensor_ref == HeightSensor::EV)) {
// All height sources are failing
ECL_WARN("%s fusion reset required, all height sources failing", AID_SRC_NAME);
_information_events.flags.reset_hgt_to_ev = true;
Expand Down
4 changes: 2 additions & 2 deletions src/modules/ekf2/EKF/aid_sources/gnss/gnss_height_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ void Ekf::controlGnssHeightFusion(const gnssSample &gps_sample)

const bool is_fusion_failing = isTimedOut(aid_src.time_last_fuse, _params.hgt_fusion_timeout_max);

if (isHeightResetRequired()) {
if (isHeightResetRequired() && (_height_sensor_ref == HeightSensor::GNSS)) {
// All height sources are failing
ECL_WARN("%s height fusion reset required, all height sources failing", HGT_SRC_NAME);

_information_events.flags.reset_hgt_to_gps = true;
resetVerticalPositionTo(-(measurement - bias_est.getBias()), measurement_var);
resetVerticalPositionTo(aid_src.observation, measurement_var);
bias_est.setBias(_state.pos(2) + measurement);

aid_src.time_last_fuse = _time_delayed_us;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ void Ekf::controlRangeHaglFusion(const imuSample &imu_sample)

const bool is_fusion_failing = isTimedOut(aid_src.time_last_fuse, _params.hgt_fusion_timeout_max);

if (isHeightResetRequired() && _control_status.flags.rng_hgt) {
if (isHeightResetRequired() && _control_status.flags.rng_hgt && (_height_sensor_ref == HeightSensor::RANGE)) {
// All height sources are failing
ECL_WARN("%s height fusion reset required, all height sources failing", HGT_SRC_NAME);

Expand Down
1 change: 1 addition & 0 deletions src/modules/ekf2/test/sensor_simulator/gps.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Gps: public Sensor
void setPdop(const float pdop);

gnssSample getDefaultGpsData();
const gnssSample &getData() const { return _gps_data; }

private:
void send(uint64_t time) override;
Expand Down
87 changes: 87 additions & 0 deletions src/modules/ekf2/test/test_EKF_height_fusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,93 @@ TEST_F(EkfHeightFusionTest, gpsRefFailOver)
EXPECT_TRUE(_ekf->getHeightSensorRef() == HeightSensor::UNKNOWN);
}

TEST_F(EkfHeightFusionTest, gpsRefAllHgtFailReset)
{
// GIVEN: EKF that fuses GNSS (reference) and baro
_sensor_simulator.startBaro();
_sensor_simulator.startGps();
_ekf_wrapper.setGpsHeightRef();
_ekf_wrapper.enableBaroHeightFusion();
_ekf_wrapper.enableGpsHeightFusion();

_sensor_simulator.runSeconds(11);
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());
EXPECT_TRUE(_ekf->getHeightSensorRef() == HeightSensor::GNSS);

const Vector3f previous_position = _ekf->getPosition();

ResetLoggingChecker reset_logging_checker(_ekf);
reset_logging_checker.capturePreResetState();

// WHEN:
const float gnss_height_step = 10.f;
_sensor_simulator._gps.stepHeightByMeters(gnss_height_step);

const float baro_height_step = 5.f;
_sensor_simulator._baro.setData(_sensor_simulator._baro.getData() + baro_height_step);
_sensor_simulator.runSeconds(15);

// THEN: then the fusion of both sensors starts to fail and the height is reset to the
// reference sensor (GNSS)
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());

const Vector3f new_position = _ekf->getPosition();
EXPECT_NEAR(new_position(2), previous_position(2) - gnss_height_step, 0.2f);

// Also check the reset counters to make sure the reset logic triggered
reset_logging_checker.capturePostResetState();
EXPECT_TRUE(reset_logging_checker.isVerticalVelocityResetCounterIncreasedBy(1));
EXPECT_TRUE(reset_logging_checker.isVerticalPositionResetCounterIncreasedBy(1));
}

TEST_F(EkfHeightFusionTest, baroRefAllHgtFailReset)
{
// GIVEN: EKF that fuses GNSS and baro (reference)
_sensor_simulator.startBaro();
_sensor_simulator.startGps();
_ekf_wrapper.setBaroHeightRef();
_ekf_wrapper.enableBaroHeightFusion();
_ekf_wrapper.enableGpsHeightFusion();

_sensor_simulator.runSeconds(11);
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());
EXPECT_TRUE(_ekf->getHeightSensorRef() == HeightSensor::BARO);

const Vector3f previous_position = _ekf->getPosition();

ResetLoggingChecker reset_logging_checker(_ekf);
reset_logging_checker.capturePreResetState();

// WHEN:
const float gnss_height_step = 10.f;
_sensor_simulator._gps.stepHeightByMeters(gnss_height_step);

const float baro_height_step = 5.f;
_sensor_simulator._baro.setData(_sensor_simulator._baro.getData() + baro_height_step);
_sensor_simulator.runSeconds(20);

// THEN: then the fusion of both sensors starts to fail and the height is reset to the
// reference sensor (baro)
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());

const Vector3f new_position = _ekf->getPosition();
EXPECT_NEAR(new_position(2), previous_position(2) - baro_height_step, 0.2f);

// Also check the reset counters to make sure the reset logic triggered
reset_logging_checker.capturePostResetState();

// The velocity does not reset as baro only provides height measurement
EXPECT_TRUE(reset_logging_checker.isVerticalVelocityResetCounterIncreasedBy(0));

// The height resets twice in a row as the baro innovation is not corrected after a height
// reset and triggers a new reset at the next iteration
EXPECT_TRUE(reset_logging_checker.isVerticalPositionResetCounterIncreasedBy(2));
}

TEST_F(EkfHeightFusionTest, changeEkfOriginAlt)
{
_sensor_simulator.startBaro();
Expand Down

0 comments on commit d2478d0

Please sign in to comment.