dis_rs/common/underwater_acoustic/
model.rs1use crate::common::{BodyInfo, Interaction};
2use crate::constants::{EIGHT_OCTETS, FOUR_OCTETS, ONE_OCTET, TWENTY_OCTETS};
3use crate::enumerations::{
4 APAStatus, PduType, UAAcousticEmitterSystemFunction, UAAcousticSystemName,
5 UAActiveEmissionParameterIndex, UAAdditionalPassiveActivityParameterIndex,
6 UAPassiveParameterIndex, UAPropulsionPlantConfiguration, UAScanPattern,
7 UAStateChangeUpdateIndicator,
8};
9use crate::model::{EntityId, EventId, PduBody, VectorF32};
10use crate::underwater_acoustic::builder::UnderwaterAcousticBuilder;
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14const BASE_UA_BODY_LENGTH: u16 = 20;
15
16#[derive(Clone, Debug, Default, PartialEq)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21pub struct UnderwaterAcoustic {
22 pub emitting_entity_id: EntityId,
23 pub event_id: EventId,
24 pub state_change_update_indicator: UAStateChangeUpdateIndicator,
25 pub passive_parameter_index: UAPassiveParameterIndex,
26 pub propulsion_plant_configuration: PropulsionPlantConfiguration,
27 pub shafts: Vec<Shaft>,
28 pub apas: Vec<APA>,
29 pub emitter_systems: Vec<UAEmitterSystem>,
30}
31
32impl UnderwaterAcoustic {
33 #[must_use]
34 pub fn builder() -> UnderwaterAcousticBuilder {
35 UnderwaterAcousticBuilder::new()
36 }
37
38 #[must_use]
39 pub fn into_builder(self) -> UnderwaterAcousticBuilder {
40 UnderwaterAcousticBuilder::new_from_body(self)
41 }
42
43 #[must_use]
44 pub fn into_pdu_body(self) -> PduBody {
45 PduBody::UnderwaterAcoustic(self)
46 }
47}
48
49impl BodyInfo for UnderwaterAcoustic {
50 fn body_length(&self) -> u16 {
51 BASE_UA_BODY_LENGTH
52 + self.shafts.iter().map(Shaft::record_length).sum::<u16>()
53 + self.apas.iter().map(APA::record_length).sum::<u16>()
54 + self
55 .emitter_systems
56 .iter()
57 .map(UAEmitterSystem::record_length)
58 .sum::<u16>()
59 }
60
61 fn body_type(&self) -> PduType {
62 PduType::UnderwaterAcoustic
63 }
64}
65
66impl Interaction for UnderwaterAcoustic {
67 fn originator(&self) -> Option<&EntityId> {
68 Some(&self.emitting_entity_id)
69 }
70
71 fn receiver(&self) -> Option<&EntityId> {
72 None
73 }
74}
75
76#[derive(Clone, Debug, Default, PartialEq)]
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
79pub struct PropulsionPlantConfiguration {
80 pub configuration: UAPropulsionPlantConfiguration,
81 pub hull_mounted_masker: bool,
82}
83
84impl PropulsionPlantConfiguration {
85 #[must_use]
86 pub fn with_configuration(mut self, configuration: UAPropulsionPlantConfiguration) -> Self {
87 self.configuration = configuration;
88 self
89 }
90
91 #[must_use]
92 pub fn with_hull_mounted_masker(mut self, masker_on: bool) -> Self {
93 self.hull_mounted_masker = masker_on;
94 self
95 }
96
97 #[must_use]
98 pub fn record_length(&self) -> u16 {
99 ONE_OCTET as u16
100 }
101}
102
103#[derive(Clone, Debug, Default, PartialEq)]
107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
108pub struct Shaft {
109 pub current_rpm: i16,
110 pub ordered_rpm: i16,
111 pub rpm_rate_of_change: i32,
112}
113
114impl Shaft {
115 #[must_use]
116 pub fn with_current_rpm(mut self, rpm: i16) -> Self {
117 self.current_rpm = rpm;
118 self
119 }
120
121 #[must_use]
122 pub fn with_ordered_rpm(mut self, rpm: i16) -> Self {
123 self.ordered_rpm = rpm;
124 self
125 }
126
127 #[must_use]
128 pub fn with_rpm_rate_of_change(mut self, rate_of_change: i32) -> Self {
129 self.rpm_rate_of_change = rate_of_change;
130 self
131 }
132
133 #[must_use]
134 pub fn record_length(&self) -> u16 {
135 EIGHT_OCTETS as u16
136 }
137}
138
139#[derive(Clone, Debug, Default, PartialEq)]
143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
144pub struct APA {
145 pub parameter: UAAdditionalPassiveActivityParameterIndex,
146 pub status: APAStatus,
147 pub value: i16,
148}
149
150impl APA {
151 #[must_use]
152 pub fn with_parameter(mut self, parameter: UAAdditionalPassiveActivityParameterIndex) -> Self {
153 self.parameter = parameter;
154 self
155 }
156
157 #[must_use]
158 pub fn with_status(mut self, status: APAStatus) -> Self {
159 self.status = status;
160 self
161 }
162 #[must_use]
163 pub fn with_value(mut self, value: i16) -> Self {
164 self.value = value;
165 self
166 }
167
168 #[must_use]
169 pub fn record_length(&self) -> u16 {
170 FOUR_OCTETS as u16
171 }
172}
173
174#[derive(Clone, Debug, Default, PartialEq)]
176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
177pub struct UAEmitterSystem {
178 pub acoustic_emitter_system: AcousticEmitterSystem,
179 pub location: VectorF32,
180 pub beams: Vec<UABeam>,
181}
182
183impl UAEmitterSystem {
184 #[must_use]
185 pub fn with_acoustic_emitter_system(
186 mut self,
187 acoustic_emitter_system: AcousticEmitterSystem,
188 ) -> Self {
189 self.acoustic_emitter_system = acoustic_emitter_system;
190 self
191 }
192
193 #[must_use]
194 pub fn with_location(mut self, location: VectorF32) -> Self {
195 self.location = location;
196 self
197 }
198
199 #[must_use]
200 pub fn with_beam(mut self, beam: UABeam) -> Self {
201 self.beams.push(beam);
202 self
203 }
204
205 #[must_use]
206 pub fn with_beams(mut self, beams: Vec<UABeam>) -> Self {
207 self.beams = beams;
208 self
209 }
210
211 #[must_use]
212 pub fn record_length(&self) -> u16 {
213 TWENTY_OCTETS as u16 + self.beams.iter().map(UABeam::record_length).sum::<u16>()
214 }
215}
216
217#[derive(Clone, Debug, Default, PartialEq)]
219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
220pub struct AcousticEmitterSystem {
221 pub acoustic_system_name: UAAcousticSystemName,
222 pub function: UAAcousticEmitterSystemFunction,
223 pub acoustic_id_number: u8,
224}
225
226impl AcousticEmitterSystem {
227 #[must_use]
228 pub fn with_acoustic_system_name(mut self, acoustic_system_name: UAAcousticSystemName) -> Self {
229 self.acoustic_system_name = acoustic_system_name;
230 self
231 }
232
233 #[must_use]
234 pub fn with_function(mut self, function: UAAcousticEmitterSystemFunction) -> Self {
235 self.function = function;
236 self
237 }
238
239 #[must_use]
240 pub fn with_acoustic_id_number(mut self, acoustic_id_number: u8) -> Self {
241 self.acoustic_id_number = acoustic_id_number;
242 self
243 }
244
245 #[must_use]
246 pub fn record_length(&self) -> u16 {
247 FOUR_OCTETS as u16
248 }
249}
250
251#[derive(Clone, Debug, Default, PartialEq)]
255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
256pub struct UABeam {
257 pub beam_data_length: u8,
258 pub beam_id_number: u8,
259 pub fundamental_parameters: UAFundamentalParameterData,
260}
261
262impl UABeam {
263 #[must_use]
264 pub fn with_beam_data_length(mut self, beam_data_length: u8) -> Self {
265 self.beam_data_length = beam_data_length;
266 self
267 }
268
269 #[must_use]
270 pub fn with_beam_id_number(mut self, beam_id_number: u8) -> Self {
271 self.beam_id_number = beam_id_number;
272 self
273 }
274
275 #[must_use]
276 pub fn with_fundamental_parameters(
277 mut self,
278 fundamental_parameters: UAFundamentalParameterData,
279 ) -> Self {
280 self.fundamental_parameters = fundamental_parameters;
281 self
282 }
283
284 #[must_use]
285 pub fn record_length(&self) -> u16 {
286 FOUR_OCTETS as u16 + self.fundamental_parameters.record_length()
287 }
288}
289
290#[derive(Clone, Debug, Default, PartialEq)]
292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293pub struct UAFundamentalParameterData {
294 pub active_emission_parameter_index: UAActiveEmissionParameterIndex,
295 pub scan_pattern: UAScanPattern,
296 pub beam_center_azimuth: f32,
297 pub azimuthal_beamwidth: f32,
298 pub beam_center_depression_elevation: f32,
299 pub depression_elevation_beamwidth: f32,
300}
301
302impl UAFundamentalParameterData {
303 #[must_use]
304 pub fn with_active_emission_parameter_index(
305 mut self,
306 active_emission_parameter_index: UAActiveEmissionParameterIndex,
307 ) -> Self {
308 self.active_emission_parameter_index = active_emission_parameter_index;
309 self
310 }
311
312 #[must_use]
313 pub fn with_scan_pattern(mut self, scan_pattern: UAScanPattern) -> Self {
314 self.scan_pattern = scan_pattern;
315 self
316 }
317
318 #[must_use]
319 pub fn with_beam_center_azimuth(mut self, beam_center_azimuth: f32) -> Self {
320 self.beam_center_azimuth = beam_center_azimuth;
321 self
322 }
323
324 #[must_use]
325 pub fn with_azimuthal_beamwidth(mut self, azimuthal_beamwidth: f32) -> Self {
326 self.azimuthal_beamwidth = azimuthal_beamwidth;
327 self
328 }
329
330 #[must_use]
331 pub fn with_beam_center_depression_elevation(
332 mut self,
333 beam_center_depression_elevation: f32,
334 ) -> Self {
335 self.beam_center_depression_elevation = beam_center_depression_elevation;
336 self
337 }
338
339 #[must_use]
340 pub fn with_depression_elevation_beamwidth(
341 mut self,
342 depression_elevation_beamwidth: f32,
343 ) -> Self {
344 self.depression_elevation_beamwidth = depression_elevation_beamwidth;
345 self
346 }
347 #[must_use]
348 pub fn record_length(&self) -> u16 {
349 TWENTY_OCTETS as u16
350 }
351}