1use std::f32::consts::PI;
2
3use crate::types::{
4 Acceleration, Degrees, DegreesPerSecond, DegreesPerSecondPerSecond, Distance, Heading,
5 Milimeters, Speed, UnitsExt,
6};
7
8#[derive(Clone)]
9pub struct RobotSpec {
10 acceleration: DegreesPerSecondPerSecond,
11 deceleration: DegreesPerSecondPerSecond,
12
13 wheel_circumference: Milimeters,
14 wheel_diameter: Milimeters,
15 wheelbase_circumference: Milimeters,
16 wheelbase_diameter: Milimeters,
17
18 max_speed: DegreesPerSecond,
19}
20
21impl RobotSpec {
22 pub fn new(
23 acceleration: impl Into<Acceleration>,
24 deceleration: impl Into<Acceleration>,
25 wheel_diameter: Milimeters,
26 wheelbase_diameter: Milimeters,
27 max_speed: impl Into<Speed>,
28 ) -> Self {
29 let wheel_circumference = PI * wheel_diameter.0;
30 let wheelbase_circumference = PI * wheelbase_diameter.0 * 2.0;
31
32 let preliminary_spec = RobotSpec {
33 acceleration: DegreesPerSecondPerSecond(0.0),
34 deceleration: DegreesPerSecondPerSecond(0.0),
35 wheel_circumference: wheel_circumference.mm(),
36 wheel_diameter,
37 wheelbase_circumference: wheelbase_circumference.mm(),
38 wheelbase_diameter,
39 max_speed: DegreesPerSecond(0.0),
40 };
41
42 RobotSpec {
43 acceleration: acceleration.into().to_dps2(&preliminary_spec),
44 deceleration: deceleration.into().to_dps2(&preliminary_spec),
45 max_speed: max_speed.into().to_dps(&preliminary_spec),
46 ..preliminary_spec
47 }
48 }
49
50 pub fn acceleration(&self) -> DegreesPerSecondPerSecond {
53 self.acceleration
54 }
55
56 pub fn deceleration(&self) -> DegreesPerSecondPerSecond {
59 self.deceleration
60 }
61
62 pub fn wheel_circumference(&self) -> Milimeters {
65 self.wheel_circumference
66 }
67
68 pub fn wheel_diameter(&self) -> Milimeters {
71 self.wheel_diameter
72 }
73
74 pub fn wheelbase_circumference(&self) -> Milimeters {
77 self.wheelbase_circumference
78 }
79
80 pub fn wheelbase_diameter(&self) -> Milimeters {
83 self.wheelbase_diameter
84 }
85
86 pub fn max_speed(&self) -> DegreesPerSecond {
89 self.max_speed
90 }
91
92 pub fn get_distance_for_turn(&self, Heading(angle): Heading) -> Degrees {
98 (angle * self.wheelbase_circumference.0 / self.wheel_circumference.0).deg()
99 }
100
101 pub fn get_approx_angle(
103 &self,
104 left: impl Into<Distance>,
105 right: impl Into<Distance>,
106 ) -> Heading {
107 ((left.into().to_deg(&self).0 - right.into().to_deg(&self).0) * self.wheel_circumference.0
108 / self.wheelbase_circumference.0)
109 .ang()
110 }
111
112 pub fn deg_to_mm(&self, Degrees(deg): Degrees) -> Milimeters {
114 (deg / 360.0 * self.wheel_circumference.0).mm()
115 }
116
117 pub fn mm_to_deg(&self, Milimeters(mm): Milimeters) -> Degrees {
119 (mm / self.wheel_circumference.0 * 360.0).deg()
120 }
121}