fusion_nav/frames.rs
1//! Reference frames as compile-time markers.
2//!
3//! A frame is a zero-sized type parameter on a quantity, so that a
4//! [`Position<Enu>`](crate::Position) cannot be passed where a `Position<Ned>` is expected.
5//! Frames carry no data and cost nothing at runtime.
6
7mod sealed {
8 pub trait Sealed {}
9}
10
11/// A reference frame a quantity can be expressed in.
12///
13/// Sealed: frames are a closed set, because the filter's Jacobians depend on the
14/// conventions of [`Ned`] and [`Body`] specifically.
15pub trait Frame: sealed::Sealed + Copy + core::fmt::Debug {
16 /// Short label used in `Debug` output, such as `"NED"`.
17 const NAME: &'static str;
18}
19
20macro_rules! frame {
21 ($(#[$meta:meta])* $name:ident, $label:literal) => {
22 $(#[$meta])*
23 #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
24 pub struct $name;
25
26 impl sealed::Sealed for $name {}
27
28 impl Frame for $name {
29 const NAME: &'static str = $label;
30 }
31 };
32}
33
34frame!(
35 /// Local tangent navigation frame: North, East, Down.
36 ///
37 /// Down-positive, so gravity has a positive `z` component. This is the frame the
38 /// filter navigates in.
39 Ned,
40 "NED"
41);
42
43frame!(
44 /// Local tangent frame: East, North, Up.
45 ///
46 /// Not used by the filter. It exists so that an ENU quantity is a compile error at the
47 /// boundary rather than a sign error in flight.
48 Enu,
49 "ENU"
50);
51
52frame!(
53 /// Vehicle body frame: x forward, y right, z down.
54 ///
55 /// IMU and magnetometer measurements and the IMU biases live here.
56 Body,
57 "body"
58);