mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-30 07:23:33 +08:00
EKF: Consolidate range finder checking
This brings all the range finder data checks (excluding innovation consistency checks) into one place and eliminates the need to perform range checking external to the library. The hard coded optical flow tilt limit is changed to use the same value as the range finder. Variable names are changed to make a clear distinction between the max/min values calculated by the stuck range check and the max/min valid values for the sensor.
This commit is contained in:
committed by
Lorenz Meier
parent
e1661a92c3
commit
4d59c834eb
+1
-1
@@ -282,7 +282,7 @@ struct parameters {
|
||||
float max_vel_for_range_aid{1.0f}; ///< maximum ground velocity for which we allow to use the range finder as height source (if range_aid == 1)
|
||||
int32_t range_aid{0}; ///< allow switching primary height source to range finder if certian conditions are met
|
||||
float range_aid_innov_gate{1.0f}; ///< gate size used for innovation consistency checks for range aid fusion
|
||||
float range_cos_max_tilt{0.7071f}; ///< cosine of the maximum tilt angle from the vertical that permits use of range finder data
|
||||
float range_cos_max_tilt{0.7071f}; ///< cosine of the maximum tilt angle from the vertical that permits use of range finder and flow data
|
||||
|
||||
// vision position fusion
|
||||
float ev_innov_gate{5.0f}; ///< vision estimator fusion innovation consistency gate size (STD)
|
||||
|
||||
+42
-19
@@ -107,21 +107,21 @@ void Ekf::controlFusionModes()
|
||||
}
|
||||
|
||||
// calculate 2,2 element of rotation matrix from sensor frame to earth frame
|
||||
// this is required for use of range finder and flow data
|
||||
_R_rng_to_earth_2_2 = _R_to_earth(2, 0) * _sin_tilt_rng + _R_to_earth(2, 2) * _cos_tilt_rng;
|
||||
|
||||
// Get range data from buffer and check that is within limits and the vehicle is not excessively tilted
|
||||
_range_data_ready = _range_buffer.pop_first_older_than(_imu_sample_delayed.time_us, &_range_sample_delayed)
|
||||
&& (_R_rng_to_earth_2_2 > _params.range_cos_max_tilt)
|
||||
&& (_range_sample_delayed.rng >= _rng_min_distance)
|
||||
&& (_range_sample_delayed.rng <= _rng_max_distance);
|
||||
// Get range data from buffer and check validity
|
||||
_range_data_ready = _range_buffer.pop_first_older_than(_imu_sample_delayed.time_us, &_range_sample_delayed);
|
||||
|
||||
checkForStuckRange();
|
||||
if (_range_data_ready) {
|
||||
checkRangeDataValidity();
|
||||
}
|
||||
|
||||
// We don't fuse flow data immediately becasue we have to wait for the mid integration point to fall behind the fusion time horizon.
|
||||
// We don't fuse flow data immediately because we have to wait for the mid integration point to fall behind the fusion time horizon.
|
||||
// This means we stop looking for new data until the old data has been fused.
|
||||
if (!_flow_data_ready) {
|
||||
_flow_data_ready = _flow_buffer.pop_first_older_than(_imu_sample_delayed.time_us, &_flow_sample_delayed)
|
||||
&& (_R_to_earth(2, 2) > 0.7071f);
|
||||
&& (_R_to_earth(2, 2) > _params.range_cos_max_tilt);
|
||||
}
|
||||
|
||||
_ev_data_ready = _ext_vision_buffer.pop_first_older_than(_imu_sample_delayed.time_us, &_ev_sample_delayed);
|
||||
@@ -1140,33 +1140,56 @@ void Ekf::rangeAidConditionsMet()
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::checkForStuckRange()
|
||||
void Ekf::checkRangeDataValidity()
|
||||
{
|
||||
if (_range_data_ready && _range_sample_delayed.time_us - _time_last_rng_ready > (uint64_t)10e6 &&
|
||||
// Check if excessively tilted
|
||||
if (_R_rng_to_earth_2_2 < _params.range_cos_max_tilt) {
|
||||
_range_data_ready = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if out of range
|
||||
if ((_range_sample_delayed.rng > _rng_valid_max_val)
|
||||
|| (_range_sample_delayed.rng < _rng_valid_min_val)) {
|
||||
if (_control_status.flags.in_air) {
|
||||
_range_data_ready = false;
|
||||
return;
|
||||
} else {
|
||||
// Range finders can fail to provide valid readings when resting on the ground
|
||||
// or being handled by the user, which prevents use of as a primary height sensor.
|
||||
// To work around this issue, we replace out of range data with the expected on ground value.
|
||||
_range_sample_delayed.rng = _params.rng_gnd_clearance;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for "stuck" range finder measurements when rng was not valid for certain period
|
||||
// This handles a failure mode observed with some lidar sensors
|
||||
if (_range_sample_delayed.time_us - _time_last_rng_ready > (uint64_t)10e6 &&
|
||||
_control_status.flags.in_air) {
|
||||
|
||||
_control_status.flags.rng_stuck = true;
|
||||
|
||||
//require a variance of rangefinder values to check for "stuck" measurements
|
||||
if (_rng_check_max_val - _rng_check_min_val > 1.0f) {
|
||||
// require a variance of rangefinder values to check for "stuck" measurements
|
||||
if (_rng_stuck_max_val - _rng_stuck_min_val > 1.0f) {
|
||||
_time_last_rng_ready = _range_sample_delayed.time_us;
|
||||
_rng_check_min_val = 0.0f;
|
||||
_rng_check_max_val = 0.0f;
|
||||
_rng_stuck_min_val = 0.0f;
|
||||
_rng_stuck_max_val = 0.0f;
|
||||
_control_status.flags.rng_stuck = false;
|
||||
|
||||
} else {
|
||||
if (_range_sample_delayed.rng > _rng_check_max_val) {
|
||||
_rng_check_max_val = _range_sample_delayed.rng;
|
||||
if (_range_sample_delayed.rng > _rng_stuck_max_val) {
|
||||
_rng_stuck_max_val = _range_sample_delayed.rng;
|
||||
}
|
||||
|
||||
if (_rng_check_min_val < 0.1f || _range_sample_delayed.rng < _rng_check_min_val) {
|
||||
_rng_check_min_val = _range_sample_delayed.rng;
|
||||
if (_rng_stuck_min_val < 0.1f || _range_sample_delayed.rng < _rng_stuck_min_val) {
|
||||
_rng_stuck_min_val = _range_sample_delayed.rng;
|
||||
}
|
||||
|
||||
_range_data_ready = false;
|
||||
}
|
||||
|
||||
} else if (_range_data_ready) {
|
||||
} else {
|
||||
_time_last_rng_ready = _range_sample_delayed.time_us;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,9 +443,9 @@ private:
|
||||
bool _range_aid_mode_enabled{false}; ///< true when range finder can be used in flight as the height reference instead of the primary height sensor
|
||||
bool _range_aid_mode_selected{false}; ///< true when range finder is being used as the height reference instead of the primary height sensor
|
||||
|
||||
// variables used to check for "stuck" rng data
|
||||
float _rng_check_min_val{0.0f}; ///< minimum value for new rng measurement when being stuck
|
||||
float _rng_check_max_val{0.0f}; ///< maximum value for new rng measurement when being stuck
|
||||
// variables used to check range finder validity data
|
||||
float _rng_stuck_min_val{0.0f}; ///< minimum value for new rng measurement when being stuck
|
||||
float _rng_stuck_max_val{0.0f}; ///< maximum value for new rng measurement when being stuck
|
||||
|
||||
// update the real time complementary filter states. This includes the prediction
|
||||
// and the correction step
|
||||
@@ -598,7 +598,7 @@ private:
|
||||
void rangeAidConditionsMet();
|
||||
|
||||
// check for "stuck" range finder measurements when rng was not valid for certain period
|
||||
void checkForStuckRange();
|
||||
void checkRangeDataValidity();
|
||||
|
||||
// return the square of two floating point numbers - used in auto coded sections
|
||||
static constexpr float sq(float var) { return var * var; }
|
||||
|
||||
+2
-2
@@ -1060,9 +1060,9 @@ hagl_max : Maximum height above ground (meters). NaN when limiting is not needed
|
||||
void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max)
|
||||
{
|
||||
// Calculate range finder limits
|
||||
float rangefinder_hagl_min = _rng_min_distance;
|
||||
float rangefinder_hagl_min = _rng_valid_min_val;
|
||||
// Allow use of 75% of rangefinder maximum range to allow for angular motion
|
||||
float rangefinder_hagl_max = 0.75f * _rng_max_distance;
|
||||
float rangefinder_hagl_max = 0.75f * _rng_valid_max_val;
|
||||
|
||||
// Calculate optical flow limits
|
||||
// Allow ground relative velocity to use 50% of available flow sensor range to allow for angular motion
|
||||
|
||||
@@ -237,8 +237,8 @@ public:
|
||||
// set sensor limitations reported by the rangefinder
|
||||
void set_rangefinder_limits(float min_distance, float max_distance)
|
||||
{
|
||||
_rng_min_distance = min_distance;
|
||||
_rng_max_distance = max_distance;
|
||||
_rng_valid_min_val = min_distance;
|
||||
_rng_valid_max_val = max_distance;
|
||||
}
|
||||
|
||||
// set sensor limitations reported by the optical flow sensor
|
||||
@@ -429,8 +429,8 @@ protected:
|
||||
float _air_density{CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C}; // air density (kg/m**3)
|
||||
|
||||
// Sensor limitations
|
||||
float _rng_min_distance{0.0f}; ///< minimum distance that the rangefinder can measure (m)
|
||||
float _rng_max_distance{0.0f}; ///< maximum distance that the rangefinder can measure (m)
|
||||
float _rng_valid_min_val{0.0f}; ///< minimum distance that the rangefinder can measure (m)
|
||||
float _rng_valid_max_val{0.0f}; ///< maximum distance that the rangefinder can measure (m)
|
||||
float _flow_max_rate{0.0f}; ///< maximum angular flow rate that the optical flow sensor can measure (rad/s)
|
||||
float _flow_min_distance{0.0f}; ///< minimum distance that the optical flow sensor can operate at (m)
|
||||
float _flow_max_distance{0.0f}; ///< maximum distance that the optical flow sensor can operate at (m)
|
||||
|
||||
Reference in New Issue
Block a user