diff --git a/EKF/common.h b/EKF/common.h index 7e5a4b2fbe..0320ad3ef3 100644 --- a/EKF/common.h +++ b/EKF/common.h @@ -133,6 +133,7 @@ struct baroSample { struct rangeSample { float rng; ///< range (distance to ground) measurement (m) uint64_t time_us; ///< timestamp of the measurement (uSec) + uint8_t quality; ///< quality indicator between 0 and 255 }; struct airspeedSample { diff --git a/EKF/control.cpp b/EKF/control.cpp index 225901fdbc..f5b904f853 100644 --- a/EKF/control.cpp +++ b/EKF/control.cpp @@ -1198,7 +1198,7 @@ void Ekf::checkRangeDataValidity() return; } else { // reset fault status when we get new data - _rng_hgt_faulty = false; + _rng_hgt_faulty = (_range_sample_delayed.quality == 0); } // Check if excessively tilted @@ -1244,7 +1244,7 @@ void Ekf::checkRangeDataValidity() } _control_status.flags.rng_stuck = true; - _rng_hgt_faulty = true; + _rng_hgt_faulty = (_range_sample_delayed.quality == 0); } } else { diff --git a/EKF/estimator_interface.cpp b/EKF/estimator_interface.cpp index 21840747cc..0de754677c 100644 --- a/EKF/estimator_interface.cpp +++ b/EKF/estimator_interface.cpp @@ -314,7 +314,7 @@ void EstimatorInterface::setAirspeedData(uint64_t time_usec, float true_airspeed } } -void EstimatorInterface::setRangeData(uint64_t time_usec, float data) +void EstimatorInterface::setRangeData(uint64_t time_usec, float data, uint8_t quality) { if (!_initialised || _range_buffer_fail) { return; @@ -336,6 +336,7 @@ void EstimatorInterface::setRangeData(uint64_t time_usec, float data) rangeSample range_sample_new; range_sample_new.rng = data; range_sample_new.time_us = time_usec - _params.range_delay_ms * 1000; + range_sample_new.quality = quality; _time_last_range = time_usec; _range_buffer.push(range_sample_new); diff --git a/EKF/estimator_interface.h b/EKF/estimator_interface.h index 2ec93d8cc4..bbd85dc005 100644 --- a/EKF/estimator_interface.h +++ b/EKF/estimator_interface.h @@ -191,7 +191,7 @@ public: void setAirspeedData(uint64_t time_usec, float true_airspeed, float eas2tas); // set range data - void setRangeData(uint64_t time_usec, float data); + void setRangeData(uint64_t time_usec, float data, uint8_t quality); // set optical flow data // if optical flow sensor gyro delta angles are not available, set gyroXYZ vector fields to NaN and the EKF will use its internal delta angle data instead diff --git a/EKF/terrain_estimator.cpp b/EKF/terrain_estimator.cpp index f975cca2a5..3027874317 100644 --- a/EKF/terrain_estimator.cpp +++ b/EKF/terrain_estimator.cpp @@ -48,7 +48,7 @@ bool Ekf::initHagl() // get most recent range measurement from buffer const rangeSample &latest_measurement = _range_buffer.get_newest(); - if ((_time_last_imu - latest_measurement.time_us) < (uint64_t)2e5 && _R_rng_to_earth_2_2 > _params.range_cos_max_tilt) { + if (!_rng_hgt_faulty && (_time_last_imu - latest_measurement.time_us) < (uint64_t)2e5 && _R_rng_to_earth_2_2 > _params.range_cos_max_tilt) { // if we have a fresh measurement, use it to initialise the terrain estimator _terrain_vpos = _state.pos(2) + latest_measurement.rng * _R_rng_to_earth_2_2; // initialise state variance to variance of measurement @@ -66,7 +66,7 @@ bool Ekf::initHagl() // Use the ground clearance value as our uncertainty _terrain_var = sq(_params.rng_gnd_clearance); // this is a guess - return false; + return true; } else { // no information - cannot initialise @@ -99,8 +99,9 @@ void Ekf::runTerrainEstimator() // if stationary on the ground and no range data for over a second, fake a measurement // to handle bad range finder data when on ground - if (!_range_data_ready && !_control_status.flags.in_air && _vehicle_at_rest && (_time_last_imu - _time_last_hagl_fuse) > (uint64_t)1E6) { + if (_rng_hgt_faulty && !_range_data_ready && !_control_status.flags.in_air && _vehicle_at_rest && (_time_last_imu - _time_last_hagl_fuse) > (uint64_t)1E6) { _range_data_ready = true; + _rng_hgt_faulty = false; _range_sample_delayed.rng = _params.rng_gnd_clearance; }