mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-22 21:43:33 +08:00
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:
@@ -10,9 +10,19 @@ EkfWrapper::~EkfWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
void EkfWrapper::setBaroHeight()
|
||||
void EkfWrapper::setBaroHeightRef()
|
||||
{
|
||||
_ekf_params->vdist_sensor_type = VerticalHeightSensor::BARO;
|
||||
_ekf_params->height_sensor_ref |= HeightSensorRef::BARO;
|
||||
}
|
||||
|
||||
void EkfWrapper::enableBaroHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode |= SensorFusionMask::USE_BARO_HGT;
|
||||
}
|
||||
|
||||
void EkfWrapper::disableBaroHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode &= ~SensorFusionMask::USE_BARO_HGT;
|
||||
}
|
||||
|
||||
bool EkfWrapper::isIntendingBaroHeightFusion() const
|
||||
@@ -20,9 +30,19 @@ bool EkfWrapper::isIntendingBaroHeightFusion() const
|
||||
return _ekf->control_status_flags().baro_hgt;
|
||||
}
|
||||
|
||||
void EkfWrapper::setGpsHeight()
|
||||
void EkfWrapper::setGpsHeightRef()
|
||||
{
|
||||
_ekf_params->vdist_sensor_type = VerticalHeightSensor::GPS;
|
||||
_ekf_params->height_sensor_ref |= HeightSensorRef::GPS;
|
||||
}
|
||||
|
||||
void EkfWrapper::enableGpsHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode |= SensorFusionMask::USE_GPS_HGT;
|
||||
}
|
||||
|
||||
void EkfWrapper::disableGpsHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode &= ~SensorFusionMask::USE_GPS_HGT;
|
||||
}
|
||||
|
||||
bool EkfWrapper::isIntendingGpsHeightFusion() const
|
||||
@@ -30,9 +50,19 @@ bool EkfWrapper::isIntendingGpsHeightFusion() const
|
||||
return _ekf->control_status_flags().gps_hgt;
|
||||
}
|
||||
|
||||
void EkfWrapper::setRangeHeight()
|
||||
void EkfWrapper::setRangeHeightRef()
|
||||
{
|
||||
_ekf_params->vdist_sensor_type = VerticalHeightSensor::RANGE;
|
||||
_ekf_params->height_sensor_ref |= HeightSensorRef::RANGE;
|
||||
}
|
||||
|
||||
void EkfWrapper::enableRangeHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode |= SensorFusionMask::USE_RNG_HGT;
|
||||
}
|
||||
|
||||
void EkfWrapper::disableRangeHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode &= ~SensorFusionMask::USE_RNG_HGT;
|
||||
}
|
||||
|
||||
bool EkfWrapper::isIntendingRangeHeightFusion() const
|
||||
@@ -40,9 +70,19 @@ bool EkfWrapper::isIntendingRangeHeightFusion() const
|
||||
return _ekf->control_status_flags().rng_hgt;
|
||||
}
|
||||
|
||||
void EkfWrapper::setVisionHeight()
|
||||
void EkfWrapper::setVisionHeightRef()
|
||||
{
|
||||
_ekf_params->vdist_sensor_type = VerticalHeightSensor::EV;
|
||||
_ekf_params->height_sensor_ref |= HeightSensorRef::EV;
|
||||
}
|
||||
|
||||
void EkfWrapper::enableVisionHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode |= SensorFusionMask::USE_EXT_VIS_HGT;
|
||||
}
|
||||
|
||||
void EkfWrapper::disableVisionHeightFusion()
|
||||
{
|
||||
_ekf_params->fusion_mode &= ~SensorFusionMask::USE_EXT_VIS_HGT;
|
||||
}
|
||||
|
||||
bool EkfWrapper::isIntendingVisionHeightFusion() const
|
||||
|
||||
@@ -49,16 +49,24 @@ public:
|
||||
~EkfWrapper();
|
||||
|
||||
|
||||
void setBaroHeight();
|
||||
void setBaroHeightRef();
|
||||
void enableBaroHeightFusion();
|
||||
void disableBaroHeightFusion();
|
||||
bool isIntendingBaroHeightFusion() const;
|
||||
|
||||
void setGpsHeight();
|
||||
void setGpsHeightRef();
|
||||
void enableGpsHeightFusion();
|
||||
void disableGpsHeightFusion();
|
||||
bool isIntendingGpsHeightFusion() const;
|
||||
|
||||
void setRangeHeight();
|
||||
void setRangeHeightRef();
|
||||
void enableRangeHeightFusion();
|
||||
void disableRangeHeightFusion();
|
||||
bool isIntendingRangeHeightFusion() const;
|
||||
|
||||
void setVisionHeight();
|
||||
void setVisionHeightRef();
|
||||
void enableVisionHeightFusion();
|
||||
void disableVisionHeightFusion();
|
||||
bool isIntendingVisionHeightFusion() const;
|
||||
|
||||
void enableGpsFusion();
|
||||
|
||||
@@ -358,6 +358,7 @@ TEST_F(EkfFusionLogicTest, doBaroHeightFusion)
|
||||
// GIVEN: EKF that receives baro and GPS data
|
||||
_sensor_simulator.startGps();
|
||||
_sensor_simulator.runSeconds(11);
|
||||
_ekf_wrapper.enableGpsHeightFusion();
|
||||
|
||||
// THEN: EKF should intend to fuse baro by default
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());
|
||||
@@ -396,26 +397,28 @@ TEST_F(EkfFusionLogicTest, doBaroHeightFusionTimeout)
|
||||
|
||||
// BUT WHEN: GPS height data is also available
|
||||
_sensor_simulator.startGps();
|
||||
_ekf_wrapper.enableGpsHeightFusion();
|
||||
_sensor_simulator.runSeconds(11);
|
||||
reset_logging_checker.capturePostResetState();
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalVelocityResetCounterIncreasedBy(2));
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalPositionResetCounterIncreasedBy(1));
|
||||
|
||||
// AND: the baro data jumps by a lot
|
||||
_sensor_simulator._baro.setData(800.f);
|
||||
_sensor_simulator.runSeconds(20);
|
||||
reset_logging_checker.capturePostResetState();
|
||||
|
||||
// THEN: EKF should fallback to GPS height
|
||||
// THEN: EKF should fallback to GPS height (without reset)
|
||||
EXPECT_FALSE(_ekf_wrapper.isIntendingBaroHeightFusion());
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalVelocityResetCounterIncreasedBy(3));
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalPositionResetCounterIncreasedBy(2));
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalVelocityResetCounterIncreasedBy(2));
|
||||
EXPECT_TRUE(reset_logging_checker.isVerticalPositionResetCounterIncreasedBy(1));
|
||||
}
|
||||
|
||||
TEST_F(EkfFusionLogicTest, doGpsHeightFusion)
|
||||
{
|
||||
// WHEN: commanding GPS height and sending GPS data
|
||||
_ekf_wrapper.setGpsHeight();
|
||||
_ekf_wrapper.enableGpsHeightFusion();
|
||||
_sensor_simulator.startGps();
|
||||
_sensor_simulator.runSeconds(11);
|
||||
|
||||
@@ -434,7 +437,7 @@ TEST_F(EkfFusionLogicTest, doGpsHeightFusion)
|
||||
TEST_F(EkfFusionLogicTest, doRangeHeightFusion)
|
||||
{
|
||||
// WHEN: commanding range height and sending range data
|
||||
_ekf_wrapper.setRangeHeight();
|
||||
_ekf_wrapper.enableRangeHeightFusion();
|
||||
_sensor_simulator.startRangeFinder();
|
||||
_sensor_simulator.runSeconds(2.5f);
|
||||
// THEN: EKF should intend to fuse range height
|
||||
@@ -462,7 +465,7 @@ TEST_F(EkfFusionLogicTest, doRangeHeightFusion)
|
||||
TEST_F(EkfFusionLogicTest, doVisionHeightFusion)
|
||||
{
|
||||
// WHEN: commanding vision height and sending vision data
|
||||
_ekf_wrapper.setVisionHeight();
|
||||
_ekf_wrapper.enableVisionHeightFusion();
|
||||
_sensor_simulator.startExternalVision();
|
||||
_sensor_simulator.runSeconds(2);
|
||||
|
||||
|
||||
@@ -157,12 +157,12 @@ TEST_F(EkfGpsTest, gpsHgtToBaroFallback)
|
||||
_ekf_wrapper.enableFlowFusion();
|
||||
_sensor_simulator.startFlow();
|
||||
|
||||
_ekf_wrapper.setGpsHeight();
|
||||
_ekf_wrapper.enableGpsHeightFusion();
|
||||
|
||||
_sensor_simulator.runSeconds(1);
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeightFusion());
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingFlowFusion());
|
||||
EXPECT_FALSE(_ekf_wrapper.isIntendingBaroHeightFusion());
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingBaroHeightFusion());
|
||||
|
||||
// WHEN: stopping GPS fusion
|
||||
_sensor_simulator.stopGps();
|
||||
|
||||
@@ -80,7 +80,6 @@ public:
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
_ekf_wrapper.enableGpsFusion();
|
||||
_ekf_wrapper.setBaroHeight();
|
||||
_sensor_simulator.runSeconds(2); // Run to pass the GPS checks
|
||||
_sensor_simulator.runSeconds(3.5); // And a bit more to start the GPS fusion TODO: this shouldn't be necessary
|
||||
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsFusion());
|
||||
|
||||
Reference in New Issue
Block a user