1use crate::*;
8pub mod wrappers;
9pub struct Invert<'a, E: Copy + Debug> {
13 term1: RefCell<Terminal<'a, E>>,
14 term2: RefCell<Terminal<'a, E>>,
15}
16impl<'a, E: Copy + Debug> Invert<'a, E> {
17 pub const fn new() -> Self {
19 Self {
20 term1: Terminal::new(),
21 term2: Terminal::new(),
22 }
23 }
24 pub fn get_terminal_1(&self) -> &'a RefCell<Terminal<'a, E>> {
26 unsafe { &*(&self.term1 as *const RefCell<Terminal<'a, E>>) }
31 }
32 pub fn get_terminal_2(&self) -> &'a RefCell<Terminal<'a, E>> {
34 unsafe { &*(&self.term2 as *const RefCell<Terminal<'a, E>>) }
35 }
36}
37impl<E: Copy + Debug> Updatable<E> for Invert<'_, E> {
38 fn update(&mut self) -> NothingOrError<E> {
39 self.update_terminals()?;
40 let get1: Option<Datum<State>> = self
41 .term1
42 .borrow()
43 .get()
44 .expect("Terminal get will always return Ok");
45 let get2: Option<Datum<State>> = self
46 .term2
47 .borrow()
48 .get()
49 .expect("Terminal get will always return Ok");
50 match get1 {
51 None => match get2 {
52 None => {}
53 Some(datum2) => {
54 let newdatum1 = Datum::new(datum2.time, -datum2.value);
55 self.term1.borrow_mut().set(newdatum1)?;
56 }
57 },
58 Some(datum1) => match get2 {
59 None => {
60 let newdatum2 = Datum::new(datum1.time, -datum1.value);
61 self.term2.borrow_mut().set(newdatum2)?;
62 }
63 Some(datum2) => {
64 let state1 = datum1.value;
65 let state2 = datum2.value;
66 let time = if datum1.time >= datum2.time {
67 datum1.time
68 } else {
69 datum2.time
70 };
71 let new_state = (state1 - state2) / 2.0;
73 self.term1.borrow_mut().set(Datum::new(time, new_state))?;
74 self.term2.borrow_mut().set(Datum::new(time, -new_state))?;
75 }
76 },
77 }
78 let get1: Option<Datum<Command>> = self
79 .term1
80 .borrow()
81 .get()
82 .expect("Terminal get will always return Ok");
83 let get2: Option<Datum<Command>> = self
84 .term2
85 .borrow()
86 .get()
87 .expect("Terminal get will always return Ok");
88 let mut maybe_datum: Option<Datum<Command>> = None;
89 maybe_datum.replace_if_none_or_older_than_option(get1);
90 match get2 {
91 Some(x) => {
92 maybe_datum.replace_if_none_or_older_than(-x);
93 }
94 None => {}
95 }
96 match maybe_datum {
97 Some(datum_command) => {
98 self.term1.borrow_mut().set(datum_command)?;
99 self.term2.borrow_mut().set(-datum_command)?;
100 }
101 None => {}
102 }
103 Ok(())
104 }
105}
106impl<E: Copy + Debug> Device<E> for Invert<'_, E> {
107 fn update_terminals(&mut self) -> NothingOrError<E> {
108 self.term1.borrow_mut().update()?;
109 self.term2.borrow_mut().update()?;
110 Ok(())
111 }
112}
113pub struct GearTrain<'a, E: Copy + Debug> {
117 term1: RefCell<Terminal<'a, E>>,
118 term2: RefCell<Terminal<'a, E>>,
119 ratio: f32,
120}
121impl<'a, E: Copy + Debug> GearTrain<'a, E> {
122 pub const fn with_ratio_raw(ratio: f32) -> Self {
124 Self {
125 term1: Terminal::new(),
126 term2: Terminal::new(),
127 ratio: ratio,
128 }
129 }
130 pub const fn with_ratio(ratio: Quantity) -> Self {
132 ratio.unit.assert_eq_assume_ok(&DIMENSIONLESS);
133 Self::with_ratio_raw(ratio.value)
134 }
135 pub const fn new<const N: usize>(teeth: [f32; N]) -> Self {
137 if N < 2 {
138 panic!("rrtk::devices::GearTrain::new must be provided with at least two gear tooth counts.");
139 }
140 let ratio = teeth[0] / teeth[teeth.len() - 1] * if N % 2 == 0 { -1.0 } else { 1.0 };
141 Self::with_ratio_raw(ratio)
142 }
143 pub fn get_terminal_1(&self) -> &'a RefCell<Terminal<'a, E>> {
145 unsafe { &*(&self.term1 as *const RefCell<Terminal<'a, E>>) }
146 }
147 pub fn get_terminal_2(&self) -> &'a RefCell<Terminal<'a, E>> {
149 unsafe { &*(&self.term2 as *const RefCell<Terminal<'a, E>>) }
150 }
151}
152impl<E: Copy + Debug> Updatable<E> for GearTrain<'_, E> {
153 fn update(&mut self) -> NothingOrError<E> {
154 self.update_terminals()?;
155 let get1: Option<Datum<State>> = self
156 .term1
157 .borrow()
158 .get()
159 .expect("Terminal get will always return Ok");
160 let get2: Option<Datum<State>> = self
161 .term2
162 .borrow()
163 .get()
164 .expect("Terminal get will always return Ok");
165 match get1 {
166 Some(datum1) => match get2 {
167 Some(datum2) => {
168 let state1 = datum1.value;
169 let state2 = datum2.value;
170 let time = if datum1.time >= datum2.time {
171 datum1.time
172 } else {
173 datum2.time
174 };
175 let r_squared_plus_1 = self.ratio * self.ratio + 1.0;
177 let x_plus_r_y = state1 + state2 * self.ratio;
178 let newstate1 = x_plus_r_y / r_squared_plus_1;
179 let newstate2 = (x_plus_r_y * self.ratio) / r_squared_plus_1;
180 self.term1.borrow_mut().set(Datum::new(time, newstate1))?;
181 self.term2.borrow_mut().set(Datum::new(time, newstate2))?;
182 }
183 None => {
184 let newdatum2 = datum1 * self.ratio;
185 self.term2.borrow_mut().set(newdatum2)?;
186 }
187 },
188 None => match get2 {
189 Some(datum2) => {
190 let newdatum1 = datum2 / self.ratio;
191 self.term1.borrow_mut().set(newdatum1)?;
192 }
193 None => {}
194 },
195 }
196 let get1: Option<Datum<Command>> = self
197 .term1
198 .borrow()
199 .get()
200 .expect("Terminal get will always return Ok");
201 let get2: Option<Datum<Command>> = self
202 .term2
203 .borrow()
204 .get()
205 .expect("Terminal get will always return Ok");
206 match get1 {
207 Some(datum1) => match get2 {
208 Some(datum2) => {
209 if datum1.time >= datum2.time {
210 let newdatum2 = datum1 * self.ratio;
211 self.term2.borrow_mut().set(newdatum2)?;
212 } else {
213 let newdatum1 = datum2 / self.ratio;
214 self.term1.borrow_mut().set(newdatum1)?;
215 }
216 }
217 None => {
218 let newdatum2 = datum1 * self.ratio;
219 self.term2.borrow_mut().set(newdatum2)?;
220 }
221 },
222 None => match get2 {
223 Some(datum2) => {
224 let newdatum1 = datum2 / self.ratio;
225 self.term1.borrow_mut().set(newdatum1)?;
226 }
227 None => {}
228 },
229 }
230 Ok(())
231 }
232}
233impl<E: Copy + Debug> Device<E> for GearTrain<'_, E> {
234 fn update_terminals(&mut self) -> NothingOrError<E> {
235 self.term1.borrow_mut().update()?;
236 self.term2.borrow_mut().update()?;
237 Ok(())
238 }
239}
240pub struct Axle<'a, const N: usize, E: Copy + Debug> {
251 inputs: [RefCell<Terminal<'a, E>>; N],
252}
253impl<'a, const N: usize, E: Copy + Debug> Axle<'a, N, E> {
254 pub fn new() -> Self {
256 let mut inputs: [core::mem::MaybeUninit<RefCell<Terminal<'a, E>>>; N] =
257 [const { core::mem::MaybeUninit::uninit() }; N];
258 for i in &mut inputs {
259 i.write(Terminal::new());
260 }
261 let inputs: [RefCell<Terminal<'a, E>>; N] = unsafe {
263 inputs
264 .as_ptr()
265 .cast::<[RefCell<Terminal<'a, E>>; N]>()
266 .read()
267 };
268 Self { inputs: inputs }
269 }
270 pub fn get_terminal(&self, terminal: usize) -> &'a RefCell<Terminal<'a, E>> {
272 unsafe { &*(&self.inputs[terminal] as *const RefCell<Terminal<'a, E>>) }
273 }
274}
275impl<const N: usize, E: Copy + Debug> Updatable<E> for Axle<'_, N, E> {
276 fn update(&mut self) -> NothingOrError<E> {
277 self.update_terminals()?;
278 let mut count = 0u16;
279 let mut datum = Datum::new(Time(i64::MIN), State::default());
280 for i in &self.inputs {
281 match i.borrow().get()? {
282 Some(gotten_datum) => {
283 datum += gotten_datum;
284 count += 1;
285 }
286 None => (),
287 }
288 }
289 if count >= 1 {
290 datum /= count as f32;
291 for i in &self.inputs {
292 i.borrow_mut().set(datum.clone())?;
293 }
294 }
295 let mut maybe_datum: Option<Datum<Command>> = None;
296 for i in &self.inputs {
297 maybe_datum.replace_if_none_or_older_than_option(i.borrow().get()?);
298 }
299 if let Some(datum) = maybe_datum {
300 for i in &self.inputs {
301 i.borrow_mut().set(datum.clone())?;
302 }
303 }
304 Ok(())
305 }
306}
307impl<const N: usize, E: Copy + Debug> Device<E> for Axle<'_, N, E> {
308 fn update_terminals(&mut self) -> NothingOrError<E> {
309 for i in &self.inputs {
310 i.borrow_mut().update()?;
311 }
312 Ok(())
313 }
314}
315pub enum DifferentialDistrust {
322 Side1,
324 Side2,
326 Sum,
328 Equal,
330}
331pub struct Differential<'a, E: Copy + Debug> {
335 side1: RefCell<Terminal<'a, E>>,
336 side2: RefCell<Terminal<'a, E>>,
337 sum: RefCell<Terminal<'a, E>>,
338 distrust: DifferentialDistrust,
339}
340impl<'a, E: Copy + Debug> Differential<'a, E> {
341 pub const fn new() -> Self {
343 Self {
344 side1: Terminal::new(),
345 side2: Terminal::new(),
346 sum: Terminal::new(),
347 distrust: DifferentialDistrust::Equal,
348 }
349 }
350 pub fn with_distrust(distrust: DifferentialDistrust) -> Self {
352 Self {
353 side1: Terminal::new(),
354 side2: Terminal::new(),
355 sum: Terminal::new(),
356 distrust: distrust,
357 }
358 }
359 pub fn get_side_1(&self) -> &'a RefCell<Terminal<'a, E>> {
361 unsafe { &*(&self.side1 as *const RefCell<Terminal<'a, E>>) }
362 }
363 pub fn get_side_2(&self) -> &'a RefCell<Terminal<'a, E>> {
365 unsafe { &*(&self.side2 as *const RefCell<Terminal<'a, E>>) }
366 }
367 pub fn get_sum(&self) -> &'a RefCell<Terminal<'a, E>> {
369 unsafe { &*(&self.sum as *const RefCell<Terminal<'a, E>>) }
370 }
371}
372impl<E: Copy + Debug> Updatable<E> for Differential<'_, E> {
373 fn update(&mut self) -> NothingOrError<E> {
374 self.update_terminals()?;
375 match self.distrust {
376 DifferentialDistrust::Side1 => {
377 let sum: Datum<State> = match self.sum.borrow().get()? {
378 Some(sum) => sum,
379 None => return Ok(()),
380 };
381 let side2: Datum<State> = match self.side2.borrow().get()? {
382 Some(side2) => side2,
383 None => return Ok(()),
384 };
385 self.side1.borrow_mut().set(sum - side2)?;
386 }
387 DifferentialDistrust::Side2 => {
388 let sum: Datum<State> = match self.sum.borrow().get()? {
389 Some(sum) => sum,
390 None => return Ok(()),
391 };
392 let side1: Datum<State> = match self.side1.borrow().get()? {
393 Some(side1) => side1,
394 None => return Ok(()),
395 };
396 self.side2.borrow_mut().set(sum - side1)?;
397 }
398 DifferentialDistrust::Sum => {
399 let side1: Datum<State> = match self.side1.borrow().get()? {
400 Some(side1) => side1,
401 None => return Ok(()),
402 };
403 let side2: Datum<State> = match self.side2.borrow().get()? {
404 Some(side2) => side2,
405 None => return Ok(()),
406 };
407 self.sum.borrow_mut().set(side1 + side2)?;
408 }
409 DifferentialDistrust::Equal => {
410 let sum: Datum<State> = match self.sum.borrow().get()? {
411 Some(sum) => sum,
412 None => return Ok(()),
413 };
414 let side1: Datum<State> = match self.side1.borrow().get()? {
415 Some(side1) => side1,
416 None => return Ok(()),
417 };
418 let side2: Datum<State> = match self.side2.borrow().get()? {
419 Some(side2) => side2,
420 None => return Ok(()),
421 };
422 self.sum
428 .borrow_mut()
429 .set((side1 + side2 + sum * 2.0) / 3.0)?;
430 self.side1
431 .borrow_mut()
432 .set((side1 * 2.0 - side2 + sum) / 3.0)?;
433 self.side2
434 .borrow_mut()
435 .set((-side1 + side2 * 2.0 + sum) / 3.0)?;
436 }
437 }
438 Ok(())
439 }
440}
441impl<E: Copy + Debug> Device<E> for Differential<'_, E> {
442 fn update_terminals(&mut self) -> NothingOrError<E> {
443 self.side1.borrow_mut().update()?;
444 self.side2.borrow_mut().update()?;
445 self.sum.borrow_mut().update()?;
446 Ok(())
447 }
448}