rrtk/
lib.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright 2024 UxuginPython
3//!# Rust Robotics ToolKit
4//!**A set of algorithms and other tools for robotics in Rust.**
5//!
6//!It is almost entirely `no_std` and most things work without `alloc`. It does not currently integrate with any API directly. This may be added in the future, probably through another crate.
7//!## Feature Flags
8//!- `alloc` - Enable items requiring dynamic allocation through Rust's builtin `alloc` crate.
9//!- `std` - Enable items requiring the Rust standard library. Requires `alloc` feature. Enabled by default.
10//!- `devices` - Enable RRTK's graph-based device system.
11//!- `dim_check_debug` - Enable dimension checking in debug mode. Enabled by default.
12//!- `dim_check_release` - Enable dimension checking in both debug mode and release mode. Requires `dim_check_debug` feature.
13//!- `libm` - Use [`libm`](https://crates.io/crates/libm) for float exponentiation when `std` is not available.
14//!- `micromath` - Use [`micromath`](https://crates.io/crates/micromath) for float exponentiation
15//!when `std` and `libm` are unavailable.
16//!
17//!RRTK prefers **`std`** over **`libm`** and `libm` over **`micromath`** when multiple are
18//!available.
19#![warn(missing_docs)]
20#![cfg_attr(not(feature = "std"), no_std)]
21#[cfg(feature = "std")]
22use alloc::sync::Arc;
23#[cfg(feature = "std")]
24use std::sync::{Mutex, RwLock};
25#[cfg(feature = "alloc")]
26extern crate alloc;
27#[cfg(feature = "alloc")]
28use alloc::rc::Rc;
29#[cfg(feature = "alloc")]
30use alloc::vec::Vec;
31//There is nothing preventing this from being used without any features; we just don't currently,
32//and it makes Cargo show a warning since there's an unused use.
33#[cfg(any(feature = "alloc", feature = "devices"))]
34use core::cell::RefCell;
35use core::fmt::Debug;
36use core::marker::PhantomData;
37use core::ops::{
38    Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Not, Sub, SubAssign,
39};
40mod command;
41mod datum;
42#[cfg(feature = "devices")]
43pub mod devices;
44pub mod dimensions;
45pub use dimensions::*;
46mod motion_profile;
47pub mod reference;
48mod state;
49pub mod streams;
50pub use command::*;
51pub use datum::*;
52pub use motion_profile::*;
53#[cfg(feature = "alloc")]
54pub use reference::rc_ref_cell_reference;
55pub use reference::Reference;
56#[cfg(feature = "std")]
57pub use reference::{arc_mutex_reference, arc_rw_lock_reference};
58pub use state::*;
59///RRTK follows the enum style of error handling. This is the error type returned from nearly all
60///RRTK types, but you can add your own custom error type using `Other(O)`. It is strongly
61///recommended that you use a single `O` type across your crate.
62#[derive(Clone, Copy, Debug, PartialEq)]
63#[non_exhaustive]
64pub enum Error<O: Copy + Debug> {
65    ///Returned when a `None` is elevated to an error by a
66    ///[`NoneToError`](streams::converters::NoneToError).
67    FromNone,
68    ///A custom error of a user-defined type. Not created by any RRTK type but can be propagated by
69    ///them.
70    Other(O),
71}
72///A derivative of position: position, velocity, or acceleration.
73#[derive(Clone, Copy, Debug, PartialEq)]
74pub enum PositionDerivative {
75    ///Where you are.
76    Position,
77    ///How fast you're going.
78    Velocity,
79    ///How fast how fast you're going's changing.
80    Acceleration,
81}
82//TODO: figure out for to use the Error enum with this
83#[cfg(any(
84    feature = "dim_check_release",
85    all(debug_assertions, feature = "dim_check_debug")
86))]
87impl TryFrom<Unit> for PositionDerivative {
88    type Error = ();
89    fn try_from(was: Unit) -> Result<Self, ()> {
90        Ok(match was {
91            MILLIMETER => PositionDerivative::Position,
92            MILLIMETER_PER_SECOND => PositionDerivative::Velocity,
93            MILLIMETER_PER_SECOND_SQUARED => PositionDerivative::Acceleration,
94            _ => return Err(()),
95        })
96    }
97}
98impl From<Command> for PositionDerivative {
99    fn from(was: Command) -> Self {
100        match was {
101            Command::Position(_) => Self::Position,
102            Command::Velocity(_) => Self::Velocity,
103            Command::Acceleration(_) => Self::Acceleration,
104        }
105    }
106}
107impl TryFrom<MotionProfilePiece> for PositionDerivative {
108    type Error = ();
109    fn try_from(was: MotionProfilePiece) -> Result<Self, ()> {
110        match was {
111            MotionProfilePiece::BeforeStart | MotionProfilePiece::Complete => Err(()),
112            MotionProfilePiece::InitialAcceleration | MotionProfilePiece::EndAcceleration => {
113                Ok(PositionDerivative::Acceleration)
114            }
115            MotionProfilePiece::ConstantVelocity => Ok(PositionDerivative::Velocity),
116        }
117    }
118}
119///Coefficients for a PID controller.
120#[derive(Clone, Copy, Debug, PartialEq)]
121pub struct PIDKValues {
122    ///Proportional coefficient.
123    pub kp: f32,
124    ///Integral coefficient.
125    pub ki: f32,
126    ///Derivative coefficient.
127    pub kd: f32,
128}
129impl PIDKValues {
130    ///Constructor for [`PIDKValues`].
131    pub const fn new(kp: f32, ki: f32, kd: f32) -> Self {
132        Self {
133            kp: kp,
134            ki: ki,
135            kd: kd,
136        }
137    }
138    ///Calculate the control variable using the coefficients given error, its integral, and its
139    ///derivative.
140    #[inline]
141    pub fn evaluate(&self, error: f32, error_integral: f32, error_derivative: f32) -> f32 {
142        self.kp * error + self.ki * error_integral + self.kd * error_derivative
143    }
144}
145///A set of PID k-values for controlling each position derivative.
146#[derive(Clone, Copy, Debug, PartialEq)]
147pub struct PositionDerivativeDependentPIDKValues {
148    ///Use these k-values when controlling position.
149    pub position: PIDKValues,
150    ///Use these k-values when controlling velocity.
151    pub velocity: PIDKValues,
152    ///Use these k-values when controlling acceleration.
153    pub acceleration: PIDKValues,
154}
155impl PositionDerivativeDependentPIDKValues {
156    ///Constructor for [`PositionDerivativeDependentPIDKValues`].
157    pub const fn new(position: PIDKValues, velocity: PIDKValues, acceleration: PIDKValues) -> Self {
158        Self {
159            position: position,
160            velocity: velocity,
161            acceleration: acceleration,
162        }
163    }
164    ///Get the k-values for a specific position derivative.
165    #[inline]
166    pub fn get_k_values(&self, position_derivative: PositionDerivative) -> PIDKValues {
167        match position_derivative {
168            PositionDerivative::Position => self.position,
169            PositionDerivative::Velocity => self.velocity,
170            PositionDerivative::Acceleration => self.acceleration,
171        }
172    }
173    ///Calculate the control variable using the coefficients for a given position derivative given
174    ///error, its integral, and its derivative.
175    #[inline]
176    pub fn evaluate(
177        &self,
178        position_derivative: PositionDerivative,
179        error: f32,
180        error_integral: f32,
181        error_derivative: f32,
182    ) -> f32 {
183        self.get_k_values(position_derivative)
184            .evaluate(error, error_integral, error_derivative)
185    }
186}
187///A generic output type when something may return an error, nothing, or something with a
188///timestamp.
189pub type Output<T, E> = Result<Option<Datum<T>>, Error<E>>;
190///Returned from [`TimeGetter`] objects, which may return either a time or an error.
191pub type TimeOutput<E> = Result<Time, Error<E>>;
192///Returned when something may return either nothing or an error.
193pub type NothingOrError<E> = Result<(), Error<E>>;
194///An object for getting the absolute time.
195pub trait TimeGetter<E: Copy + Debug>: Updatable<E> {
196    ///Get the time.
197    fn get(&self) -> TimeOutput<E>;
198}
199///An object that can return a value, like a [`Getter`], for a given time.
200pub trait History<T, E: Copy + Debug>: Updatable<E> {
201    ///Get a value at a time.
202    fn get(&self, time: Time) -> Option<Datum<T>>;
203}
204///Something with an [`update`](Updatable::update) method. Mostly for subtraiting.
205pub trait Updatable<E: Copy + Debug> {
206    ///As this trait is very generic, exactly what this does will be very dependent on the
207    ///implementor.
208    fn update(&mut self) -> NothingOrError<E>;
209}
210///Something with a [`get`](Getter::get) method. Structs implementing this will often be chained for easier data
211///processing, with a struct having other implementors in fields which will have some operation
212///performed on their output before it being passed on. Data processing Getters with other Getters
213///as fields can be referred to as streams, though this is only in naming and trait-wise there is
214///no distinction. The other common use for this trait is encoders. These should not be called
215///streams.
216pub trait Getter<G, E: Copy + Debug>: Updatable<E> {
217    ///Get something.
218    fn get(&self) -> Output<G, E>;
219}
220///Internal data needed for following a [`Getter`] with a [`Settable`].
221pub struct SettableData<S, E: Copy + Debug> {
222    following: Option<Reference<dyn Getter<S, E>>>,
223    last_request: Option<S>,
224}
225impl<S, E: Copy + Debug> SettableData<S, E> {
226    ///Constructor for [`SettableData`].
227    pub const fn new() -> Self {
228        Self {
229            following: None,
230            last_request: None,
231        }
232    }
233}
234///Something with a [`set`](Settable::set) method. Usually used for motors and other mechanical components and
235///systems. This trait too is fairly broad.
236pub trait Settable<S: Clone, E: Copy + Debug>: Updatable<E> {
237    ///Set something, not updating the internal [`SettableData`]. Due to current limitations of the
238    ///language, you must implement this but call [`set`](Settable::set). Do not call this directly as it will make
239    ///[`get_last_request`](Settable::get_last_request) work incorrectly.
240    fn impl_set(&mut self, value: S) -> NothingOrError<E>;
241    ///Set something to a value. For example, this could set a motor to a voltage. You should call
242    ///this and not [`impl_set`](Settable::impl_set).
243    fn set(&mut self, value: S) -> NothingOrError<E> {
244        self.impl_set(value.clone())?;
245        let data = self.get_settable_data_mut();
246        data.last_request = Some(value);
247        Ok(())
248    }
249    ///As traits cannot have fields, get functions and separate types are required. All you have to
250    ///do is make a field for a corresponding [`SettableData`], make this return an immutable
251    ///reference to it, and make [`get_settable_data_mut`](Settable::get_settable_data_mut)
252    ///return a mutable reference to it.
253    fn get_settable_data_ref(&self) -> &SettableData<S, E>;
254    ///As traits cannot have fields, get functions and separate types are required. All you have to
255    ///do is make a field for a corresponding [`SettableData`], make this return a mutable
256    ///reference to it, and make [`get_settable_data_ref`](Settable::get_settable_data_ref)
257    ///return an immutable reference to it.
258    fn get_settable_data_mut(&mut self) -> &mut SettableData<S, E>;
259    ///Begin following a [`Getter`] of the same type. For this to work, you must have
260    ///[`update_following_data`](Settable::update_following_data) in your [`Updatable`] implementation.
261    fn follow(&mut self, getter: Reference<dyn Getter<S, E>>) {
262        let data = self.get_settable_data_mut();
263        data.following = Some(getter);
264    }
265    ///Stop following the [`Getter`].
266    fn stop_following(&mut self) {
267        let data = self.get_settable_data_mut();
268        data.following = None;
269    }
270    ///Get a new value from the [`Getter`] we're following, if there is one, and call
271    ///[`set`](Settable::set)
272    ///accordingly. You must add this to your [`Updatable`] implementation if you are following
273    ///[`Getter`]s. This is a current limitation of the Rust language. If specialization is ever
274    ///stabilized, this will hopefully be done in a better way.
275    fn update_following_data(&mut self) -> NothingOrError<E> {
276        let data = self.get_settable_data_ref();
277        match &data.following {
278            None => {}
279            Some(getter) => {
280                let new_value = getter.borrow().get()?;
281                match new_value {
282                    None => {
283                        return Ok(());
284                    }
285                    Some(datum) => {
286                        self.set(datum.value)?;
287                    }
288                }
289            }
290        }
291        Ok(())
292    }
293    ///Get the argument from the last time [`set`](Settable::set) was called.
294    fn get_last_request(&self) -> Option<S> {
295        let data = self.get_settable_data_ref();
296        data.last_request.clone()
297    }
298}
299///Because [`Getter`]s always return a timestamp (as long as they don't return `Err(_)` or
300///`Ok(None)`), we can use this to treat them like [`TimeGetter`]s.
301pub struct TimeGetterFromGetter<T: Clone, G: Getter<T, E> + ?Sized, E: Copy + Debug> {
302    elevator: streams::converters::NoneToError<T, G, E>,
303}
304impl<T: Clone, G: Getter<T, E> + ?Sized, E: Copy + Debug> TimeGetterFromGetter<T, G, E> {
305    ///Constructor for [`TimeGetterFromGetter`].
306    pub const fn new(stream: Reference<G>) -> Self {
307        Self {
308            elevator: streams::converters::NoneToError::new(stream),
309        }
310    }
311}
312impl<T: Clone, G: Getter<T, E> + ?Sized, E: Copy + Debug> TimeGetter<E>
313    for TimeGetterFromGetter<T, G, E>
314{
315    fn get(&self) -> TimeOutput<E> {
316        let output = self.elevator.get()?;
317        let output = output.expect("`NoneToError` made all `Ok(None)`s into `Err(_)`s, and `?` returned all `Err(_)`s, so we're sure this is now an `Ok(Some(_))`.");
318        return Ok(output.time);
319    }
320}
321impl<T: Clone, G: Getter<T, E> + ?Sized, E: Copy + Debug> Updatable<E>
322    for TimeGetterFromGetter<T, G, E>
323{
324    fn update(&mut self) -> NothingOrError<E> {
325        Ok(())
326    }
327}
328///As histories return values at times, we can ask them to return values at the time of now or now
329///with a delta. This makes that much easier and is the recommended way of following
330///[`MotionProfile`]s.
331pub struct GetterFromHistory<'a, G, TG: TimeGetter<E>, E: Copy + Debug> {
332    history: &'a mut dyn History<G, E>,
333    time_getter: Reference<TG>,
334    time_delta: Time,
335}
336impl<'a, G, TG: TimeGetter<E>, E: Copy + Debug> GetterFromHistory<'a, G, TG, E> {
337    ///Constructor such that the time in the request to the history will be directly that returned
338    ///from the [`TimeGetter`] with no delta.
339    pub fn new_no_delta(history: &'a mut impl History<G, E>, time_getter: Reference<TG>) -> Self {
340        Self {
341            history: history,
342            time_getter: time_getter,
343            time_delta: Time::default(),
344        }
345    }
346    ///Constructor such that the times requested from the [`History`] will begin at zero where zero
347    ///is the moment this constructor is called.
348    pub fn new_start_at_zero(
349        history: &'a mut impl History<G, E>,
350        time_getter: Reference<TG>,
351    ) -> Result<Self, Error<E>> {
352        let time_delta = -time_getter.borrow().get()?;
353        Ok(Self {
354            history: history,
355            time_getter: time_getter,
356            time_delta: time_delta,
357        })
358    }
359    ///Constructor such that the times requested from the [`History`] will start at a given time with
360    ///that time defined as the moment of construction.
361    pub fn new_custom_start(
362        history: &'a mut impl History<G, E>,
363        time_getter: Reference<TG>,
364        start: Time,
365    ) -> Result<Self, Error<E>> {
366        let time_delta = start - time_getter.borrow().get()?;
367        Ok(Self {
368            history: history,
369            time_getter: time_getter,
370            time_delta: time_delta,
371        })
372    }
373    ///Constructor with a custom time delta.
374    pub fn new_custom_delta(
375        history: &'a mut impl History<G, E>,
376        time_getter: Reference<TG>,
377        time_delta: Time,
378    ) -> Self {
379        Self {
380            history: history,
381            time_getter: time_getter,
382            time_delta: time_delta,
383        }
384    }
385    ///Set the time delta.
386    pub fn set_delta(&mut self, time_delta: Time) {
387        self.time_delta = time_delta;
388    }
389    ///Define now as a given time in the history. Mostly used when construction and use are far
390    ///apart in time.
391    pub fn set_time(&mut self, time: Time) -> NothingOrError<E> {
392        let time_delta = time - self.time_getter.borrow().get()?;
393        self.time_delta = time_delta;
394        Ok(())
395    }
396}
397impl<G, TG: TimeGetter<E>, E: Copy + Debug> Updatable<E> for GetterFromHistory<'_, G, TG, E> {
398    fn update(&mut self) -> NothingOrError<E> {
399        self.history.update()?;
400        self.time_getter.borrow_mut().update()?;
401        Ok(())
402    }
403}
404impl<G, TG: TimeGetter<E>, E: Copy + Debug> Getter<G, E> for GetterFromHistory<'_, G, TG, E> {
405    fn get(&self) -> Output<G, E> {
406        let time = self.time_getter.borrow().get()?;
407        Ok(match self.history.get(time + self.time_delta) {
408            Some(datum) => Some(Datum::new(time, datum.value)),
409            None => None,
410        })
411    }
412}
413///Getter for returning a constant value.
414pub struct ConstantGetter<T: Clone, TG: TimeGetter<E> + ?Sized, E: Copy + Debug> {
415    settable_data: SettableData<T, E>,
416    time_getter: Reference<TG>,
417    value: T,
418}
419impl<T: Clone, TG: TimeGetter<E> + ?Sized, E: Copy + Debug> ConstantGetter<T, TG, E> {
420    ///Constructor for [`ConstantGetter`].
421    pub const fn new(time_getter: Reference<TG>, value: T) -> Self {
422        Self {
423            settable_data: SettableData::new(),
424            time_getter: time_getter,
425            value: value,
426        }
427    }
428}
429impl<T: Clone, TG: TimeGetter<E> + ?Sized, E: Copy + Debug> Getter<T, E>
430    for ConstantGetter<T, TG, E>
431{
432    fn get(&self) -> Output<T, E> {
433        let time = self.time_getter.borrow().get()?;
434        Ok(Some(Datum::new(time, self.value.clone())))
435    }
436}
437impl<T: Clone, TG: TimeGetter<E> + ?Sized, E: Copy + Debug> Settable<T, E>
438    for ConstantGetter<T, TG, E>
439{
440    fn get_settable_data_ref(&self) -> &SettableData<T, E> {
441        &self.settable_data
442    }
443    fn get_settable_data_mut(&mut self) -> &mut SettableData<T, E> {
444        &mut self.settable_data
445    }
446    fn impl_set(&mut self, value: T) -> NothingOrError<E> {
447        self.value = value;
448        Ok(())
449    }
450}
451impl<T: Clone, TG: TimeGetter<E> + ?Sized, E: Copy + Debug> Updatable<E>
452    for ConstantGetter<T, TG, E>
453{
454    ///This does not need to be called.
455    fn update(&mut self) -> NothingOrError<E> {
456        self.update_following_data()?;
457        Ok(())
458    }
459}
460///Getter always returning `Ok(None)`.
461pub struct NoneGetter;
462impl NoneGetter {
463    ///Constructor for [`NoneGetter`]. Since [`NoneGetter`] is a unit struct, you can use this or just
464    ///the struct's name.
465    pub const fn new() -> Self {
466        Self
467    }
468}
469impl<T, E: Copy + Debug> Getter<T, E> for NoneGetter {
470    fn get(&self) -> Output<T, E> {
471        Ok(None)
472    }
473}
474impl<E: Copy + Debug> Updatable<E> for NoneGetter {
475    fn update(&mut self) -> NothingOrError<E> {
476        Ok(())
477    }
478}
479impl<E: Copy + Debug> TimeGetter<E> for Time {
480    fn get(&self) -> TimeOutput<E> {
481        Ok(*self)
482    }
483}
484impl<E: Copy + Debug> Updatable<E> for Time {
485    fn update(&mut self) -> NothingOrError<E> {
486        Ok(())
487    }
488}
489///A place where a device can connect to another.
490#[cfg(feature = "devices")]
491pub struct Terminal<'a, E: Copy + Debug> {
492    settable_data_state: SettableData<Datum<State>, E>,
493    settable_data_command: SettableData<Datum<Command>, E>,
494    other: Option<&'a RefCell<Terminal<'a, E>>>,
495}
496#[cfg(feature = "devices")]
497impl<E: Copy + Debug> Terminal<'_, E> {
498    ///Direct constructor for a [`Terminal`]. You almost always actually want [`RefCell<Terminal>`]
499    ///however, in which case you should call [`new`](Terminal::new), which returns [`RefCell<Terminal>`].
500    pub const fn new_raw() -> Self {
501        Self {
502            settable_data_state: SettableData::new(),
503            settable_data_command: SettableData::new(),
504            other: None,
505        }
506    }
507    ///This constructs a [`RefCell<Terminal>`]. This is almost always what you want, and what is
508    ///needed for connecting terminals. If you do just want a [`Terminal`], use
509    ///[`new_raw`](Terminal::new_raw) instead.
510    pub const fn new() -> RefCell<Self> {
511        RefCell::new(Self::new_raw())
512    }
513    ///Disconnect this terminal and the one that it is connected to. You can connect terminals by
514    ///calling the [`rrtk::connect`](connect) function.
515    pub fn disconnect(&mut self) {
516        match self.other {
517            Some(other) => {
518                let mut other = other.borrow_mut();
519                other.other = None;
520                self.other = None;
521            }
522            None => (),
523        }
524    }
525}
526#[cfg(feature = "devices")]
527impl<E: Copy + Debug> Settable<Datum<State>, E> for Terminal<'_, E> {
528    fn get_settable_data_ref(&self) -> &SettableData<Datum<State>, E> {
529        &self.settable_data_state
530    }
531    fn get_settable_data_mut(&mut self) -> &mut SettableData<Datum<State>, E> {
532        &mut self.settable_data_state
533    }
534    //SettableData takes care of this for us.
535    fn impl_set(&mut self, _state: Datum<State>) -> NothingOrError<E> {
536        Ok(())
537    }
538}
539#[cfg(feature = "devices")]
540impl<E: Copy + Debug> Settable<Datum<Command>, E> for Terminal<'_, E> {
541    fn get_settable_data_ref(&self) -> &SettableData<Datum<Command>, E> {
542        &self.settable_data_command
543    }
544    fn get_settable_data_mut(&mut self) -> &mut SettableData<Datum<Command>, E> {
545        &mut self.settable_data_command
546    }
547    fn impl_set(&mut self, _command: Datum<Command>) -> NothingOrError<E> {
548        Ok(())
549    }
550}
551#[cfg(feature = "devices")]
552impl<E: Copy + Debug> Getter<State, E> for Terminal<'_, E> {
553    fn get(&self) -> Output<State, E> {
554        let mut addends: [core::mem::MaybeUninit<Datum<State>>; 2] =
555            [core::mem::MaybeUninit::uninit(); 2];
556        let mut addend_count = 0usize;
557        match self.get_last_request() {
558            Some(state) => {
559                addends[0].write(state);
560                addend_count += 1;
561            }
562            None => (),
563        }
564        match self.other {
565            Some(other) => match other.borrow().get_last_request() {
566                Some(state) => {
567                    addends[addend_count].write(state);
568                    addend_count += 1;
569                }
570                None => (),
571            },
572            None => (),
573        }
574        unsafe {
575            match addend_count {
576                0 => return Ok(None),
577                1 => return Ok(Some(addends[0].assume_init())),
578                2 => {
579                    return Ok(Some(
580                        (addends[0].assume_init() + addends[1].assume_init()) / 2.0,
581                    ))
582                }
583                _ => unimplemented!(),
584            }
585        }
586    }
587}
588#[cfg(feature = "devices")]
589impl<E: Copy + Debug> Getter<Command, E> for Terminal<'_, E> {
590    fn get(&self) -> Output<Command, E> {
591        let mut maybe_command: Option<Datum<Command>> = None;
592        match self.get_last_request() {
593            Some(command) => {
594                maybe_command = Some(command);
595            }
596            None => {}
597        }
598        match self.other {
599            Some(other) => {
600                match <Terminal<'_, E> as Settable<Datum<Command>, E>>::get_last_request(
601                    &other.borrow(),
602                ) {
603                    Some(gotten_command) => match maybe_command {
604                        Some(command_some) => {
605                            if gotten_command.time > command_some.time {
606                                maybe_command = Some(gotten_command);
607                            }
608                        }
609                        None => {
610                            maybe_command = Some(gotten_command);
611                        }
612                    },
613                    None => (),
614                }
615            }
616            None => (),
617        }
618        Ok(maybe_command)
619    }
620}
621#[cfg(feature = "devices")]
622impl<E: Copy + Debug> Getter<TerminalData, E> for Terminal<'_, E> {
623    fn get(&self) -> Output<TerminalData, E> {
624        let command = self.get().expect("Terminal get cannot return Err");
625        let state = self.get().expect("Terminal get cannot return Err");
626        let (mut time, command) = match command {
627            Some(datum_command) => (Some(datum_command.time), Some(datum_command.value)),
628            None => (None, None),
629        };
630        let state = match state {
631            Some(datum_state) => {
632                time = Some(datum_state.time);
633                Some(datum_state.value)
634            }
635            None => None,
636        };
637        Ok(match time {
638            Some(time) => Some(Datum::new(
639                time,
640                TerminalData {
641                    time: time,
642                    command: command,
643                    state: state,
644                },
645            )),
646            None => None,
647        })
648    }
649}
650#[cfg(feature = "devices")]
651impl<E: Copy + Debug> Updatable<E> for Terminal<'_, E> {
652    fn update(&mut self) -> NothingOrError<E> {
653        <Terminal<'_, E> as Settable<Datum<Command>, E>>::update_following_data(self)?;
654        <Terminal<'_, E> as Settable<Datum<State>, E>>::update_following_data(self)?;
655        Ok(())
656    }
657}
658///Connect two terminals. Connected terminals should represent a physical connection between
659///mechanical devices. This function will automatically disconnect the specified terminals if they
660///are connected. You can manually disconnect terminals by calling the
661///[`disconnect`](Terminal::disconnect) method on either of them.
662#[cfg(feature = "devices")]
663pub fn connect<'a, E: Copy + Debug>(
664    term1: &'a RefCell<Terminal<'a, E>>,
665    term2: &'a RefCell<Terminal<'a, E>>,
666) {
667    let mut term1_borrow = term1.borrow_mut();
668    let mut term2_borrow = term2.borrow_mut();
669    term1_borrow.disconnect();
670    term2_borrow.disconnect();
671    term1_borrow.other = Some(term2);
672    term2_borrow.other = Some(term1);
673}
674///Data that are sent between terminals: A timestamp, an optional command, and a state.
675#[cfg(feature = "devices")]
676#[derive(Clone, Copy, Debug, PartialEq)]
677pub struct TerminalData {
678    ///Timestamp.
679    pub time: Time,
680    ///Optional command from the terminal.
681    pub command: Option<Command>,
682    ///Optional state from the terminal.
683    pub state: Option<State>,
684}
685#[cfg(feature = "devices")]
686impl TryFrom<TerminalData> for Datum<Command> {
687    type Error = ();
688    fn try_from(value: TerminalData) -> Result<Datum<Command>, ()> {
689        match value.command {
690            Some(command) => Ok(Datum::new(value.time, command)),
691            None => Err(()),
692        }
693    }
694}
695#[cfg(feature = "devices")]
696impl TryFrom<TerminalData> for Datum<State> {
697    type Error = ();
698    fn try_from(value: TerminalData) -> Result<Datum<State>, ()> {
699        match value.state {
700            Some(state) => Ok(Datum::new(value.time, state)),
701            None => Err(()),
702        }
703    }
704}
705///A mechanical device.
706#[cfg(feature = "devices")]
707pub trait Device<E: Copy + Debug>: Updatable<E> {
708    ///Call only the [`update`](Terminal::update) methods of owned terminals and do not update anything else with the
709    ///device.
710    fn update_terminals(&mut self) -> NothingOrError<E>;
711}
712///Get the newer of two [`Datum`] objects.
713pub fn latest<T>(dat1: Datum<T>, dat2: Datum<T>) -> Datum<T> {
714    if dat1.time >= dat2.time {
715        dat1
716    } else {
717        dat2
718    }
719}