FlightTask: Fix ekf2 reset race condition during task switch (#14692)

* FlightTask: Fix ekf2 reset race condition during task switch

During a loss of GPS data when using GPS as primary height source,
the height is reset to baro and the local position gets invalid at the
same time. This triggers a switch to altitude flight task and a setpoint
reset.
This combination of events had the effect to ignore the height reset,
the large sudden height error could create an abrupt change of altitude
or even a crash.
The ekf2 reset is now done at the beginning of each update call.
This commit is contained in:
Mathieu Bresciani
2020-04-22 13:18:35 +02:00
committed by GitHub
parent e82880d6d7
commit be2bb4a479
14 changed files with 85 additions and 42 deletions
+14 -1
View File
@@ -36,6 +36,16 @@ const vehicle_local_position_setpoint_s FlightTasks::getPositionSetpoint()
}
}
const ekf_reset_counters_s FlightTasks::getResetCounters()
{
if (isAnyTaskActive()) {
return _current_task.task->getResetCounters();
} else {
return FlightTask::zero_reset_counters;
}
}
const vehicle_constraints_s FlightTasks::getConstraints()
{
if (isAnyTaskActive()) {
@@ -64,7 +74,8 @@ FlightTaskError FlightTasks::switchTask(FlightTaskIndex new_task_index)
}
// Save current setpoints for the next FlightTask
vehicle_local_position_setpoint_s last_setpoint = getPositionSetpoint();
const vehicle_local_position_setpoint_s last_setpoint = getPositionSetpoint();
const ekf_reset_counters_s last_reset_counters = getResetCounters();
if (_initTask(new_task_index)) {
// invalid task
@@ -84,6 +95,8 @@ FlightTaskError FlightTasks::switchTask(FlightTaskIndex new_task_index)
return FlightTaskError::ActivationFailed;
}
_current_task.task->setResetCounters(last_reset_counters);
return FlightTaskError::NoError;
}
+6
View File
@@ -81,6 +81,12 @@ public:
*/
const vehicle_local_position_setpoint_s getPositionSetpoint();
/**
* Get the local frame and attitude reset counters of the estimator from the current task
* @return the reset counters
*/
const ekf_reset_counters_s getResetCounters();
/**
* Get task dependent constraints
* @return setpoint constraints that has to be respected by the position controller
@@ -42,8 +42,9 @@ using namespace matrix;
bool FlightTaskAutoFollowMe::update()
{
bool ret = FlightTaskAuto::update();
_position_setpoint = _target;
matrix::Vector2f vel_sp = _getTargetVelocityXY();
_velocity_setpoint = matrix::Vector3f(vel_sp(0), vel_sp(1), 0.0f);
return true;
}
return ret;
}
@@ -49,6 +49,7 @@ bool FlightTaskAutoMapper::activate(vehicle_local_position_setpoint_s last_setpo
bool FlightTaskAutoMapper::update()
{
bool ret = FlightTaskAuto::update();
// always reset constraints because they might change depending on the type
_setDefaultConstraints();
@@ -107,7 +108,7 @@ bool FlightTaskAutoMapper::update()
// update previous type
_type_previous = _type;
return true;
return ret;
}
void FlightTaskAutoMapper::_reset()
@@ -48,6 +48,8 @@ bool FlightTaskDescend::activate(vehicle_local_position_setpoint_s last_setpoint
bool FlightTaskDescend::update()
{
bool ret = FlightTask::update();
if (PX4_ISFINITE(_velocity(2))) {
// land with landspeed
_velocity_setpoint(2) = _param_mpc_land_speed.get();
@@ -59,5 +61,5 @@ bool FlightTaskDescend::update()
_acceleration_setpoint(2) = .3f;
}
return true;
return ret;
}
@@ -49,6 +49,8 @@ bool FlightTaskFailsafe::activate(vehicle_local_position_setpoint_s last_setpoin
bool FlightTaskFailsafe::update()
{
bool ret = FlightTask::update();
if (PX4_ISFINITE(_position(0)) && PX4_ISFINITE(_position(1))) {
// stay at current position setpoint
_velocity_setpoint(0) = _velocity_setpoint(1) = 0.f;
@@ -72,5 +74,5 @@ bool FlightTaskFailsafe::update()
_acceleration_setpoint(2) = NAN;
}
return true;
return ret;
}
@@ -6,6 +6,7 @@ constexpr uint64_t FlightTask::_timeout;
// First index of empty_setpoint corresponds to time-stamp and requires a finite number.
const vehicle_local_position_setpoint_s FlightTask::empty_setpoint = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {}};
const ekf_reset_counters_s FlightTask::zero_reset_counters = {};
const vehicle_constraints_s FlightTask::empty_constraints = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, false, {}};
const landing_gear_s FlightTask::empty_landing_gear_default_keep = {0, landing_gear_s::GEAR_KEEP, {}};
@@ -13,7 +14,6 @@ bool FlightTask::activate(vehicle_local_position_setpoint_s last_setpoint)
{
_resetSetpoints();
_setDefaultConstraints();
_initEkfResetCounters();
_time_stamp_activate = hrt_absolute_time();
_gear = empty_landing_gear_default_keep;
return true;
@@ -37,17 +37,13 @@ bool FlightTask::updateInitialize()
_evaluateVehicleLocalPosition();
_evaluateDistanceToGround();
_checkEkfResetCounters();
return true;
}
void FlightTask::_initEkfResetCounters()
bool FlightTask::update()
{
_reset_counters.xy = _sub_vehicle_local_position.get().xy_reset_counter;
_reset_counters.vxy = _sub_vehicle_local_position.get().vxy_reset_counter;
_reset_counters.z = _sub_vehicle_local_position.get().z_reset_counter;
_reset_counters.vz = _sub_vehicle_local_position.get().vz_reset_counter;
_reset_counters.quat = _sub_attitude.get().quat_reset_counter;
_checkEkfResetCounters();
return true;
}
void FlightTask::_checkEkfResetCounters()
@@ -55,6 +55,14 @@
#include <uORB/topics/home_position.h>
#include <lib/weather_vane/WeatherVane.hpp>
struct ekf_reset_counters_s {
uint8_t xy;
uint8_t vxy;
uint8_t z;
uint8_t vz;
uint8_t quat;
};
class FlightTask : public ModuleParams
{
public:
@@ -97,7 +105,7 @@ public:
* To be called regularly in the control loop cycle to execute the task
* @return true on success, false on error
*/
virtual bool update() = 0;
virtual bool update();
/**
* Call after update()
@@ -113,6 +121,9 @@ public:
*/
const vehicle_local_position_setpoint_s getPositionSetpoint();
const ekf_reset_counters_s getResetCounters() const { return _reset_counters; }
void setResetCounters(const ekf_reset_counters_s &counters) { _reset_counters = counters; }
/**
* Get vehicle constraints.
* The constraints can vary with task.
@@ -139,6 +150,11 @@ public:
*/
static const vehicle_local_position_setpoint_s empty_setpoint;
/**.
* All counters are set to 0.
*/
static const ekf_reset_counters_s zero_reset_counters;
/**
* Empty constraints.
* All constraints are set to NAN.
@@ -193,8 +209,8 @@ protected:
/**
* Monitor the EKF reset counters and
* call the appropriate handling functions in case of a reset event
* TODO: add the delta values to all the handlers
*/
void _initEkfResetCounters();
void _checkEkfResetCounters();
virtual void _ekfResetHandlerPositionXY() {};
virtual void _ekfResetHandlerVelocityXY() {};
@@ -234,14 +250,7 @@ protected:
matrix::Vector3f _velocity_setpoint_feedback;
matrix::Vector3f _acceleration_setpoint_feedback;
/* Counters for estimator local position resets */
struct {
uint8_t xy;
uint8_t vxy;
uint8_t z;
uint8_t vz;
uint8_t quat;
} _reset_counters{};
ekf_reset_counters_s _reset_counters{}; ///< Counters for estimator local position resets
/**
* Vehicle constraints.
@@ -361,10 +361,11 @@ bool FlightTaskManualAltitude::_checkTakeoff()
bool FlightTaskManualAltitude::update()
{
bool ret = FlightTaskManual::update();
_updateConstraintsFromEstimator();
_scaleSticks();
_updateSetpoints();
_constraints.want_takeoff = _checkTakeoff();
return true;
return ret;
}
@@ -68,6 +68,8 @@ bool FlightTaskOffboard::activate(vehicle_local_position_setpoint_s last_setpoin
bool FlightTaskOffboard::update()
{
bool ret = FlightTask::update();
// reset setpoint for every loop
_resetSetpoints();
@@ -106,7 +108,7 @@ bool FlightTaskOffboard::update()
}
// don't have to continue
return true;
return ret;
} else {
_position_lock.setAll(NAN);
@@ -124,7 +126,7 @@ bool FlightTaskOffboard::update()
}
// don't have to continue
return true;
return ret;
} else {
_position_lock.setAll(NAN);
@@ -144,7 +146,7 @@ bool FlightTaskOffboard::update()
}
// don't have to continue
return true;
return ret;
} else {
_position_lock.setAll(NAN);
@@ -155,7 +157,7 @@ bool FlightTaskOffboard::update()
_position_setpoint.setNaN(); // Don't require any position/velocity setpoints
_velocity_setpoint.setNaN();
_acceleration_setpoint = Vector3f(0.f, 0.f, 100.f); // High downwards acceleration to make sure there's no thrust
return true;
return ret;
}
// Possible inputs:
@@ -240,5 +242,5 @@ bool FlightTaskOffboard::update()
// use default conditions of upwards position or velocity to take off
_constraints.want_takeoff = _checkTakeoff();
return true;
return ret;
}
@@ -162,7 +162,7 @@ bool FlightTaskOrbit::activate(vehicle_local_position_setpoint_s last_setpoint)
bool FlightTaskOrbit::update()
{
// update altitude
FlightTaskManualAltitudeSmooth::update();
bool ret = FlightTaskManualAltitudeSmooth::update();
// stick input adjusts parameters within a fixed time frame
const float r = _r - _sticks_expo(0) * _deltatime * (_radius_max / 8.f);
@@ -186,7 +186,7 @@ bool FlightTaskOrbit::update()
// publish information to UI
sendTelemetry();
return true;
return ret;
}
void FlightTaskOrbit::generate_circle_approach_setpoints()
@@ -60,6 +60,7 @@ void FlightTaskTransition::checkSetpoints(vehicle_local_position_setpoint_s &set
bool FlightTaskTransition::update()
{
bool ret = FlightTask::update();
_acceleration_setpoint.xy() = matrix::Vector2f(0.f, 0.f);
// demand zero vertical velocity and level attitude
// tailsitters will override attitude and thrust setpoint
@@ -68,5 +69,5 @@ bool FlightTaskTransition::update()
_velocity_setpoint(2) = 0.0f;
_yaw_setpoint = NAN;
return true;
return ret;
}
@@ -92,7 +92,11 @@ public:
_state.x = pos;
_trajectory[0].setCurrentPosition(pos(0));
_trajectory[1].setCurrentPosition(pos(1));
// TODO: check lock/unlock in case of EKF reset
_position_estimate = pos;
if (_position_lock_active) {
_position_setpoint_locked = pos;
}
}
Vector2f getCurrentPosition() const { return _position_setpoint_locked; }
@@ -108,15 +112,15 @@ private:
bool _position_lock_active{false};
Vector2f _position_setpoint_locked;
Vector2f _position_setpoint_locked{};
Vector2f _velocity_setpoint_feedback;
Vector2f _position_estimate;
Vector2f _velocity_setpoint_feedback{};
Vector2f _position_estimate{};
struct {
Vector2f j;
Vector2f a;
Vector2f v;
Vector2f x;
} _state;
} _state{};
};
@@ -84,6 +84,11 @@ public:
{
_state.x = pos;
_trajectory.setCurrentPosition(pos);
_position_estimate = pos;
if (_position_lock_active) {
_position_setpoint_locked = pos;
}
}
float getCurrentPosition() const { return _position_setpoint_locked; }
void setCurrentPositionEstimate(float pos) { _position_estimate = pos; }
@@ -99,17 +104,17 @@ private:
bool _position_lock_active{false};
float _position_setpoint_locked;
float _position_setpoint_locked{};
float _velocity_setpoint_feedback;
float _position_estimate;
float _velocity_setpoint_feedback{};
float _position_estimate{};
struct {
float j;
float a;
float v;
float x;
} _state;
} _state{};
float _max_accel_up{0.f};
float _max_accel_down{0.f};