marg_orientation/
magnetometer_reading.rs

1use crate::impl_standard_traits;
2use core::fmt::{Debug, Formatter};
3use core::ops::Mul;
4use uniform_array_derive::UniformArray;
5
6#[derive(UniformArray)]
7#[cfg_attr(test, ensure_uniform_type::ensure_uniform_type)]
8#[repr(C)]
9pub struct MagnetometerReading<T> {
10    /// The magnetic field strength along the x-axis, in Gauss.
11    pub x: T,
12    /// The magnetic field strength along the y-axis, in Gauss.
13    pub y: T,
14    /// The magnetic field strength along the z-axis, in Gauss.
15    pub z: T,
16}
17
18impl<T> MagnetometerReading<T> {
19    /// Initializes a new [`MagnetometerReading`] instance.
20    #[inline(always)]
21    pub const fn new(x: T, y: T, z: T) -> Self {
22        Self { x, y, z }
23    }
24
25    /// Constructs a new [`MagnetometerReading`] instance from a reading in a given coordinate frame.
26    #[cfg(feature = "coordinate-frame")]
27    #[cfg_attr(docsrs, doc(cfg(feature = "coordinate-frame")))]
28    pub fn north_east_down<C>(coordinate: C) -> Self
29    where
30        C: Into<coordinate_frame::NorthEastDown<T>>,
31        T: Clone,
32    {
33        let coordinate = coordinate.into();
34        Self {
35            x: coordinate.x(),
36            y: coordinate.y(),
37            z: coordinate.z(),
38        }
39    }
40
41    /// Represents this reading as a tuple.
42    pub fn as_tuple(&self) -> (T, T, T)
43    where
44        T: Copy,
45    {
46        (self.x, self.y, self.z)
47    }
48}
49
50impl<T> Default for MagnetometerReading<T>
51where
52    T: Default,
53{
54    #[inline]
55    fn default() -> Self {
56        Self::new(Default::default(), Default::default(), Default::default())
57    }
58}
59
60impl<T> Clone for MagnetometerReading<T>
61where
62    T: Clone,
63{
64    fn clone(&self) -> Self {
65        Self {
66            x: self.x.clone(),
67            y: self.y.clone(),
68            z: self.z.clone(),
69        }
70    }
71}
72
73impl<T> Debug for MagnetometerReading<T>
74where
75    T: Debug,
76{
77    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
78        f.debug_tuple("MagnetometerReading")
79            .field(&self.x)
80            .field(&self.y)
81            .field(&self.z)
82            .finish()
83    }
84}
85
86impl<T> Mul<T> for MagnetometerReading<T>
87where
88    T: Mul<T, Output = T> + Clone,
89{
90    type Output = MagnetometerReading<T>;
91
92    fn mul(self, rhs: T) -> Self::Output {
93        Self {
94            x: self.x * rhs.clone(),
95            y: self.y * rhs.clone(),
96            z: self.z * rhs.clone(),
97        }
98    }
99}
100
101#[cfg(feature = "coordinate-frame")]
102#[cfg_attr(docsrs, doc(cfg(feature = "coordinate-frame")))]
103impl<T, C> From<C> for MagnetometerReading<T>
104where
105    C: coordinate_frame::CoordinateFrame<Type = T>,
106    T: Copy + coordinate_frame::SaturatingNeg<Output = T>,
107{
108    fn from(value: C) -> Self {
109        Self::north_east_down(value.to_ned())
110    }
111}
112
113impl_standard_traits!(MagnetometerReading, T);
114
115#[cfg(test)]
116mod test {
117    use super::*;
118
119    #[test]
120    fn test_len() {
121        let reading = MagnetometerReading::<f32>::default();
122        assert_eq!(reading.len(), 3);
123    }
124
125    #[test]
126    fn test_index() {
127        let reading = MagnetometerReading::<f32> {
128            x: 1.0,
129            y: 2.0,
130            z: 3.0,
131        };
132
133        assert_eq!(reading[0], 1.0);
134        assert_eq!(reading[1], 2.0);
135        assert_eq!(reading[2], 3.0);
136    }
137}