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::*;