Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Apr 22, 2020

Conversation

bresch
Copy link
Member

@bresch bresch commented Apr 17, 2020

fixes #14677

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.

The ekf reset without a correct compensation of the setpoint can lead to a crash.
task_no_z_reset
task_z_reset

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.
Copy link
Member

@MaEtUgR MaEtUgR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some questions, maybe we can quickly discuss.

{
_reset_counters.xy = _sub_vehicle_local_position.get().xy_reset_counter;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah clever so you went around the problem that the counters got initialized on task start with the new frame by not initializing them before the update and the first update now always initializes them given the reset counter is never exactly zero 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be sure the reset counter is never zero when there's a valid estimate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you then get an e.g. _ekfResetHandlerPositionZ() and _smoothing.setCurrentPosition(_position(2)) after every task switch which would override taking over the setpoint from the last task?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you then get an e.g. _ekfResetHandlerPositionZ() and _smoothing.setCurrentPosition(_position(2)) after every task switch which would override taking over the setpoint from the last task?

Ouch, yes, this is correct and not something we want. I need to find an other solution, thanks...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, the previous value of the counters is transferred to from the previous to the next FlightTask using a get/set function

@@ -60,6 +60,7 @@ void FlightTaskTransition::checkSetpoints(vehicle_local_position_setpoint_s &set

bool FlightTaskTransition::update()
{
FlightTask::update();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FlightTaskOffboard and FlightTaskOrbit need to call the base update as well.
Also to make it fully correct you need to logically and with the return value like for example here: https://github.com/PX4/Firmware/blob/2fca03e1bda313f86fd96d05130e830b9a2ee220/src/lib/flight_tasks/tasks/Manual/FlightTaskManual.cpp#L47

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I added it for FlightTaskOffboard, but orbit inherits from Altitude, so it's not required

@bresch bresch changed the title FlightTask: Fix ekf2 reset race condition during task switch [WIP]FlightTask: Fix ekf2 reset race condition during task switch Apr 17, 2020
@bresch
Copy link
Member Author

bresch commented Apr 20, 2020

@MaEtUgR Should be good now. I tested in SITL that the reset works when EKF resets and that the counter is saved when you switch between tasks

@bresch bresch requested a review from MaEtUgR April 20, 2020 06:50
@bresch bresch changed the title [WIP]FlightTask: Fix ekf2 reset race condition during task switch FlightTask: Fix ekf2 reset race condition during task switch Apr 20, 2020
@bresch bresch force-pushed the pr-ekf-reset-fix branch from d1e6f4b to ca96289 Compare April 20, 2020 07:07
Copy link
Member

@MaEtUgR MaEtUgR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks correct to me, I just had some minor comments.

@@ -81,6 +81,12 @@ class FlightTasks
*/
const vehicle_local_position_setpoint_s getPositionSetpoint();

/**
* Get the reset counters from the current task
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name says that but I would probably ask myself what reset counters.

Suggested change
* Get the reset counters from the current task
* Get the estimation reference frame reset counters from the current task

?

_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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle you could leave the _checkEkfResetCounters() call in the update Initialize. They would just be checked twice on activation then... works either way.

@@ -113,6 +121,9 @@ class FlightTask : public ModuleParams
*/
const vehicle_local_position_setpoint_s getPositionSetpoint();

const ekf_reset_counters_s getResetCounters() const { return _reset_counters; }
void setResetCounters(ekf_reset_counters_s counters) { _reset_counters = counters; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void setResetCounters(ekf_reset_counters_s counters) { _reset_counters = counters; }
void setResetCounters(const ekf_reset_counters_s &counters) { _reset_counters = counters; }

@@ -153,7 +155,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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg we should to get rid of these early returns, not here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's horrible :|

Copy link
Member

@MaEtUgR MaEtUgR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything addressed, thanks 👍

@bresch bresch merged commit be2bb4a into master Apr 22, 2020
@bresch bresch deleted the pr-ekf-reset-fix branch April 22, 2020 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multicopter v1.11 beta testing - max throttle is suddenly asserted
2 participants