Skip to main content

StaticWindow

Struct StaticWindow 

Source
pub struct StaticWindow { /* private fields */ }
Expand description

The initialization window, accumulated one sample at a time.

Eskf::initialize needs only what the window reduces to: sums, peaks, the span, the barometer’s scatter and the first and last GNSS velocity. So the samples are folded in as they arrive rather than buffered. A buffered window at the default Initialization::min_duration is more RAM than a Cortex-M0 has; this one is the same size at any rate and any length (measured).

let mut filter = Eskf::default();
let config = *filter.config();
let mut window = StaticWindow::new();
let mut i = 0;
while !window.is_long_enough(&config) {
    i += 1;
    // A refused sample leaves the window as it was: drop it and go on.
    if window.push(sample(i)).is_err() {
        continue;
    }
    // Waiting for stillness: a vehicle that moved starts the wait over.
    if !window.is_at_rest(&config) {
        window = StaticWindow::new();
    }
}
assert_eq!(filter.initialize(&window)?, Alignment::Static);

Waiting for stillness restarts the window, as above; is_at_rest says why it cannot slide. A buffered slice can, at the cost of the buffer, and try_extend or TryFrom builds a window from one.

Each push costs a few dozen floating-point operations, some in f64 (counted). On a core with no floating-point unit every one is a library call, inside the loop that is already reading the IMU: the price of not buffering, paid only until the window commits. level_scatter and BaroReadings say why their sums need f64. For the averages it is precaution: summing a few thousand readings near γ in f32 costs on the order of 10⁻⁵ rad of tilt, against a 0.02 rad prior.

Implementations§

Source§

impl StaticWindow

Source

pub fn new() -> Self

An empty window.

Source

pub fn push(&mut self, sample: StaticSample) -> Result<(), SampleRefusal>

Add one sample to the window.

Every check initialization makes on raw input is here, so that nothing downstream can be handed an unusable interval, a clock that does not run forward, or a value that is not a number. A refused sample leaves the window as it was, so the caller can drop it and go on, or start over. The clock is checked because it starts at the last sample’s time: a window timed anywhere but forward would start it somewhere the samples do not describe, and the first predict would coast the whole flight so far.

§Errors

SampleRefusal, naming which check the sample failed.

Source

pub fn try_extend( &mut self, samples: impl IntoIterator<Item = StaticSample>, ) -> Result<(), SampleRefusal>

Push every sample samples yields, in order, stopping at the first one refused.

The samples before it stay in the window, and the refused one and those after it are not taken. A caller building one start from a buffer discards the window on an error, as TryFrom does: a sample the buffer cannot supply says it is not the window the caller thought it was.

§Errors

As push, for the first sample refused.

Source

pub fn is_at_rest(&self, config: &Config) -> bool

Whether the window’s peak motion so far is within the tolerances of a still one.

The test Alignment::Static and the barometric reference rest on, asked of the peaks alone, so it is cheap after every sample where alignment_of measures the whole window. An empty window has not moved.

A window only grows, and peaks do not fall, so once this is false it stays false: an application waiting for stillness starts a new window rather than sliding this one.

Source

pub fn is_long_enough(&self, config: &Config) -> bool

Whether the window holds a sample and spans Initialization::min_duration: the condition a collection loop runs until.

The sample is asked for as well as the span, so that a min_duration of zero still ends the loop on a window Eskf::initialize accepts rather than on an empty one it refuses.

Source

pub fn span(&self) -> Seconds

The time the window’s samples integrated: the sum of their angle intervals, and what Initialization::min_duration is checked against.

Integrated time rather than the distance between the first and last timestamps, because it is what the window observed: a window a logger dropped samples from covers the samples it kept, and a stillness test over time nobody measured would pass on nothing. The angle interval rather than the velocity one for no reason but one: the two cover the same sample and differ only by when a driver closed each integral.

Summed in f64: in f32, 100 intervals of 20 ms come to 1.9999987 s, and a window of exactly min_duration would read as too short by the rounding. That is data/flight.csv’s window: summed in f32, it starts short.

Source

pub fn noise(&self, config: &Config) -> Option<WindowNoise>

The white noise this window measured on each sensor, a floor under the noise the filter should be told; WindowNoise says why a floor. Equation (8″).

On the window rather than the filter, because the figure is for building a Config and so comes before any filter exists; it reads the same tolerances is_at_rest does. Measured and reported, never applied: a figure changes the filter only if the caller writes it into the Config (GOALS.md differentiator 7, where derived is not adaptive).

None unless the window is at rest, the test the barometric reference rests on, and spans WindowNoise::MIN_READINGS of the WindowNoise::BLOCKs the IMU’s densities are read over: a moving window’s scatter is its motion. The barometer’s figure takes the same count of its own readings.

Trait Implementations§

Source§

impl Clone for StaticWindow

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 Debug for StaticWindow

Source§

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

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

impl Default for StaticWindow

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl TryFrom<&[StaticSample]> for StaticWindow

A window from samples already buffered, through StaticWindow::try_extend: the first refused refuses the window. An empty slice is an empty window, which Eskf::initialize refuses as InitError::NoSamples.

Source§

type Error = SampleRefusal

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

fn try_from(samples: &[StaticSample]) -> Result<Self, SampleRefusal>

Performs the conversion.

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<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.