Skip to main content

Recovery

Struct Recovery 

Source
pub struct Recovery {
    pub gnss_position: Option<Seconds>,
    pub gnss_height: Option<Seconds>,
    pub gnss_velocity: Option<Seconds>,
    pub baro_altitude: Option<Seconds>,
    pub mag_heading: Option<Seconds>,
    pub gnss_heading: Option<Seconds>,
    pub course: Option<Seconds>,
    pub yaw_estimator: Option<Seconds>,
}
Expand description

How long each source may be rejected before the filter adopts it again: automatic recovery from gate lockout, one switch per source. None turns that source’s recovery off.

A source recovers when the gate rejects one of its measurements and none has been accepted for at least this long — since initialization, for a source never accepted. That measurement is then adopted rather than discarded: Fusion::Reset, counted in SourceHealth::recovered. The state becomes the measurement and its covariance block the measurement’s, which is what undoes the overconfidence that locked the gate rather than only moving the estimate. Only a rejection triggers it: a source that is silent or refused has nothing to adopt, and a stream of NaN must not step the state.

On by default, because a filter that reports lockout and stops hands every integrator the same timeout-and-reset loop to write. An application that owns its failsafe policy — a controller that cannot take a step, an operator alert instead of a reset — turns off the source it owns, or all of them with Recovery::OFF, and drives Eskf::reset_position_to itself. The decision is rejection handling.

Per source, not per quantity, because a source is what the gate rejects: the fields mirror Gates and Diagnostics.

After a position hold the timeout is waived once: the first GNSS position or velocity the gate turns down is adopted at once, unless its field here is None; see Hold.

Fields§

§gnss_position: Option<Seconds>

GNSS horizontal position: north and east are adopted, height is left alone.

§gnss_height: Option<Seconds>

GNSS height: the down axis is adopted, and the barometric reference is dropped so that the next altitude reads it again against the adopted height — unless Config::baro_reference_from_estimate is off, which leaves the reference the caller’s and keeps it.

§gnss_velocity: Option<Seconds>

GNSS velocity: all three axes are adopted.

§baro_altitude: Option<Seconds>

Barometric altitude: the reference α₀ is read again from the estimate, as the first one is when a start leaves none, and the state does not move. Needs an established position to read it against, and Config::baro_reference_from_estimate on: with it off the reference is the caller’s, and a barometer that disagrees stays rejected.

§mag_heading: Option<Seconds>

Magnetic heading: adopted as the first heading is, with the R of (36′) — but only while neither GNSS position nor velocity is fresh (SourceHealth::is_fresh), since with those arriving a magnetometer that disagrees for this long is more likely disturbed than right. Nor while a GNSS heading is accepted, for the same reason.

§gnss_heading: Option<Seconds>

Dual-antenna GNSS heading: adopted as the first heading is, with the caller’s R. No guard: it is the absolute heading reference when the vehicle carries one.

§course: Option<Seconds>

Course constraint: adopted as the first heading is — but only while neither magnetic nor GNSS heading is fresh, since with either arriving a course that disagrees this long is sideslip the caller did not allow for, a crosswind or a multirotor crabbing, rather than a wrong heading.

§yaw_estimator: Option<Seconds>

The yaw estimator’s heading, adopted in place of one GNSS contradicts: once no GNSS velocity has been accepted for this long and a second in a row is rejected, while the estimator of Config::yaw_estimator has converged on a yaw more than 25° from the filter’s. A magnetometer is then not adopted back until one of its headings passes the gate. That velocity, and the first GNSS position the gate turns down after it, are then adopted at once rather than after their own timeouts, since what they were judged against was the wrong heading. Not while a dual-antenna GNSS heading is fresh (SourceHealth::is_fresh): it measures what the estimator infers. Unlike the fields above it times another source’s rejections: the estimator’s answer is never gated.

Implementations§

Source§

impl Recovery

Source

pub const OFF: Self

No automatic recovery at all: the filter reports lockout and the application decides.

Trait Implementations§

Source§

impl Clone for Recovery

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Recovery

Source§

impl Debug for Recovery

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Recovery

Source§

fn default() -> Self

PX4’s timeouts, at c4e4ef98e9: reset_timeout_max, 7 s, for horizontal position, velocity and heading, and hgt_fusion_timeout_max, 5 s, for height (src/modules/ekf2/EKF/common.h:515-517). Each is applied the way PX4 applies it — position at aid_sources/gnss/gps_control.cpp:204-213, velocity at :146-156, heading at aid_sources/magnetometer/mag_control.cpp:276-289, whose guard against fresh horizontal aiding mag_heading keeps — with one departure.

PX4 resets height only when every height source is failing (ekf_helper.cpp:48-57), and otherwise stops fusing the one that disagrees, whichever EKF2_HGT_REF names the reference (GNSS by default, module.yaml:87-106). Here GNSS height is always the absolute and the barometer’s offset is estimated, equation (30′), so a GNSS height rejected for 5 s is adopted even while the barometer is accepted, and a barometer rejected for 5 s has its reference read again: the absolute wins either way.

The two heading sources PX4 either lacks or does not recover take the same 7 s, by the rule recovery follows everywhere here rather than by a measurement. PX4 stops fusing a GNSS yaw that has failed for reset_timeout_max and resets nothing (aid_sources/gnss/gnss_yaw_control.cpp:78-81); ArduPilot realigns it on the ground after 10 s (AP_NavEKF3_MagFusion.cpp:433-435 at 368dc0c4). PX4 has no course constraint at all; ArduPilot’s in-flight course realignment is itself a reset (realignYawGPS, AP_NavEKF3_MagFusion.cpp:145-218).

The yaw estimator’s is PX4’s EKFGSF_reset_delay, 1 s (common.h:395), applied as PX4 applies it to a rejected velocity (gps_control.cpp:113-125, isYawFailure at :546-562) less its in-air condition, which this filter is not told.

Source§

impl PartialEq for Recovery

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Recovery

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.