mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-16 15:43:37 +08:00
ekf2: update flags (in_air, at_rest, etc) on delayed time horizon (#20576)
- in a lot of cases this won't really matter, although you can see it in logs (especially with things like vehicle_at_rest), but it's something we might as well do properly Co-authored-by: Mathieu Bresciani <brescianimathieu@gmail.com>
This commit is contained in:
co-authored by
Mathieu Bresciani
parent
b0e1cc72f7
commit
639d1ddca2
@@ -254,6 +254,14 @@ struct auxVelSample {
|
||||
Vector2f velVar{}; ///< estimated error variance of the NE velocity (m/sec)**2
|
||||
};
|
||||
|
||||
struct systemFlagUpdate {
|
||||
uint64_t time_us{};
|
||||
bool at_rest{false};
|
||||
bool in_air{true};
|
||||
bool is_fixed_wing{false};
|
||||
bool gnd_effect{false};
|
||||
};
|
||||
|
||||
struct stateSample {
|
||||
Quatf quat_nominal{}; ///< quaternion defining the rotation from body to earth frame
|
||||
Vector3f vel{}; ///< NED velocity in earth frame in m/s
|
||||
|
||||
@@ -48,6 +48,22 @@ void Ekf::controlFusionModes()
|
||||
// Store the status to enable change detection
|
||||
_control_status_prev.value = _control_status.value;
|
||||
|
||||
if (_system_flag_buffer) {
|
||||
systemFlagUpdate system_flags_delayed;
|
||||
|
||||
if (_system_flag_buffer->pop_first_older_than(_imu_sample_delayed.time_us, &system_flags_delayed)) {
|
||||
|
||||
set_vehicle_at_rest(system_flags_delayed.at_rest);
|
||||
set_in_air_status(system_flags_delayed.in_air);
|
||||
|
||||
set_is_fixed_wing(system_flags_delayed.is_fixed_wing);
|
||||
|
||||
if (system_flags_delayed.gnd_effect) {
|
||||
set_gnd_effect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// monitor the tilt alignment
|
||||
if (!_control_status.flags.tilt_align) {
|
||||
// whilst we are aligning the tilt, monitor the variances
|
||||
|
||||
@@ -410,6 +410,42 @@ void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
|
||||
}
|
||||
}
|
||||
|
||||
void EstimatorInterface::setSystemFlagData(const systemFlagUpdate &system_flags)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_system_flag_buffer == nullptr) {
|
||||
_system_flag_buffer = new RingBuffer<systemFlagUpdate>(_obs_buffer_length);
|
||||
|
||||
if (_system_flag_buffer == nullptr || !_system_flag_buffer->valid()) {
|
||||
delete _system_flag_buffer;
|
||||
_system_flag_buffer = nullptr;
|
||||
printBufferAllocationFailed("system flag");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_system_flag_buffer->push(system_flags);
|
||||
|
||||
const int64_t time_us = system_flags.time_us
|
||||
- static_cast<int64_t>(_dt_ekf_avg * 5e5f); // seconds to microseconds divided by 2
|
||||
|
||||
// limit data rate to prevent data being lost
|
||||
if (time_us >= static_cast<int64_t>(_system_flag_buffer->get_newest().time_us + _min_obs_interval_us)) {
|
||||
|
||||
systemFlagUpdate system_flags_new{system_flags};
|
||||
system_flags_new.time_us = time_us;
|
||||
|
||||
_system_flag_buffer->push(system_flags_new);
|
||||
|
||||
} else {
|
||||
ECL_WARN("system flag update too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _system_flag_buffer->get_newest().time_us, _min_obs_interval_us);
|
||||
}
|
||||
}
|
||||
|
||||
void EstimatorInterface::setDragData(const imuSample &imu)
|
||||
{
|
||||
// down-sample the drag specific force data by accumulating and calculating the mean when
|
||||
|
||||
@@ -101,6 +101,8 @@ public:
|
||||
|
||||
void setAuxVelData(const auxVelSample &auxvel_sample);
|
||||
|
||||
void setSystemFlagData(const systemFlagUpdate &system_flags);
|
||||
|
||||
// return a address to the parameters struct
|
||||
// in order to give access to the application
|
||||
parameters *getParamHandle() { return &_params; }
|
||||
@@ -355,9 +357,10 @@ protected:
|
||||
uint64_t _time_last_in_air{0}; ///< last time we were in air (uSec)
|
||||
|
||||
// data buffer instances
|
||||
RingBuffer<imuSample> _imu_buffer{12}; // buffer length 12 with default parameters
|
||||
RingBuffer<outputSample> _output_buffer{12};
|
||||
RingBuffer<outputVert> _output_vert_buffer{12};
|
||||
static constexpr uint8_t kBufferLengthDefault = 12;
|
||||
RingBuffer<imuSample> _imu_buffer{kBufferLengthDefault};
|
||||
RingBuffer<outputSample> _output_buffer{kBufferLengthDefault};
|
||||
RingBuffer<outputVert> _output_vert_buffer{kBufferLengthDefault};
|
||||
|
||||
RingBuffer<gpsSample> *_gps_buffer{nullptr};
|
||||
RingBuffer<magSample> *_mag_buffer{nullptr};
|
||||
@@ -368,6 +371,7 @@ protected:
|
||||
RingBuffer<extVisionSample> *_ext_vision_buffer{nullptr};
|
||||
RingBuffer<dragSample> *_drag_buffer{nullptr};
|
||||
RingBuffer<auxVelSample> *_auxvel_buffer{nullptr};
|
||||
RingBuffer<systemFlagUpdate> *_system_flag_buffer{nullptr};
|
||||
|
||||
uint64_t _time_last_gps_buffer_push{0};
|
||||
uint64_t _time_last_gps_yaw_buffer_push{0};
|
||||
|
||||
+49
-47
@@ -530,53 +530,6 @@ void EKF2::Run()
|
||||
_last_time_slip_us = 0;
|
||||
}
|
||||
|
||||
// update all other topics if they have new data
|
||||
if (_status_sub.updated()) {
|
||||
vehicle_status_s vehicle_status;
|
||||
|
||||
if (_status_sub.copy(&vehicle_status)) {
|
||||
const bool is_fixed_wing = (vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
|
||||
|
||||
// let the EKF know if the vehicle motion is that of a fixed wing (forward flight only relative to wind)
|
||||
_ekf.set_is_fixed_wing(is_fixed_wing);
|
||||
|
||||
_preflt_checker.setVehicleCanObserveHeadingInFlight(vehicle_status.vehicle_type !=
|
||||
vehicle_status_s::VEHICLE_TYPE_ROTARY_WING);
|
||||
}
|
||||
}
|
||||
|
||||
if (_vehicle_land_detected_sub.updated()) {
|
||||
vehicle_land_detected_s vehicle_land_detected;
|
||||
|
||||
if (_vehicle_land_detected_sub.copy(&vehicle_land_detected)) {
|
||||
|
||||
_ekf.set_vehicle_at_rest(vehicle_land_detected.at_rest);
|
||||
|
||||
if (vehicle_land_detected.in_ground_effect) {
|
||||
_ekf.set_gnd_effect();
|
||||
}
|
||||
|
||||
const bool was_in_air = _ekf.control_status_flags().in_air;
|
||||
const bool in_air = !vehicle_land_detected.landed;
|
||||
|
||||
if (!was_in_air && in_air) {
|
||||
// takeoff
|
||||
_ekf.set_in_air_status(true);
|
||||
|
||||
// reset learned sensor calibrations on takeoff
|
||||
_accel_cal = {};
|
||||
_gyro_cal = {};
|
||||
_mag_cal = {};
|
||||
|
||||
_preflt_checker.reset();
|
||||
|
||||
} else if (was_in_air && !in_air) {
|
||||
// landed
|
||||
_ekf.set_in_air_status(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ekf2_timestamps (using 0.1 ms relative timestamps)
|
||||
ekf2_timestamps_s ekf2_timestamps {
|
||||
.timestamp = now,
|
||||
@@ -595,6 +548,7 @@ void EKF2::Run()
|
||||
UpdateGpsSample(ekf2_timestamps);
|
||||
UpdateMagSample(ekf2_timestamps);
|
||||
UpdateRangeSample(ekf2_timestamps);
|
||||
UpdateSystemFlagsSample(ekf2_timestamps);
|
||||
|
||||
vehicle_odometry_s ev_odom;
|
||||
const bool new_ev_odom = UpdateExtVisionSample(ekf2_timestamps, ev_odom);
|
||||
@@ -1037,6 +991,11 @@ void EKF2::PublishInnovations(const hrt_abstime ×tamp)
|
||||
_estimator_innovations_pub.publish(innovations);
|
||||
|
||||
// calculate noise filtered velocity innovations which are used for pre-flight checking
|
||||
if (_ekf.control_status_prev_flags().in_air != _ekf.control_status_flags().in_air) {
|
||||
// fully reset on takeoff or landing
|
||||
_preflt_checker.reset();
|
||||
}
|
||||
|
||||
if (!_ekf.control_status_flags().in_air) {
|
||||
// TODO: move to run before publications
|
||||
_preflt_checker.setUsingGpsAiding(_ekf.control_status_flags().gps);
|
||||
@@ -1049,6 +1008,8 @@ void EKF2::PublishInnovations(const hrt_abstime ×tamp)
|
||||
_preflt_checker.setUsingRngHgtAiding(_ekf.control_status_flags().rng_hgt);
|
||||
_preflt_checker.setUsingEvHgtAiding(_ekf.control_status_flags().ev_hgt);
|
||||
|
||||
_preflt_checker.setVehicleCanObserveHeadingInFlight(_ekf.control_status_flags().fixed_wing);
|
||||
|
||||
_preflt_checker.update(_ekf.get_imu_sample_delayed().delta_ang_dt, innovations);
|
||||
}
|
||||
}
|
||||
@@ -2107,9 +2068,50 @@ void EKF2::UpdateRangeSample(ekf2_timestamps_s &ekf2_timestamps)
|
||||
}
|
||||
}
|
||||
|
||||
void EKF2::UpdateSystemFlagsSample(ekf2_timestamps_s &ekf2_timestamps)
|
||||
{
|
||||
// EKF system flags
|
||||
if (_status_sub.updated() || _vehicle_land_detected_sub.updated()) {
|
||||
|
||||
systemFlagUpdate flags{};
|
||||
flags.time_us = ekf2_timestamps.timestamp;
|
||||
|
||||
// vehicle_status
|
||||
vehicle_status_s vehicle_status;
|
||||
|
||||
if (_status_sub.copy(&vehicle_status)
|
||||
&& (ekf2_timestamps.timestamp < vehicle_status.timestamp + 3_s)) {
|
||||
|
||||
// initially set in_air from arming_state (will be overridden if land detector is available)
|
||||
flags.in_air = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
|
||||
|
||||
// let the EKF know if the vehicle motion is that of a fixed wing (forward flight only relative to wind)
|
||||
flags.is_fixed_wing = (vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
|
||||
}
|
||||
|
||||
// vehicle_land_detected
|
||||
vehicle_land_detected_s vehicle_land_detected;
|
||||
|
||||
if (_vehicle_land_detected_sub.copy(&vehicle_land_detected)
|
||||
&& (ekf2_timestamps.timestamp < vehicle_land_detected.timestamp + 3_s)) {
|
||||
|
||||
flags.at_rest = vehicle_land_detected.at_rest;
|
||||
flags.in_air = !vehicle_land_detected.landed;
|
||||
flags.gnd_effect = vehicle_land_detected.in_ground_effect;
|
||||
}
|
||||
|
||||
_ekf.setSystemFlagData(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void EKF2::UpdateCalibration(const hrt_abstime ×tamp, InFlightCalibration &cal, const matrix::Vector3f &bias,
|
||||
const matrix::Vector3f &bias_variance, float bias_limit, bool bias_valid, bool learning_valid)
|
||||
{
|
||||
// reset existing cal on takeoff
|
||||
if (!_ekf.control_status_prev_flags().in_air && _ekf.control_status_flags().in_air) {
|
||||
cal = {};
|
||||
}
|
||||
|
||||
// Check if conditions are OK for learning of accelerometer bias values
|
||||
// the EKF is operating in the correct mode and there are no filter faults
|
||||
static constexpr float max_var_allowed = 1e-3f;
|
||||
|
||||
@@ -170,6 +170,7 @@ private:
|
||||
void UpdateGpsSample(ekf2_timestamps_s &ekf2_timestamps);
|
||||
void UpdateMagSample(ekf2_timestamps_s &ekf2_timestamps);
|
||||
void UpdateRangeSample(ekf2_timestamps_s &ekf2_timestamps);
|
||||
void UpdateSystemFlagsSample(ekf2_timestamps_s &ekf2_timestamps);
|
||||
|
||||
// Used to check, save and use learned accel/gyro/mag biases
|
||||
struct InFlightCalibration {
|
||||
|
||||
Reference in New Issue
Block a user