Skip to main content

fusion_nav/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![forbid(unsafe_code)]
5#![deny(missing_docs)]
6
7#[cfg(test)]
8extern crate std;
9
10mod config;
11mod display;
12mod eskf;
13mod frames;
14mod geodetic;
15mod gsf;
16mod health;
17mod history;
18mod init;
19#[cfg(feature = "magnetic-model")]
20mod magnetic;
21mod math;
22mod observation;
23mod propagate;
24mod state;
25mod units;
26mod update;
27
28#[doc = include_str!("../GUIDE.md")]
29pub mod guide {}
30
31// The prelude is the one list of public types; the root adds back the four it leaves out.
32#[doc(inline)]
33pub use prelude::*;
34
35pub use config::ConfigBound;
36pub use frames::Frame;
37pub use state::STATES;
38pub use units::Quaternion;
39
40/// Everything needed to write an integration loop, in one import.
41///
42/// ```
43/// use fusion_nav::prelude::*;
44///
45/// let mut filter = Eskf::default();
46/// let dt = Seconds::from_secs(0.0025);
47/// let at = |sample: u64| Timestamp::from_micros(2_500 * sample);
48/// let gravity = Acceleration::body(0.0, 0.0, -GRAVITY);
49/// let still = |sample| ImuSample::from_rates(at(sample), AngularRate::zero(), gravity, dt);
50///
51/// // The barometer in the window is what fixes the reference the fusion below is
52/// // relative to, and its scatter is how well: one reading held across the window has
53/// // none, and fixes no reference. Without one the first altitude is spent reading a
54/// // reference from the estimate instead, and tests nothing.
55/// let mut window = StaticWindow::new();
56/// for i in 1..=800 {
57///     window.push(StaticSample {
58///         imu: still(i),
59///         baro: Some(Altitude::from_meters(if i % 2 == 1 { 112.25 } else { 111.75 })),
60///         ..StaticSample::default()
61///     })?;
62/// }
63/// filter.initialize(&window)?;
64/// assert_eq!(filter.predict(still(801)), Propagation::Propagated);
65///
66/// // An IMU that has stopped producing numbers is refused rather than propagated: a
67/// // non-finite sample reaches the quaternion and then the covariance, and never leaves.
68/// let spinning = AngularRate::body(f32::NAN, 0.0, 0.0);
69/// let broken = ImuSample::from_rates(at(802), spinning, gravity, dt);
70/// assert_eq!(filter.predict(broken), Propagation::NotFinite);
71///
72/// // Two meters above the reference the window fixed. An altitude far from what the
73/// // filter expects is `Fusion::Rejected` instead — the gate of (37) runs on every
74/// // measurement, and a 52 m step from a vehicle that has not moved does not pass it.
75/// let outcome = filter.fuse_baro_altitude(
76///     at(802),
77///     Altitude::from_meters(114.0),
78///     AltitudeNoise::from_sigma(2.0),
79/// );
80/// assert!(outcome.is_accepted());
81///
82/// // `R` describes that one measurement, so it travels with it — and it has to be a
83/// // variance some sensor could have. Zero or negative is refused, not fused.
84/// assert_eq!(
85///     filter.fuse_baro_altitude(
86///         at(802),
87///         Altitude::from_meters(114.0),
88///         AltitudeNoise::from_variance(0.0),
89///     ),
90///     Fusion::InvalidNoise,
91/// );
92/// # Ok::<(), InitError>(())
93/// ```
94///
95/// Deliberately excluded, because their names are too generic to glob-import safely:
96/// [`Frame`], [`STATES`] and [`Quaternion`], the last of which `nalgebra` and most algebra
97/// crates also export. Import those by path, as
98/// [`ConfigBound`], which a caller reads off a [`ConfigError`] far more often than it names.
99pub mod prelude {
100    pub use crate::config::{
101        ALIGNED_HEADING, ALIGNED_TILT, Accuracy, Coast, Config, ConfigError, Correlation, GRAVITY,
102        Gate, Gates, Hold, ImuNoise, Initialization, LATENCY_HORIZON, Percentile, Recovery,
103        Timeouts,
104    };
105    pub use crate::eskf::Eskf;
106    pub use crate::frames::{Body, Enu, Ned};
107    pub use crate::geodetic::{Geodetic, LocalOrigin};
108    pub use crate::health::{
109        Diagnostics, Fusion, GnssFusion, Innovation, Propagation, PropagationHealth, Refusal,
110        SourceHealth, Status, Validity,
111    };
112    pub use crate::init::{
113        Alignment, Coarse, InitError, SampleRefusal, StaticSample, StaticWindow, WindowNoise,
114    };
115    pub use crate::propagate::ImuSample;
116    pub use crate::state::{AttitudeVariance, Covariance, ErrorState, State};
117    pub use crate::units::{
118        Acceleration, Altitude, AltitudeNoise, AngularRate, Attitude, DeltaAngle, DeltaVelocity,
119        HeadingNoise, MagField, Meters, MetersPerSecond, MetersPerSecond2, Position, PositionNoise,
120        Radians, RadiansPerSecond, Seconds, SigmaBounds, Timestamp, Velocity, VelocityNoise,
121    };
122}