mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-01 20:54:08 +08:00
rng height: reset to baro using common logic
The failsafe from rng height to baro height should occur after a reset to baro triggered by the controlHeightSensorTimeouts function and not in the fusion selector. Until now, the EKF was fusing baro measurements between rng updates if the range finder ODR was slower than the EKF update rate. This is not the case anymore as the height reset occurs after 5 seconds. The unit test has been extended to show this behavior.
This commit is contained in:
parent
03fed323ab
commit
c212975abe
@ -70,6 +70,12 @@ public:
|
||||
* and can be fused in the estimator
|
||||
*/
|
||||
virtual bool isDataHealthy() const = 0;
|
||||
|
||||
/*
|
||||
* return true if the sensor data rate is
|
||||
* stable and high enough
|
||||
*/
|
||||
virtual bool isRegularlySendingData() const = 0;
|
||||
};
|
||||
|
||||
} // namespace sensor
|
||||
|
||||
@ -989,8 +989,8 @@ void Ekf::controlHeightFusion()
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_baro_data_ready && !_baro_hgt_faulty) {
|
||||
startBaroHgtFusion();
|
||||
} else if (_control_status.flags.baro_hgt && _baro_data_ready && !_baro_hgt_faulty) {
|
||||
// fuse baro data if there was a reset to baro
|
||||
fuse_height = true;
|
||||
}
|
||||
|
||||
@ -1055,16 +1055,17 @@ void Ekf::controlHeightFusion()
|
||||
|
||||
updateBaroHgtOffset();
|
||||
|
||||
if (isTimedOut(_time_last_hgt_fuse, 2 * RNG_MAX_INTERVAL) && _control_status.flags.rng_hgt
|
||||
&& (!_range_sensor.isDataHealthy())) {
|
||||
if (_control_status.flags.rng_hgt
|
||||
&& isTimedOut(_time_last_hgt_fuse, 2 * RNG_MAX_INTERVAL)
|
||||
&& !_range_sensor.isDataHealthy()
|
||||
&& _range_sensor.isRegularlySendingData()
|
||||
&& !_control_status.flags.in_air) {
|
||||
|
||||
// If we are supposed to be using range finder data as the primary height sensor, have missed or rejected measurements
|
||||
// and are on the ground, then synthesise a measurement at the expected on ground value
|
||||
if (!_control_status.flags.in_air) {
|
||||
_range_sensor.setRange(_params.rng_gnd_clearance);
|
||||
_range_sensor.setDataReadiness(true);
|
||||
_range_sensor.setValidity(true); // bypass the checks
|
||||
}
|
||||
_range_sensor.setRange(_params.rng_gnd_clearance);
|
||||
_range_sensor.setDataReadiness(true);
|
||||
_range_sensor.setValidity(true); // bypass the checks
|
||||
|
||||
fuse_height = true;
|
||||
}
|
||||
|
||||
@ -64,9 +64,12 @@ void SensorRangeFinder::updateValidity(uint64_t current_time_us)
|
||||
|
||||
if (isSampleOutOfDate(current_time_us) || !isDataContinuous()) {
|
||||
_is_sample_valid = false;
|
||||
_is_regularly_sending_data = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_is_regularly_sending_data = true;
|
||||
|
||||
// Don't run the checks unless we have retrieved new data from the buffer
|
||||
if (_is_sample_ready) {
|
||||
_is_sample_valid = false;
|
||||
|
||||
@ -57,6 +57,7 @@ public:
|
||||
void runChecks(uint64_t current_time_us, const matrix::Dcmf &R_to_earth);
|
||||
bool isHealthy() const override { return _is_sample_valid; }
|
||||
bool isDataHealthy() const override { return _is_sample_ready && _is_sample_valid; }
|
||||
bool isRegularlySendingData() const override { return _is_regularly_sending_data; }
|
||||
|
||||
void setSample(const rangeSample &sample) {
|
||||
_sample = sample;
|
||||
@ -115,6 +116,7 @@ private:
|
||||
|
||||
bool _is_sample_ready{}; ///< true when new range finder data has fallen behind the fusion time horizon and is available to be fused
|
||||
bool _is_sample_valid{}; ///< true if range finder sample retrieved from buffer is valid
|
||||
bool _is_regularly_sending_data{false}; ///< true if the interval between two samples is less than the maximum expected interval
|
||||
uint64_t _time_last_valid_us{}; ///< time the last range finder measurement was ready (uSec)
|
||||
|
||||
/*
|
||||
|
||||
@ -337,17 +337,26 @@ TEST_F(EkfFusionLogicTest, doRangeHeightFusion)
|
||||
// WHEN: commanding range height and sending range data
|
||||
_ekf_wrapper.setRangeHeight();
|
||||
_sensor_simulator.startRangeFinder();
|
||||
_sensor_simulator.runSeconds(2.5);
|
||||
|
||||
_sensor_simulator.runSeconds(2.5f);
|
||||
// THEN: EKF should intend to fuse range height
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingRangeHeightFusion());
|
||||
|
||||
const float dt = 8e-3f;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_sensor_simulator.runSeconds(dt);
|
||||
// THEN: EKF should intend to fuse range height, even if
|
||||
// there is no new data at each EKF iteration (EKF rate > sensor rate)
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingRangeHeightFusion());
|
||||
}
|
||||
|
||||
// WHEN: stop sending range data
|
||||
_sensor_simulator.stopRangeFinder();
|
||||
_sensor_simulator.runSeconds(2.5);
|
||||
_sensor_simulator.runSeconds(5.1);
|
||||
|
||||
// THEN: EKF should stop to intend to use range height
|
||||
// and fall back to baro height
|
||||
EXPECT_FALSE(_ekf_wrapper.isIntendingRangeHeightFusion());
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());
|
||||
}
|
||||
|
||||
TEST_F(EkfFusionLogicTest, doVisionHeightFusion)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user