gmt_dos_clients_servos/
lib.rs

1/*!
2# GMT Servo-Mechanisms
3
4A dos-actors [system] that combines together a few clients:
5  * the GMT [FEM]
6  * the GMT [mount] control system
7  * the GMT [M1] control system
8  * the GMT [M2] control system
9
10Per default, only a few inputs and outputs of the FEM are made available:
11 * FEM inputs:
12   * [`MountTorques`](gmt_dos_clients_io::mount::MountTorques)
13   * [`M1HardpointsForces`](gmt_dos_clients_io::gmt_m1::assembly::M1HardpointsForces)
14   * [`HardpointsForces<ID>`](gmt_dos_clients_io::gmt_m1::segment::HardpointsForces)
15   * [`M1ActuatorAppliedForces`](gmt_dos_clients_io::gmt_m1::assembly::M1ActuatorAppliedForces)
16   * [`ActuatorAppliedForces<ID>`](gmt_dos_clients_io::gmt_m1::segment::ActuatorAppliedForces)
17   * [`M2ASMVoiceCoilsForces`](gmt_dos_clients_io::gmt_m2::asm::M2ASMVoiceCoilsForces)
18   * [`VoiceCoilsForces<ID>`](gmt_dos_clients_io::gmt_m2::asm::segment::VoiceCoilsForces)
19   * [`M2ASMFluidDampingForces`](gmt_dos_clients_io::gmt_m2::asm::M2ASMFluidDampingForces)
20   * [`FluidDampingForces<ID>`](gmt_dos_clients_io::gmt_m2::asm::segment::FluidDampingForces)
21   * [`M2PositionerForces`](gmt_dos_clients_io::gmt_m2::M2PositionerForces)
22 * FEM outputs
23   * [`MountEncoders`](gmt_dos_clients_io::mount::MountEncoders)
24   * [`M1HardpointsMotion`](gmt_dos_clients_io::gmt_m1::assembly::M1HardpointsMotion)
25   * [`HardpointsMotion<ID>`](gmt_dos_clients_io::gmt_m1::segment::HardpointsMotion)
26   * [`M1RigidBodyMotions`](gmt_dos_clients_io::gmt_m1::M1RigidBodyMotions)
27   * [`M2ASMVoiceCoilsMotion`](gmt_dos_clients_io::gmt_m2::asm::M2ASMVoiceCoilsMotion)
28   * [`VoiceCoilsMotion<ID>`](gmt_dos_clients_io::gmt_m2::asm::segment::VoiceCoilsMotion)
29   * [`M2RigidBodyMotions`](gmt_dos_clients_io::gmt_m2::M2RigidBodyMotions)
30   * [`M2PositionerNodes`](gmt_dos_clients_io::gmt_m2::M2PositionerNodes)
31
32Other builders will add extra inputs and outputs to the FEM.
33These builders are:
34  * [`AsmsServo`]
35     * [`Facesheet`][asms_servo::Facesheet]
36     * [`ReferenceBody`][asms_servo::ReferenceBody]
37     * [`VoiceCoils`][asms_servo::VoiceCoils]
38  * [`WindLoads`]
39  * [`EdgeSensors`]
40
41## Warning
42
43The `gmt_dos-clients_servos` crate depends on  some code that is generated at compile timed
44based on the value of the environment variables `FEM_REPO` and `MOUNT_MODEL`.
45To get the full documentation, you need to set the `FEM_REPO` environment variable and
46recompile the docs locally with:
47```shell
48FEM_REPO=<path-to-fem>  cargo doc --no-deps --package gmt_dos-clients_servos --open
49```
50
51## Example
52
53```no_run
54use gmt_dos_clients_servos::GmtServoMechanisms;
55use gmt_fem::FEM;
56
57const ACTUATOR_RATE: usize = 80; // 100Hz
58
59let frequency = 8000_f64; // Hz
60let fem = FEM::from_env()?;
61
62let gmt_servos =
63    GmtServoMechanisms::<ACTUATOR_RATE, 1>::new(frequency, fem).build()?;
64# Ok::<(), Box<dyn std::error::Error>>(())
65```
66
67[system]: https://docs.rs/gmt_dos-actors/latest/gmt_dos_actors/system
68[FEM]: https://docs.rs/gmt_dos-clients_fem/latest/gmt_dos_clients_fem/
69[mount]: https://docs.rs/gmt_dos-clients_mount/latest/gmt_dos_clients_mount/
70[M1]: https://docs.rs/gmt_dos-clients_m1-ctrl/latest/gmt_dos_clients_m1_ctrl/
71[M2]: https://docs.rs/gmt_dos-clients_m2-ctrl/latest/gmt_dos_clients_m2_ctrl/
72*/
73
74#[cfg(fem)]
75mod builder;
76#[cfg(fem)]
77mod servos;
78#[cfg(fem)]
79mod fem {
80    use crate::builder::ServosBuilderError;
81    #[cfg(topend = "ASM")]
82    pub use crate::builder::{AsmsServo, asms_servo};
83    pub use crate::builder::{EdgeSensors, M1SegmentFigure, ServosBuilder, WindLoads};
84    pub use crate::servos::GmtServoMechanisms;
85    use gmt_dos_actors::system::{Sys, SystemError};
86
87    #[cfg(not(feature = "cuda"))]
88    pub(crate) type FemSolver = gmt_dos_clients_fem::solvers::ExponentialMatrix;
89    #[cfg(feature = "cuda")]
90    pub(crate) type FemSolver = gmt_dos_clients_fem::solvers::CuStateSpace;
91
92    /// GMT servo-mechanisms system
93    // pub enum GmtServoMechanisms<const M1_RATE: usize, const M2_RATE: usize = 1> {}
94
95    impl<const M1_RATE: usize, const M2_RATE: usize> GmtServoMechanisms<M1_RATE, M2_RATE> {
96        /// Create a new [builder](ServosBuilder)
97        pub fn new(
98            sim_sampling_frequency: f64,
99            fem: gmt_fem::FEM,
100        ) -> ServosBuilder<M1_RATE, M2_RATE> {
101            ServosBuilder {
102                sim_sampling_frequency,
103                fem,
104                ..Default::default()
105            }
106        }
107    }
108
109    impl From<ServosBuilderError> for SystemError {
110        fn from(value: ServosBuilderError) -> Self {
111            SystemError::SubSystem(format!("{:?}", value))
112        }
113    }
114
115    impl<const M1_RATE: usize, const M2_RATE: usize> ServosBuilder<M1_RATE, M2_RATE> {
116        /// Build the system
117        pub fn build(self) -> Result<Sys<GmtServoMechanisms<M1_RATE, M2_RATE>>, SystemError> {
118            log::info!("building ServosBuilder");
119            Ok(Sys::new(GmtServoMechanisms::<M1_RATE, M2_RATE>::try_from(self)?).build()?)
120        }
121    }
122
123    impl<const M1_RATE: usize, const M2_RATE: usize> TryFrom<ServosBuilder<M1_RATE, M2_RATE>>
124        for Sys<GmtServoMechanisms<M1_RATE, M2_RATE>>
125    {
126        type Error = SystemError;
127
128        fn try_from(builder: ServosBuilder<M1_RATE, M2_RATE>) -> Result<Self, Self::Error> {
129            builder.build()
130        }
131    }
132
133    /// GMT FEM client
134    pub type GmtFem = gmt_dos_clients_fem::DiscreteModalSolver<FemSolver>;
135    /// GMT M1 client
136    pub type GmtM1 = gmt_dos_systems_m1::assembly::DispatchIn;
137    pub type GmtM1Out = gmt_dos_systems_m1::assembly::DispatchOut;
138    /// GMT mount client
139    pub type GmtMount = gmt_dos_clients_mount::Mount;
140    /// GMT M2 positioners client
141    pub type GmtM2Hex = gmt_dos_clients_m2_ctrl::Positioners;
142    /// GMT M2 mirror client
143    pub type GmtM2 = gmt_dos_systems_m2::DispatchIn;
144
145    #[cfg(test)]
146    mod tests {
147        use std::error::Error;
148
149        use gmt_dos_actors::actorscript;
150        use gmt_dos_clients::timer::Timer;
151        use interface::Tick;
152
153        pub use super::*;
154
155        #[test]
156        fn builder() {
157            let frequency = 1000_f64; // Hz
158            let fem = gmt_fem::FEM::from_env().unwrap();
159            assert!(GmtServoMechanisms::<10, 1>::new(frequency, fem)
160                .build()
161                .is_ok());
162        }
163    }
164}
165#[cfg(fem)]
166pub use fem::*;