mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 11:03:35 +08:00
ekf2: tighten terrain validity requirements
- require valid fusion from a range finder or optical flow before considering terrain valid again
This commit is contained in:
committed by
Mathieu Bresciani
parent
5b85859bfe
commit
34ee097f02
@@ -146,9 +146,10 @@ void Ekf::controlFusionModes(const imuSample &imu_delayed)
|
|||||||
// Additional horizontal velocity data from an auxiliary sensor can be fused
|
// Additional horizontal velocity data from an auxiliary sensor can be fused
|
||||||
controlAuxVelFusion(imu_delayed);
|
controlAuxVelFusion(imu_delayed);
|
||||||
#endif // CONFIG_EKF2_AUXVEL
|
#endif // CONFIG_EKF2_AUXVEL
|
||||||
//
|
|
||||||
#if defined(CONFIG_EKF2_TERRAIN)
|
#if defined(CONFIG_EKF2_TERRAIN)
|
||||||
controlTerrainFakeFusion();
|
controlTerrainFakeFusion();
|
||||||
|
updateTerrainValidity();
|
||||||
#endif // CONFIG_EKF2_TERRAIN
|
#endif // CONFIG_EKF2_TERRAIN
|
||||||
|
|
||||||
controlZeroInnovationHeadingUpdate();
|
controlZeroInnovationHeadingUpdate();
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
|
|
||||||
#if defined(CONFIG_EKF2_TERRAIN)
|
#if defined(CONFIG_EKF2_TERRAIN)
|
||||||
// terrain estimate
|
// terrain estimate
|
||||||
bool isTerrainEstimateValid() const;
|
bool isTerrainEstimateValid() const { return _terrain_valid; }
|
||||||
|
|
||||||
// get the estimated terrain vertical position relative to the NED origin
|
// get the estimated terrain vertical position relative to the NED origin
|
||||||
float getTerrainVertPos() const { return _state.terrain; };
|
float getTerrainVertPos() const { return _state.terrain; };
|
||||||
@@ -500,6 +500,8 @@ private:
|
|||||||
#if defined(CONFIG_EKF2_TERRAIN)
|
#if defined(CONFIG_EKF2_TERRAIN)
|
||||||
// Terrain height state estimation
|
// Terrain height state estimation
|
||||||
float _last_on_ground_posD{0.0f}; ///< last vertical position when the in_air status was false (m)
|
float _last_on_ground_posD{0.0f}; ///< last vertical position when the in_air status was false (m)
|
||||||
|
|
||||||
|
bool _terrain_valid{false};
|
||||||
#endif // CONFIG_EKF2_TERRAIN
|
#endif // CONFIG_EKF2_TERRAIN
|
||||||
|
|
||||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||||
@@ -733,6 +735,8 @@ private:
|
|||||||
float getTerrainVPos() const { return isTerrainEstimateValid() ? _state.terrain : _last_on_ground_posD; }
|
float getTerrainVPos() const { return isTerrainEstimateValid() ? _state.terrain : _last_on_ground_posD; }
|
||||||
void controlTerrainFakeFusion();
|
void controlTerrainFakeFusion();
|
||||||
|
|
||||||
|
void updateTerrainValidity();
|
||||||
|
|
||||||
# if defined(CONFIG_EKF2_RANGE_FINDER)
|
# if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||||
// update the terrain vertical position estimate using a height above ground measurement from the range finder
|
// update the terrain vertical position estimate using a height above ground measurement from the range finder
|
||||||
bool fuseHaglRng(estimator_aid_source1d_s &aid_src, bool update_height, bool update_terrain);
|
bool fuseHaglRng(estimator_aid_source1d_s &aid_src, bool update_height, bool update_terrain);
|
||||||
|
|||||||
@@ -75,9 +75,31 @@ void Ekf::controlTerrainFakeFusion()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ekf::isTerrainEstimateValid() const
|
void Ekf::updateTerrainValidity()
|
||||||
{
|
{
|
||||||
bool valid = false;
|
bool valid_opt_flow_terrain = false;
|
||||||
|
bool valid_rng_terrain = false;
|
||||||
|
bool valid_hagl_var = false;
|
||||||
|
|
||||||
|
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||||
|
|
||||||
|
if (_control_status.flags.opt_flow_terrain
|
||||||
|
&& isRecent(_aid_src_optical_flow.time_last_fuse, _params.hgt_fusion_timeout_max)
|
||||||
|
) {
|
||||||
|
valid_opt_flow_terrain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_EKF2_OPTICAL_FLOW
|
||||||
|
|
||||||
|
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||||
|
|
||||||
|
if (_control_status.flags.rng_terrain
|
||||||
|
&& isRecent(_aid_src_rng_hgt.time_last_fuse, _params.hgt_fusion_timeout_max)
|
||||||
|
) {
|
||||||
|
valid_rng_terrain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_EKF2_RANGE_FINDER
|
||||||
|
|
||||||
if (_time_last_terrain_fuse != 0) {
|
if (_time_last_terrain_fuse != 0) {
|
||||||
// Assume being valid when the uncertainty is small compared to the height above ground
|
// Assume being valid when the uncertainty is small compared to the height above ground
|
||||||
@@ -85,18 +107,20 @@ bool Ekf::isTerrainEstimateValid() const
|
|||||||
sym::ComputeHaglInnovVar(P, 0.f, &hagl_var);
|
sym::ComputeHaglInnovVar(P, 0.f, &hagl_var);
|
||||||
|
|
||||||
if (hagl_var < fmaxf(sq(0.1f * getHagl()), 0.2f)) {
|
if (hagl_var < fmaxf(sq(0.1f * getHagl()), 0.2f)) {
|
||||||
valid = true;
|
valid_hagl_var = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
if (!_terrain_valid) {
|
||||||
|
// require valid RNG or optical flow (+valid variance) to initially consider terrain valid
|
||||||
|
if (valid_rng_terrain
|
||||||
|
|| (valid_opt_flow_terrain && valid_hagl_var)
|
||||||
|
) {
|
||||||
|
_terrain_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Assume that the terrain estimate is always valid when direct observations are fused
|
} else {
|
||||||
if (_control_status.flags.rng_terrain && isRecent(_aid_src_rng_hgt.time_last_fuse, _params.hgt_fusion_timeout_max)) {
|
// terrain was previously valid, continue considering valid if variance is good
|
||||||
valid = true;
|
_terrain_valid = valid_hagl_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CONFIG_EKF2_RANGE_FINDER
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user