nav_types/
ned.rs

1use crate::enu::ENU;
2use crate::utils::RealFieldCopy;
3use crate::Access;
4use na::Vector3;
5use std::convert::From;
6use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8/// North East Down vector
9///
10/// This struct represents a vector in the NED coordinate system.
11/// See: [NED](https://en.wikipedia.org/wiki/North_east_down) for a general
12/// description.
13#[derive(Debug, Copy, Clone, PartialEq)]
14pub struct NED<N: RealFieldCopy>(Vector3<N>);
15
16impl<N: RealFieldCopy> NED<N> {
17    /// Create a new NED vector
18    pub fn new(n: N, e: N, d: N) -> NED<N> {
19        NED(Vector3::new(n, e, d))
20    }
21
22    /// Computes the L2 (Euclidean) norm of this vector
23    pub fn norm(&self) -> N {
24        self.0.norm()
25    }
26}
27
28impl<N: RealFieldCopy> NED<N> {
29    /// Get the North component of this vector
30    pub fn north(&self) -> N {
31        self.0.x
32    }
33
34    /// Get the East component of this vector
35    pub fn east(&self) -> N {
36        self.0.y
37    }
38
39    /// Get the Down component of this vector
40    pub fn down(&self) -> N {
41        self.0.z
42    }
43}
44
45impl<N: RealFieldCopy + Neg<Output = N>> From<NED<N>> for ENU<N> {
46    /// Convert `NED` vectors into `ENU`
47    fn from(e: NED<N>) -> Self {
48        ENU::new(e.east(), e.north(), -e.down())
49    }
50}
51
52impl<N: RealFieldCopy + Add<N, Output = N>> Add<NED<N>> for NED<N> {
53    type Output = NED<N>;
54    fn add(self, right: NED<N>) -> NED<N> {
55        NED(self.0 + right.0)
56    }
57}
58
59impl<N: RealFieldCopy + AddAssign<N>> AddAssign<NED<N>> for NED<N> {
60    fn add_assign(&mut self, right: NED<N>) {
61        self.0 += right.0
62    }
63}
64
65impl<N: RealFieldCopy + Sub<N, Output = N>> Sub<NED<N>> for NED<N> {
66    type Output = NED<N>;
67    fn sub(self, right: NED<N>) -> NED<N> {
68        NED(self.0 - right.0)
69    }
70}
71
72impl<N: RealFieldCopy + SubAssign<N>> SubAssign<NED<N>> for NED<N> {
73    fn sub_assign(&mut self, right: NED<N>) {
74        self.0 -= right.0
75    }
76}
77
78impl<N: RealFieldCopy + Mul<N, Output = N>> Mul<N> for NED<N> {
79    type Output = NED<N>;
80    fn mul(self, right: N) -> NED<N> {
81        NED(self.0 * right)
82    }
83}
84
85impl<N: RealFieldCopy + MulAssign<N>> MulAssign<N> for NED<N> {
86    fn mul_assign(&mut self, right: N) {
87        self.0 *= right
88    }
89}
90
91impl<N: RealFieldCopy + Div<N, Output = N>> Div<N> for NED<N> {
92    type Output = NED<N>;
93    fn div(self, right: N) -> NED<N> {
94        NED(self.0 / right)
95    }
96}
97
98impl<N: RealFieldCopy + DivAssign<N>> DivAssign<N> for NED<N> {
99    fn div_assign(&mut self, right: N) {
100        self.0 /= right
101    }
102}
103
104impl<N: RealFieldCopy> Access<Vector3<N>> for NED<N> {
105    fn access(self) -> Vector3<N> {
106        self.0
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113    use crate::enu::ENU;
114
115    quickcheck! {
116        fn create_ned(n: f32, e: f32, d: f32) -> () {
117            NED::new(n, e, d);
118        }
119
120        fn get_components(n: f32, e: f32, d: f32) -> () {
121            let vec = NED::new(n, e, d);
122            assert_eq!(vec.north(), n);
123            assert_eq!(vec.east(), e);
124            assert_eq!(vec.down(), d);
125        }
126
127        fn into_enu(n: f32, e: f32, d: f32) -> () {
128            let ned = NED::new(n, e, d);
129            let enu: ENU<_> = ned.into();
130            assert_eq!(n, enu.north());
131            assert_eq!(e, enu.east());
132            assert_eq!(d, -enu.up());
133        }
134
135        fn add_enu(n: f32, e: f32, d: f32) -> () {
136            let ned = NED::new(n, e, d);
137            let enu = ENU::new(e, n, -d);
138            let sum = enu + ned;
139            let twi = ned * 2.0;
140            assert_eq!(sum.north(), twi.north());
141            assert_eq!(sum.east(), twi.east());
142            assert_eq!(sum.up(), -twi.down());
143        }
144    }
145}