1use super::*;
4pub trait GenericCommand:
11 Copy
12 + Debug
13 + PartialEq
14 + From<Self::Position>
15 + From<Self::Velocity>
16 + From<Self::Acceleration>
17 + From<Self::CorrespondingState>
18 + Add<Output = Self>
19 + Sub<Output = Self>
20 + Mul<Dimensionless<f32>>
21 + Div<Dimensionless<f32>>
22 + Neg<Output = Self>
23 + AddAssign
24 + SubAssign
25 + MulAssign<Dimensionless<f32>>
26 + DivAssign<Dimensionless<f32>>
27 + Into<PositionDerivative>
28 + Into<f32>
29{
30 type Position: Copy
32 + Debug
33 + Default
34 + fmt::Display
35 + PartialOrd
36 + Neg<Output = Self::Position>
37 + Add<Output = Self::Position>
38 + Sub<Output = Self::Position>
39 + Mul<Dimensionless<f32>, Output = Self::Position>
40 + Div<Dimensionless<f32>, Output = Self::Position>
41 + Div<Time, Output = Self::Velocity>
42 + Div<Self::Velocity, Output = Second<f32>>
43 + Div<SecondSquared<f32>, Output = Self::Acceleration>
44 + stulta::AbsoluteValue;
45 type Velocity: Copy
47 + Debug
48 + Default
49 + fmt::Display
50 + PartialOrd
51 + Neg<Output = Self::Velocity>
52 + Add<Output = Self::Velocity>
53 + Sub<Output = Self::Velocity>
54 + Mul<Dimensionless<f32>, Output = Self::Velocity>
55 + Div<Dimensionless<f32>, Output = Self::Velocity>
56 + Mul<Time, Output = Self::Position>
57 + Div<Time, Output = Self::Acceleration>
58 + Div<Self::Acceleration, Output = Second<f32>>
59 + Mul<Second<f32>, Output = Self::Position>
60 + stulta::AbsoluteValue;
61 type Acceleration: Copy
63 + Debug
64 + Default
65 + fmt::Display
66 + PartialOrd
67 + Neg<Output = Self::Acceleration>
68 + Add<Output = Self::Acceleration>
69 + Sub<Output = Self::Acceleration>
70 + Mul<Dimensionless<f32>, Output = Self::Acceleration>
71 + Div<Dimensionless<f32>, Output = Self::Acceleration>
72 + Mul<Time, Output = Self::Velocity>
73 + Mul<Second<f32>, Output = Self::Velocity>
74 + Mul<SecondSquared<f32>, Output = Self::Position>
75 + stulta::AbsoluteValue;
76 type CorrespondingState: GenericState<
78 Position = Self::Position,
79 Velocity = Self::Velocity,
80 Acceleration = Self::Acceleration,
81 >;
82 fn generic_new(position_derivative: PositionDerivative, value: f32) -> Self;
84 fn generic_get_position(&self) -> Option<Self::Position>;
87 fn generic_get_velocity(&self) -> Option<Self::Velocity>;
93 fn generic_get_acceleration(&self) -> Self::Acceleration;
97}
98macro_rules! build_command_enum {
99 ($name: ident, $pos: ty, $vel: ty, $acc: ty, $corresponding_state: ty) => {
100 #[derive(Clone, Copy, Debug, PartialEq)]
102 pub enum $name {
103 Position($pos),
105 Velocity($vel),
107 Acceleration($acc),
109 }
110 impl $name {
111 pub const fn new(position_derivative: PositionDerivative, value: f32) -> Self {
113 match position_derivative {
114 PositionDerivative::Position => Self::Position(<$pos>::new(value)),
115 PositionDerivative::Velocity => Self::Velocity(<$vel>::new(value)),
116 PositionDerivative::Acceleration => Self::Acceleration(<$acc>::new(value)),
117 }
118 }
119 pub const fn get_position(&self) -> Option<$pos> {
122 if let Self::Position(pos) = self {
123 Some(*pos)
124 } else {
125 None
126 }
127 }
128 pub const fn get_velocity(&self) -> Option<$vel> {
133 match self {
134 Self::Position(_) => Some(<$vel>::new(0.0)),
135 Self::Velocity(vel) => Some(*vel),
136 Self::Acceleration(_) => None,
137 }
138 }
139 pub const fn get_acceleration(&self) -> $acc {
143 if let Self::Acceleration(acc) = self {
144 *acc
145 } else {
146 <$acc>::new(0.0)
147 }
148 }
149 }
150 impl GenericCommand for $name {
151 type Position = $pos;
152 type Velocity = $vel;
153 type Acceleration = $acc;
154 type CorrespondingState = $corresponding_state;
155 #[inline]
156 fn generic_new(position_derivative: PositionDerivative, value: f32) -> Self {
157 Self::new(position_derivative, value)
158 }
159 #[inline]
160 fn generic_get_position(&self) -> Option<$pos> {
161 self.get_position()
162 }
163 #[inline]
164 fn generic_get_velocity(&self) -> Option<$vel> {
165 self.get_velocity()
166 }
167 #[inline]
168 fn generic_get_acceleration(&self) -> $acc {
169 self.get_acceleration()
170 }
171 }
172 impl From<$pos> for $name {
173 fn from(was: $pos) -> Self {
174 Self::Position(was)
175 }
176 }
177 impl From<$vel> for $name {
178 fn from(was: $vel) -> Self {
179 Self::Velocity(was)
180 }
181 }
182 impl From<$acc> for $name {
183 fn from(was: $acc) -> Self {
184 Self::Acceleration(was)
185 }
186 }
187 impl From<$corresponding_state> for $name {
188 fn from(state: $corresponding_state) -> Self {
189 if state.acceleration == <$acc>::new(0.0) {
190 if state.velocity == <$vel>::new(0.0) {
191 Self::Position(state.position)
192 } else {
193 Self::Velocity(state.velocity)
194 }
195 } else {
196 Self::Acceleration(state.acceleration)
197 }
198 }
199 }
200 impl From<$name> for f32 {
201 fn from(was: $name) -> f32 {
202 match was {
203 $name::Position(pos) => pos.into_inner(),
204 $name::Velocity(vel) => vel.into_inner(),
205 $name::Acceleration(acc) => acc.into_inner(),
206 }
207 }
208 }
209 impl Add for $name {
210 type Output = Self;
211 fn add(self, rhs: Self) -> Self {
212 let self_pos_der = PositionDerivative::from(self);
213 assert_eq!(self_pos_der, PositionDerivative::from(rhs));
214 Self::new(self_pos_der, f32::from(self) + f32::from(rhs))
215 }
216 }
217 impl Sub for $name {
218 type Output = Self;
219 fn sub(self, rhs: Self) -> Self {
220 let self_pos_der = PositionDerivative::from(self);
221 assert_eq!(self_pos_der, PositionDerivative::from(rhs));
222 Self::new(self_pos_der, f32::from(self) - f32::from(rhs))
223 }
224 }
225 impl Mul<Dimensionless<f32>> for $name {
226 type Output = Self;
227 fn mul(self, rhs: Dimensionless<f32>) -> Self {
228 match self {
229 Self::Position(pos) => Self::Position(pos * rhs),
230 Self::Velocity(vel) => Self::Velocity(vel * rhs),
231 Self::Acceleration(acc) => Self::Acceleration(acc * rhs),
232 }
233 }
234 }
235 impl Div<Dimensionless<f32>> for $name {
236 type Output = Self;
237 fn div(self, rhs: Dimensionless<f32>) -> Self {
238 match self {
239 Self::Position(pos) => Self::Position(pos / rhs),
240 Self::Velocity(vel) => Self::Velocity(vel / rhs),
241 Self::Acceleration(vel) => Self::Acceleration(vel / rhs),
242 }
243 }
244 }
245 impl Neg for $name {
246 type Output = Self;
247 fn neg(self) -> Self {
248 match self {
249 Self::Position(pos) => Self::Position(-pos),
250 Self::Velocity(vel) => Self::Velocity(-vel),
251 Self::Acceleration(acc) => Self::Acceleration(-acc),
252 }
253 }
254 }
255 impl AddAssign for $name {
256 fn add_assign(&mut self, rhs: Self) {
257 *self = *self + rhs;
258 }
259 }
260 impl SubAssign for $name {
261 fn sub_assign(&mut self, rhs: Self) {
262 *self = *self - rhs;
263 }
264 }
265 impl MulAssign<Dimensionless<f32>> for $name {
268 fn mul_assign(&mut self, rhs: Dimensionless<f32>) {
269 match self {
270 Self::Position(pos) => *pos *= rhs,
271 Self::Velocity(vel) => *vel *= rhs,
272 Self::Acceleration(acc) => *acc *= rhs,
273 }
274 }
275 }
276 impl DivAssign<Dimensionless<f32>> for $name {
277 fn div_assign(&mut self, rhs: Dimensionless<f32>) {
278 match self {
279 Self::Position(pos) => *pos /= rhs,
280 Self::Velocity(vel) => *vel /= rhs,
281 Self::Acceleration(acc) => *acc /= rhs,
282 }
283 }
284 }
285 impl From<$name> for PositionDerivative {
286 fn from(was: $name) -> Self {
287 match was {
288 $name::Position(_) => Self::Position,
289 $name::Velocity(_) => Self::Velocity,
290 $name::Acceleration(_) => Self::Acceleration,
291 }
292 }
293 }
294 };
295}
296build_command_enum!(
297 LinearCommand,
298 Millimeter<f32>,
299 MillimeterPerSecond<f32>,
300 MillimeterPerSecondSquared<f32>,
301 LinearState
302);
303build_command_enum!(
304 AngularCommand,
305 Dimensionless<f32>,
306 InverseSecond<f32>,
307 InverseSecondSquared<f32>,
308 AngularState
309);
310impl Mul<Millimeter<f32>> for AngularCommand {
311 type Output = LinearCommand;
312 fn mul(self, rhs: Millimeter<f32>) -> LinearCommand {
313 match self {
314 Self::Position(pos) => LinearCommand::Position(pos * rhs),
315 Self::Velocity(vel) => LinearCommand::Velocity(vel * rhs),
316 Self::Acceleration(acc) => LinearCommand::Acceleration(acc * rhs),
317 }
318 }
319}
320impl Div<Millimeter<f32>> for LinearCommand {
321 type Output = AngularCommand;
322 fn div(self, rhs: Millimeter<f32>) -> AngularCommand {
323 match self {
324 Self::Position(pos) => AngularCommand::Position(pos / rhs),
325 Self::Velocity(vel) => AngularCommand::Velocity(vel / rhs),
326 Self::Acceleration(acc) => AngularCommand::Acceleration(acc / rhs),
327 }
328 }
329}