#[non_exhaustive]pub struct SourceHealth {
pub test_ratio: Option<f32>,
pub innovation: Option<Innovation>,
pub time_since_accepted: Option<Seconds>,
pub consecutive_rejections: u16,
pub accepted: u32,
pub rejected: u32,
pub refused: u32,
pub last_refusal: Option<Refusal>,
pub adopted: u32,
pub recovered: u32,
/* private fields */
}Expand description
Health of one observation source.
#[non_exhaustive]: read the fields, do not construct one. The set grows as the filter
learns to report more, and every addition would otherwise break every caller.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.test_ratio: Option<f32>Test ratio of the most recent measurement that reached the gate, or None if none
has.
A refusal leaves it alone: there was no innovation to normalize, so the alternative is
inventing a ratio or discarding the last real one. It can therefore read healthy while
refused climbs — a receiver that starts reporting eph = 0 freezes
this at its last good value — so a consumer plotting it reads
last_refusal beside it.
innovation: Option<Innovation>Innovation ν and its variance, from the most recent update the gate ran, whether it
accepted or rejected; None if the last measurement that set test_ratio ran no
update, and until one has.
Published so that a consistency statistic — NIS against the gate, or a comparison with
the innovations PX4 logs — reads the filter’s own number rather than recomputing it from
the measurement and the covariance, which would be a second implementation of (23) and
(24) free to disagree with this one. None after an acceptance that ran no update: an
adoption (Fusion::Reset) or a geodetic fix spent placing the origin.
time_since_accepted: Option<Seconds>Time since a measurement from this source was last accepted, or None if none
ever has been. Advances with the dt passed to
Eskf::predict.
consecutive_rejections: u16Rejections since the last acceptance.
accepted: u32Measurements accepted over the filter’s life.
rejected: u32Measurements rejected over the filter’s life.
refused: u32Measurements turned away before the gate ran, over the filter’s life.
Distinct from rejected, which is the gate’s verdict on a
measurement it could judge. A refusal means it could not be judged at all, and a
source with a rising count here is misconfigured or miswired rather than noisy: a
source that only ever refuses reads as never accepted, exactly like one that was
never connected.
last_refusal: Option<Refusal>Why the most recent refusal happened, or None if none has.
adopted: u32Measurements adopted outright rather than fused, over the filter’s life.
For a quantity initialization left unobserved, once, and for every
recovered lockout; see Fusion::Reset. Also counted in
accepted, because the measurement was taken and the timer restarted
— this is what tells the two apart, since an adoption steps the state and an ordinary
acceptance does not.
recovered: u32Adoptions that recovered from gate lockout, over the filter’s life: a measurement the
gate rejected after Recovery’s timeout, adopted instead. Also
counted in adopted.
Counted apart because it means something the first adoption does not: the covariance had shrunk around an error it could not see. A source that recovers regularly on good data is a finding against the covariance, not a working filter.
Implementations§
Source§impl SourceHealth
impl SourceHealth
Sourcepub const fn has_been_used(&self) -> bool
pub const fn has_been_used(&self) -> bool
Whether this source has ever been fused.
Sourcepub fn accepted_within(&self, timeout: Seconds) -> bool
pub fn accepted_within(&self, timeout: Seconds) -> bool
Whether a measurement from this source was accepted no more than timeout ago.
Never, for a source that has not been accepted at all.
Sourcepub fn period(&self) -> Option<Seconds>
pub fn period(&self) -> Option<Seconds>
This source’s update period as measured: the mean interval between its recent
measurements, or None until fifteen have arrived.
Measured rather than configured, because the caller would be asked for a number the
filter can read off the stream (GOALS.md differentiator 7). Every measurement placed in
time counts, whether the gate then accepts, rejects or refuses it: this is how often
the sensor speaks, which timeout reads, not how often it is believed.
Sourcepub fn timeout(&self, timeouts: &Timeouts) -> Seconds
pub fn timeout(&self, timeouts: &Timeouts) -> Seconds
How long this source may go unaccepted before it counts as timed out: two and a half
of its own periods, or Timeouts::dead_reckoning_after until a
period has been measured.
Not capped by dead_reckoning_after once one has: that is the mission’s limit on
horizontal dead reckoning, and a mission that sets it to 2 s would otherwise time a
jittery 1 Hz receiver out below its own 2.5 periods, the regime that flapped
2c42096b. A source slower than that limit allows is reported by DeadReckoning,
which outranks Degraded, whenever it matters.
Two and a half, because that is where the corpus stops flapping. eb799954’s
magnetometer, which bursts, changes status 2826 times over two periods and twice over
two and a half; 2c42096b’s jittery 1 Hz receiver 330 times against 48. What is left
is real: on a299e722, 10 Hz GNSS velocity rejected for a second at a time, which a
threshold sized for a 1 Hz receiver never showed.
Per source, because one threshold has to clear the slowest source: sized for a 1 Hz
GNSS, a 5 Hz barometer that stops is invisible for twelve missed readings. PX4 and
ArduPilot fix theirs as constants (no_aid_timeout_max, 1 s,
src/modules/ekf2/EKF/common.h:516 at c4e4ef98e9; hgtRetryTime*_ms,
libraries/AP_NavEKF3/AP_NavEKF3.h:493-497 at 368dc0c428).
Trait Implementations§
Source§impl Clone for SourceHealth
impl Clone for SourceHealth
impl Copy for SourceHealth
Source§impl Debug for SourceHealth
impl Debug for SourceHealth
Source§impl Default for SourceHealth
impl Default for SourceHealth
Source§impl Format for SourceHealth
Available on crate feature defmt only.
impl Format for SourceHealth
defmt only.Source§impl PartialEq for SourceHealth
impl PartialEq for SourceHealth
impl StructuralPartialEq for SourceHealth
Auto Trait Implementations§
impl Freeze for SourceHealth
impl RefUnwindSafe for SourceHealth
impl Send for SourceHealth
impl Sync for SourceHealth
impl Unpin for SourceHealth
impl UnsafeUnpin for SourceHealth
impl UnwindSafe for SourceHealth
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> Scalar for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.