rust_gnc/units/spatial.rs
1//! # Spatial Units and Kinematics
2//!
3//! This module defines the 3D spatial primitives used for navigation.
4//!
5//! ### Coordinate Convention
6//! We use the **NED (North-East-Down)** convention:
7//! - **X-axis**: Points North.
8//! - **Y-axis**: Points East.
9//! - **Z-axis**: Points Down (aligned with gravity).
10
11use core::ops::{Add, Mul};
12use crate::units::angular::Radians;
13
14/// Represents linear velocity in 3D space.
15/// Units are typically Meters per Second (m/s).
16#[derive(Debug, Clone, Copy, PartialEq, Default)]
17pub struct Velocity {
18 /// Velocity component along the North axis.
19 pub x: f32,
20 /// Velocity component along the East axis.
21 pub y: f32,
22 /// Velocity component along the Down axis (positive is descending).
23 pub z: f32,
24}
25
26impl Mul<f32> for Velocity {
27 type Output = Self;
28
29 /// Scales velocity by a scalar value.
30 /// Commonly used to calculate displacement (Velocity * dt).
31 fn mul(self, rhs: f32) -> Self::Output {
32 Self {
33 x: self.x * rhs,
34 y: self.y * rhs,
35 z: self.z * rhs,
36 }
37 }
38}
39
40/// Represents a 3D position in the NED frame.
41/// Units are typically Meters (m).
42#[derive(Debug, Clone, Copy, PartialEq, Default)]
43pub struct Position {
44 /// Distance North of the origin.
45 pub x: f32,
46 /// Distance East of the origin.
47 pub y: f32,
48 /// Altitude relative to origin (positive is below the origin/sea level).
49 pub z: f32,
50}
51
52impl Add<Velocity> for Position {
53 type Output = Self;
54
55 /// Adds a velocity vector (scaled by time) to a position.
56 /// Implements the basic kinematic equation: P_new = P_old + V.
57 fn add(self, rhs: Velocity) -> Self::Output {
58 Self {
59 x: self.x + rhs.x,
60 y: self.y + rhs.y,
61 z: self.z + rhs.z,
62 }
63 }
64}
65
66impl Position {
67 /// Performs a first-order Euler integration to predict the next position.
68 ///
69 /// ### Arguments
70 /// * `velocity` - The current velocity vector.
71 /// * `dt` - The time delta (seconds).
72 pub fn predict_next(&self, velocity: Velocity, dt: f32) -> Self {
73 *self +velocity * dt
74 }
75}
76
77/// Represents the aircraft orientation using Euler angles.
78///
79/// Follows the standard Tait-Bryan convention (Z-Y-X).
80#[derive(Debug, Clone, Copy, PartialEq)]
81pub struct Attitude {
82 /// Rotation about the X-axis (longitudinal).
83 pub roll: Radians,
84 /// Rotation about the Y-axis (lateral).
85 pub pitch: Radians,
86 /// Rotation about the Z-axis (vertical/heading).
87 pub yaw: Radians,
88}
89
90impl Default for Attitude {
91 /// Returns a level attitude (zeroed on all axes).
92 fn default() -> Self {
93 Self {
94 roll: Radians(0.0),
95 pitch: Radians(0.0),
96 yaw: Radians(0.0),
97 }
98 }
99}