fll_rs/
types.rs

1//! Newtype definitions for units
2
3use std::ops::Neg;
4
5use crate::movement::spec::RobotSpec;
6
7// TODO check i did this right
8
9macro_rules! impl_math {
10    ($type:ty) => {
11        impl Neg for $type {
12            type Output = $type;
13
14            fn neg(self) -> Self::Output {
15                Self(-self.0)
16            }
17        }
18    };
19}
20
21/// Repersents distance in milimeters
22#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
23pub struct Milimeters(pub f32);
24
25/// Repersents distance in wheel degrees
26#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
27pub struct Degrees(pub f32);
28
29/// Repersents distance in wheel rotations
30#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
31pub struct Rotations(pub f32);
32
33/// Repersents speed in wheel degrees per second
34#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
35pub struct DegreesPerSecond(pub f32);
36
37/// Repersents speed in milimeters per second
38#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
39pub struct MilimetersPerSecond(pub f32);
40
41/// Repersents acceleration in wheel degrees per second per second
42#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
43pub struct DegreesPerSecondPerSecond(pub f32);
44
45/// Repersents acceleration in milimeters per second per second
46#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
47pub struct MilimetersPerSecondPerSecond(pub f32);
48
49/// Repersented as a number from -1.0 -> 1.0
50#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
51pub struct Percent(pub f32);
52
53/// Repersent a heading, stored as degrees (-180 -> 180 when normalized)
54#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
55pub struct Heading(pub f32);
56
57impl_math!(Milimeters);
58impl_math!(Degrees);
59impl_math!(Rotations);
60impl_math!(DegreesPerSecond);
61impl_math!(MilimetersPerSecond);
62impl_math!(DegreesPerSecondPerSecond);
63impl_math!(MilimetersPerSecondPerSecond);
64impl_math!(Percent);
65impl_math!(Heading);
66
67#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
68pub enum Distance {
69    Milimeters(Milimeters),
70    Degrees(Degrees),
71    Rotations(Rotations),
72}
73
74impl Distance {
75    pub fn to_deg(self, spec: &RobotSpec) -> Degrees {
76        match self {
77            Distance::Milimeters(val) => spec.mm_to_deg(val),
78            Distance::Degrees(val) => val,
79            Distance::Rotations(val) => Degrees(val.0 * 360.0),
80        }
81    }
82
83    pub fn to_rot(self, spec: &RobotSpec) -> Rotations {
84        match self {
85            Distance::Milimeters(val) => Rotations(spec.mm_to_deg(val).0 / 360.0),
86            Distance::Rotations(val) => val,
87            Distance::Degrees(val) => Rotations(val.0 / 360.0),
88        }
89    }
90
91    pub fn to_mm(self, spec: &RobotSpec) -> Milimeters {
92        match self {
93            Distance::Milimeters(val) => val,
94            Distance::Rotations(val) => spec.deg_to_mm((val.0 * 360.0).deg()),
95            Distance::Degrees(val) => spec.deg_to_mm(val),
96        }
97    }
98}
99
100impl From<Degrees> for Distance {
101    fn from(value: Degrees) -> Self {
102        Distance::Degrees(value)
103    }
104}
105
106impl From<Rotations> for Distance {
107    fn from(value: Rotations) -> Self {
108        Distance::Rotations(value)
109    }
110}
111
112impl From<Milimeters> for Distance {
113    fn from(value: Milimeters) -> Self {
114        Distance::Milimeters(value)
115    }
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
119pub enum Speed {
120    DegreesPerSecond(DegreesPerSecond),
121    MilimetersPerSecond(MilimetersPerSecond),
122    Percent(Percent),
123}
124
125impl Speed {
126    pub fn to_dps(self, spec: &RobotSpec) -> DegreesPerSecond {
127        match self {
128            Speed::DegreesPerSecond(val) => val,
129            Speed::MilimetersPerSecond(val) => DegreesPerSecond(spec.mm_to_deg(val.0.mm()).0),
130            Speed::Percent(val) => DegreesPerSecond(val.0 * spec.max_speed().0),
131        }
132    }
133
134    pub fn to_mmps(self, spec: &RobotSpec) -> MilimetersPerSecond {
135        match self {
136            Speed::DegreesPerSecond(val) => MilimetersPerSecond(spec.deg_to_mm(val.0.deg()).0),
137            Speed::MilimetersPerSecond(val) => val,
138            Speed::Percent(val) => {
139                MilimetersPerSecond(spec.deg_to_mm((val.0 * spec.max_speed().0).deg()).0)
140            }
141        }
142    }
143
144    pub fn to_pct(self, spec: &RobotSpec) -> Percent {
145        match self {
146            Speed::DegreesPerSecond(val) => Percent(val.0 / spec.max_speed().0),
147            Speed::MilimetersPerSecond(val) => {
148                Percent(spec.mm_to_deg(val.0.mm()).0 / spec.max_speed().0)
149            }
150            Speed::Percent(val) => val,
151        }
152    }
153}
154
155impl From<DegreesPerSecond> for Speed {
156    fn from(value: DegreesPerSecond) -> Self {
157        Speed::DegreesPerSecond(value)
158    }
159}
160
161impl From<MilimetersPerSecond> for Speed {
162    fn from(value: MilimetersPerSecond) -> Self {
163        Speed::MilimetersPerSecond(value)
164    }
165}
166
167impl From<Percent> for Speed {
168    fn from(value: Percent) -> Self {
169        Speed::Percent(value)
170    }
171}
172
173#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
174pub enum Acceleration {
175    Degrees(DegreesPerSecondPerSecond),
176    Milimeters(MilimetersPerSecondPerSecond),
177}
178
179impl Acceleration {
180    pub fn to_dps2(self, spec: &RobotSpec) -> DegreesPerSecondPerSecond {
181        match self {
182            Acceleration::Milimeters(val) => {
183                DegreesPerSecondPerSecond(spec.mm_to_deg(val.0.mm()).0)
184            }
185            Acceleration::Degrees(val) => val,
186        }
187    }
188
189    pub fn to_mmps2(self, spec: &RobotSpec) -> MilimetersPerSecondPerSecond {
190        match self {
191            Acceleration::Milimeters(val) => val,
192            Acceleration::Degrees(val) => {
193                MilimetersPerSecondPerSecond(spec.deg_to_mm(val.0.deg()).0)
194            }
195        }
196    }
197}
198
199impl From<DegreesPerSecondPerSecond> for Acceleration {
200    fn from(value: DegreesPerSecondPerSecond) -> Self {
201        Acceleration::Degrees(value)
202    }
203}
204
205impl From<MilimetersPerSecondPerSecond> for Acceleration {
206    fn from(value: MilimetersPerSecondPerSecond) -> Self {
207        Acceleration::Milimeters(value)
208    }
209}
210
211pub trait UnitsExt {
212    /// Converts this value to `Milimeters` (istance)
213    fn mm(self) -> Milimeters;
214    /// Converts this value to `Degrees` (istance)
215    fn deg(self) -> Degrees;
216    /// Converts this value to `Rotations` (distance)
217    fn rot(self) -> Rotations;
218
219    /// Converts this value to `DegreesPerSecond` (speed)
220    fn dps(self) -> DegreesPerSecond;
221    /// Converts this value to `MilimetersPerSecond` (speed)
222    fn mmps(self) -> MilimetersPerSecond;
223
224    /// Converts this value to `DegreesPerSecondPerSecond` (acceleration)
225    fn dps2(self) -> DegreesPerSecondPerSecond;
226    /// Converts this value to `MilimetersPerSecondPerSecond` (acceleration)
227    fn mmps2(self) -> MilimetersPerSecondPerSecond;
228
229    /// Converts this value to `Heading` (heading)
230    fn ang(self) -> Heading;
231
232    /// Converts number from -100 -> 100 to percent
233    fn pct(self) -> Percent;
234}
235
236impl UnitsExt for f32 {
237    fn mm(self) -> Milimeters {
238        Milimeters(self)
239    }
240
241    fn deg(self) -> Degrees {
242        Degrees(self)
243    }
244
245    fn rot(self) -> Rotations {
246        Rotations(self)
247    }
248
249    fn dps(self) -> DegreesPerSecond {
250        DegreesPerSecond(self)
251    }
252
253    fn mmps(self) -> MilimetersPerSecond {
254        MilimetersPerSecond(self)
255    }
256
257    fn dps2(self) -> DegreesPerSecondPerSecond {
258        DegreesPerSecondPerSecond(self)
259    }
260
261    fn mmps2(self) -> MilimetersPerSecondPerSecond {
262        MilimetersPerSecondPerSecond(self)
263    }
264
265    fn ang(self) -> Heading {
266        Heading(self)
267    }
268
269    fn pct(self) -> Percent {
270        Percent(self / 100.0)
271    }
272}
273
274impl UnitsExt for i32 {
275    fn mm(self) -> Milimeters {
276        Milimeters(self as f32)
277    }
278
279    fn deg(self) -> Degrees {
280        Degrees(self as f32)
281    }
282
283    fn rot(self) -> Rotations {
284        Rotations(self as f32)
285    }
286
287    fn dps(self) -> DegreesPerSecond {
288        DegreesPerSecond(self as f32)
289    }
290
291    fn mmps(self) -> MilimetersPerSecond {
292        MilimetersPerSecond(self as f32)
293    }
294
295    fn dps2(self) -> DegreesPerSecondPerSecond {
296        DegreesPerSecondPerSecond(self as f32)
297    }
298
299    fn mmps2(self) -> MilimetersPerSecondPerSecond {
300        MilimetersPerSecondPerSecond(self as f32)
301    }
302
303    fn ang(self) -> Heading {
304        Heading(self as f32)
305    }
306
307    fn pct(self) -> Percent {
308        Percent(self as f32 / 100.0)
309    }
310}