1#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
4#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
5pub enum Capability {
6 Motor(Motor),
7 Encoder(Encoder),
8 Accelerometer(Accelerometer),
9 Gyroscope(Gyroscope),
10 Magnetometer(Magnetometer),
11 Imu(Imu),
12 Gnss(Gnss),
13 Camera(Camera),
14 Depth(Depth),
15 EmergencyStop(EmergencyStop),
16 Range(Range),
17 Lidar(Lidar),
18 Mmwave(Mmwave),
19 Microphone(Microphone),
20 Speaker(Speaker),
21 Battery(Battery),
22 Led(Led),
23}
24
25#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
26#[serde(rename_all = "snake_case")]
27pub enum EncoderType {
28 Incremental,
29 Absolute,
30}
31
32#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
33#[serde(rename_all = "snake_case")]
34pub enum MotorCommand {
35 Position,
36 Velocity,
37 Torque,
38}
39
40#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
41#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
42pub enum StructuralTarget {
43 Joint { id: String },
44 Link { id: String },
45}
46
47pub const MODULE_INSTANCE_SEPARATOR: &str = "__";
48
49#[must_use]
51pub fn namespaced_structure_id(component_id: &str, local_id: &str) -> String {
52 format!("{component_id}{MODULE_INSTANCE_SEPARATOR}{local_id}")
53}
54
55impl StructuralTarget {
56 #[must_use]
57 pub fn namespaced(&self, component_id: &str) -> Self {
58 match self {
59 Self::Joint { id } => Self::Joint {
60 id: namespaced_structure_id(component_id, id),
61 },
62 Self::Link { id } => Self::Link {
63 id: namespaced_structure_id(component_id, id),
64 },
65 }
66 }
67}
68
69#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
70#[serde(rename_all = "snake_case")]
71pub enum LidarOutput {
72 Ranges,
73 Points,
74}
75
76#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
77#[serde(rename_all = "snake_case")]
78pub enum CameraMode {
79 Mono,
80 Rgb,
81}
82
83#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, Default, PartialEq, Eq)]
84#[serde(rename_all = "snake_case")]
85pub enum GnssCoordinateSystem {
86 #[default]
87 Local,
88 Wgs84,
89}
90
91impl Capability {
92 #[must_use]
93 pub const fn kind_name(&self) -> &'static str {
94 match self {
95 Self::Motor(_) => "motor",
96 Self::Encoder(_) => "encoder",
97 Self::Accelerometer(_) => "accelerometer",
98 Self::Gyroscope(_) => "gyroscope",
99 Self::Magnetometer(_) => "magnetometer",
100 Self::Imu(_) => "imu",
101 Self::Gnss(_) => "gnss",
102 Self::Camera(_) => "camera",
103 Self::Depth(_) => "depth",
104 Self::EmergencyStop(_) => "emergency_stop",
105 Self::Range(_) => "range",
106 Self::Lidar(_) => "lidar",
107 Self::Mmwave(_) => "mmwave",
108 Self::Microphone(_) => "microphone",
109 Self::Speaker(_) => "speaker",
110 Self::Battery(_) => "battery",
111 Self::Led(_) => "led",
112 }
113 }
114
115 #[must_use]
116 pub const fn target(&self) -> &StructuralTarget {
117 match self {
118 Self::Motor(value) => &value.target,
119 Self::Encoder(value) => &value.target,
120 Self::Accelerometer(value) => &value.target,
121 Self::Gyroscope(value) => &value.target,
122 Self::Magnetometer(value) => &value.target,
123 Self::Imu(value) => &value.target,
124 Self::Gnss(value) => &value.target,
125 Self::Camera(value) => &value.target,
126 Self::Depth(value) => &value.target,
127 Self::EmergencyStop(value) => &value.target,
128 Self::Range(value) => &value.target,
129 Self::Lidar(value) => &value.target,
130 Self::Mmwave(value) => &value.target,
131 Self::Microphone(value) => &value.target,
132 Self::Speaker(value) => &value.target,
133 Self::Battery(value) => &value.target,
134 Self::Led(value) => &value.target,
135 }
136 }
137}
138
139#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
140#[serde(deny_unknown_fields)]
141pub struct Motor {
142 pub target: StructuralTarget,
143 pub command: MotorCommand,
144 pub gear_ratio: f64,
145 pub max_torque_nm: Option<f64>,
146 pub max_velocity_radps: Option<f64>,
147}
148
149#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
150#[serde(deny_unknown_fields)]
151pub struct Encoder {
152 pub target: StructuralTarget,
153 pub publish_rate_hz: f64,
154 pub gear_ratio: f64,
155 pub encoder_type: EncoderType,
156 pub counts_per_revolution: u32,
157}
158
159#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
160#[serde(deny_unknown_fields)]
161pub struct Accelerometer {
162 pub target: StructuralTarget,
163 pub publish_rate_hz: f64,
164 pub axes: Option<[bool; 3]>,
165}
166
167#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
168#[serde(deny_unknown_fields)]
169pub struct Gyroscope {
170 pub target: StructuralTarget,
171 pub publish_rate_hz: f64,
172 pub axes: Option<[bool; 3]>,
173}
174
175#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
176#[serde(deny_unknown_fields)]
177pub struct Magnetometer {
178 pub target: StructuralTarget,
179 pub publish_rate_hz: f64,
180 pub axes: Option<[bool; 3]>,
181}
182
183#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
184#[serde(deny_unknown_fields)]
185pub struct Imu {
186 pub target: StructuralTarget,
187 pub publish_rate_hz: f64,
188 pub axes: Option<[bool; 3]>,
189}
190
191#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
192#[serde(deny_unknown_fields)]
193pub struct Gnss {
194 pub target: StructuralTarget,
195 pub publish_rate_hz: f64,
196 pub coordinate_system: GnssCoordinateSystem,
197}
198
199#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
200#[serde(deny_unknown_fields)]
201pub struct Camera {
202 pub target: StructuralTarget,
203 pub mode: CameraMode,
204 pub publish_rate_hz: f64,
205 pub width_px: u32,
206 pub height_px: u32,
207 pub field_of_view_rad: Option<f64>,
208}
209
210#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
211#[serde(deny_unknown_fields)]
212pub struct Depth {
213 pub target: StructuralTarget,
214 pub publish_rate_hz: f64,
215 pub width_px: u32,
216 pub height_px: u32,
217 pub field_of_view_rad: Option<f64>,
218 pub min_range_m: Option<f64>,
219 pub max_range_m: Option<f64>,
220}
221
222#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
223#[serde(deny_unknown_fields)]
224pub struct Range {
225 pub target: StructuralTarget,
226 pub publish_rate_hz: f64,
227 pub min_range_m: f64,
228 pub max_range_m: f64,
229 pub field_of_view_rad: f64,
230}
231
232#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
233#[serde(deny_unknown_fields)]
234pub struct EmergencyStop {
235 pub target: StructuralTarget,
236}
237
238#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
239#[serde(deny_unknown_fields)]
240pub struct Lidar {
241 pub target: StructuralTarget,
242 pub publish_rate_hz: f64,
243 pub output: LidarOutput,
244 pub min_range_m: Option<f64>,
245 pub max_range_m: Option<f64>,
246 pub horizontal_fov_rad: Option<f64>,
247 pub horizontal_resolution_rad: Option<f64>,
248 pub vertical_fov_rad: Option<f64>,
249 pub vertical_resolution_rad: Option<f64>,
250}
251
252#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
253#[serde(deny_unknown_fields)]
254pub struct Mmwave {
255 pub target: StructuralTarget,
256 pub publish_rate_hz: f64,
257}
258
259#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
260#[serde(deny_unknown_fields)]
261pub struct Microphone {
262 pub target: StructuralTarget,
263 pub publish_rate_hz: f64,
264}
265
266#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
267#[serde(deny_unknown_fields)]
268pub struct Speaker {
269 pub target: StructuralTarget,
270}
271
272#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
273#[serde(deny_unknown_fields)]
274pub struct Battery {
275 pub target: StructuralTarget,
276 pub publish_rate_hz: f64,
277 pub voltage_v: f64,
278 pub capacity_ah: f64,
279}
280
281#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
282#[serde(deny_unknown_fields)]
283pub struct Led {
284 pub target: StructuralTarget,
285}