Skip to main content

elevator_core/components/
position.rs

1//! Position and velocity components along the shaft axis.
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6/// Position along the shaft axis.
7///
8/// # Display
9///
10/// Formats as a compact distance string:
11///
12/// ```
13/// # use elevator_core::components::Position;
14/// let pos = Position::from(4.5);
15/// assert_eq!(format!("{pos}"), "4.50m");
16/// ```
17#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
18pub struct Position {
19    /// Absolute position value.
20    pub(crate) value: f64,
21}
22
23impl Position {
24    /// Zero position (shaft origin).
25    pub const ZERO: Self = Self { value: 0.0 };
26
27    /// Absolute position value.
28    #[must_use]
29    pub const fn value(&self) -> f64 {
30        self.value
31    }
32
33    /// Absolute distance between two positions.
34    #[must_use]
35    pub fn distance_to(self, other: Self) -> f64 {
36        (self.value - other.value).abs()
37    }
38}
39
40impl fmt::Display for Position {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        write!(f, "{:.2}m", self.value)
43    }
44}
45
46impl From<f64> for Position {
47    fn from(value: f64) -> Self {
48        debug_assert!(
49            value.is_finite(),
50            "Position value must be finite, got {value}"
51        );
52        Self { value }
53    }
54}
55
56/// Velocity along the shaft axis (signed: +up, -down).
57///
58/// # Display
59///
60/// Formats as a compact speed string:
61///
62/// ```
63/// # use elevator_core::components::Velocity;
64/// let vel = Velocity::from(1.2);
65/// assert_eq!(format!("{vel}"), "1.20m/s");
66/// let stopped = Velocity::from(0.0);
67/// assert_eq!(format!("{stopped}"), "0.00m/s");
68/// ```
69#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
70pub struct Velocity {
71    /// Signed velocity value.
72    pub(crate) value: f64,
73}
74
75impl Velocity {
76    /// Zero velocity (stationary).
77    pub const ZERO: Self = Self { value: 0.0 };
78
79    /// Signed velocity value.
80    #[must_use]
81    pub const fn value(&self) -> f64 {
82        self.value
83    }
84
85    /// Absolute speed (magnitude of velocity).
86    #[must_use]
87    pub const fn speed(self) -> f64 {
88        self.value.abs()
89    }
90}
91
92impl fmt::Display for Velocity {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(f, "{:.2}m/s", self.value)
95    }
96}
97
98impl From<f64> for Velocity {
99    fn from(value: f64) -> Self {
100        debug_assert!(
101            value.is_finite(),
102            "Velocity value must be finite, got {value}"
103        );
104        Self { value }
105    }
106}