FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
xml_serializer_utils.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2026-present FERS Contributors (see AUTHORS.md).
4//
5// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
6
8
9#include <cmath>
10
12#include "core/world.h"
13#include "math/coord.h"
14#include "math/path.h"
15#include "math/rotation_path.h"
16#include "radar/platform.h"
17#include "radar/receiver.h"
18#include "radar/target.h"
19#include "radar/transmitter.h"
21#include "signal/radar_signal.h"
23#include "timing/timing.h"
24
26{
27 void addChildWithText(const XmlElement& parent, const std::string& name, const std::string& text)
28 {
29 parent.addChild(name).setText(text);
30 }
31
32 void setAttributeFromBool(const XmlElement& element, const std::string& name, const bool value)
33 {
34 element.setAttribute(name, value ? "true" : "false");
35 }
36
37 void serializeSchedule(const std::vector<radar::SchedulePeriod>& schedule, const XmlElement& parent)
38 {
39 if (schedule.empty())
40 {
41 return;
42 }
43 const XmlElement sched_elem = parent.addChild("schedule");
44 for (const auto& period : schedule)
45 {
46 XmlElement const p_elem = sched_elem.addChild("period");
47 p_elem.setAttribute("start", std::to_string(period.start));
48 p_elem.setAttribute("end", std::to_string(period.end));
49 }
50 }
51
53 {
54 addChildWithNumber(parent, "starttime", p.start);
55 addChildWithNumber(parent, "endtime", p.end);
56 addChildWithNumber(parent, "rate", p.rate);
57
59 {
61 }
62 if (p.sim_sampling_rate != 1000.0)
63 {
64 addChildWithNumber(parent, "simSamplingRate", p.sim_sampling_rate);
65 }
66 if (p.random_seed)
67 {
68 addChildWithNumber(parent, "randomseed", *p.random_seed);
69 }
70 if (p.adc_bits != 0)
71 {
72 addChildWithNumber(parent, "adc_bits", p.adc_bits);
73 }
74 if (p.oversample_ratio != 1)
75 {
76 addChildWithNumber(parent, "oversample", p.oversample_ratio);
77 }
78 if (p.rotation_angle_unit != params::RotationAngleUnit::Degrees)
79 {
80 addChildWithText(parent, "rotationangleunit",
81 std::string(params::rotationAngleUnitToken(p.rotation_angle_unit)));
82 }
83
84 const XmlElement origin = parent.addChild("origin");
85 origin.setAttribute("latitude", std::to_string(p.origin_latitude));
86 origin.setAttribute("longitude", std::to_string(p.origin_longitude));
87 origin.setAttribute("altitude", std::to_string(p.origin_altitude));
88
89 const XmlElement cs = parent.addChild("coordinatesystem");
90 switch (p.coordinate_frame)
91 {
93 cs.setAttribute("frame", "ENU");
94 break;
96 cs.setAttribute("frame", "UTM");
97 cs.setAttribute("zone", std::to_string(p.utm_zone));
98 cs.setAttribute("hemisphere", p.utm_north_hemisphere ? "N" : "S");
99 break;
101 cs.setAttribute("frame", "ECEF");
102 break;
103 }
104 }
105
107 {
108 parent.setAttribute("name", waveform.getName());
109
110 addChildWithNumber(parent, "power", waveform.getPower());
111 addChildWithNumber(parent, "carrier_frequency", waveform.getCarrier());
112
113 if (dynamic_cast<const fers_signal::CwSignal*>(waveform.getSignal()) != nullptr)
114 {
115 (void)parent.addChild("cw"); // Empty element
116 }
117 else if (const auto* fmcw = waveform.getFmcwChirpSignal(); fmcw != nullptr)
118 {
119 const XmlElement fmcw_elem = parent.addChild("fmcw_linear_chirp");
120 fmcw_elem.setAttribute("direction",
121 std::string(fers_signal::fmcwChirpDirectionToken(fmcw->getDirection())));
122 addChildWithNumber(fmcw_elem, "chirp_bandwidth", fmcw->getChirpBandwidth());
123 addChildWithNumber(fmcw_elem, "chirp_duration", fmcw->getChirpDuration());
124 addChildWithNumber(fmcw_elem, "chirp_period", fmcw->getChirpPeriod());
125 if (std::abs(fmcw->getStartFrequencyOffset()) > EPSILON)
126 {
127 addChildWithNumber(fmcw_elem, "start_frequency_offset", fmcw->getStartFrequencyOffset());
128 }
129 if (fmcw->getChirpCount().has_value())
130 {
131 addChildWithNumber(fmcw_elem, "chirp_count", static_cast<RealType>(*fmcw->getChirpCount()));
132 }
133 }
134 else if (const auto* sfcw = waveform.getSteppedFrequencySignal(); sfcw != nullptr)
135 {
136 const XmlElement sfcw_elem = parent.addChild("stepped_frequency");
137 addChildWithNumber(sfcw_elem, "start_frequency_offset", sfcw->getStartFrequencyOffset());
138 addChildWithNumber(sfcw_elem, "step_size", sfcw->getStepSize());
139 addChildWithNumber(sfcw_elem, "step_count", static_cast<RealType>(sfcw->getStepCount()));
140 addChildWithNumber(sfcw_elem, "dwell_time", sfcw->getDwellTime());
141 addChildWithNumber(sfcw_elem, "step_period", sfcw->getStepPeriod());
142 if (sfcw->getSweepCount().has_value())
143 {
144 addChildWithNumber(sfcw_elem, "sweep_count", static_cast<RealType>(*sfcw->getSweepCount()));
145 }
146 }
147 else if (const auto* triangle = waveform.getFmcwTriangleSignal(); triangle != nullptr)
148 {
149 const XmlElement fmcw_elem = parent.addChild("fmcw_triangle");
150 addChildWithNumber(fmcw_elem, "chirp_bandwidth", triangle->getChirpBandwidth());
151 addChildWithNumber(fmcw_elem, "chirp_duration", triangle->getChirpDuration());
152 if (std::abs(triangle->getStartFrequencyOffset()) > EPSILON)
153 {
154 addChildWithNumber(fmcw_elem, "start_frequency_offset", triangle->getStartFrequencyOffset());
155 }
156 if (triangle->getTriangleCount().has_value())
157 {
158 addChildWithNumber(fmcw_elem, "triangle_count", static_cast<RealType>(*triangle->getTriangleCount()));
159 }
160 }
161 else
162 {
163 const XmlElement pulsed_file = parent.addChild("pulsed_from_file");
164 const auto& filename = waveform.getFilename();
165 pulsed_file.setAttribute("filename", filename.value_or(""));
166 }
167 }
168
170 {
171 parent.setAttribute("name", timing.getName());
172 setAttributeFromBool(parent, "synconpulse", timing.getSyncOnPulse());
173
174 addChildWithNumber(parent, "frequency", timing.getFrequency());
175 if (const auto val = timing.getFreqOffset())
176 {
177 addChildWithNumber(parent, "freq_offset", *val);
178 }
179 if (const auto val = timing.getRandomFreqOffsetStdev())
180 {
181 addChildWithNumber(parent, "random_freq_offset_stdev", *val);
182 }
183 if (const auto val = timing.getPhaseOffset())
184 {
185 addChildWithNumber(parent, "phase_offset", *val);
186 }
187 if (const auto val = timing.getRandomPhaseOffsetStdev())
188 {
189 addChildWithNumber(parent, "random_phase_offset_stdev", *val);
190 }
191
192 std::vector<RealType> alphas, weights;
193 timing.copyAlphas(alphas, weights);
194 for (size_t i = 0; i < alphas.size(); ++i)
195 {
196 XmlElement const entry = parent.addChild("noise_entry");
197 addChildWithNumber(entry, "alpha", alphas[i]);
198 addChildWithNumber(entry, "weight", weights[i]);
199 }
200 }
201
203 {
204 parent.setAttribute("name", antenna.getName());
205
206 if (const auto* sinc = dynamic_cast<const antenna::Sinc*>(&antenna))
207 {
208 parent.setAttribute("pattern", "sinc");
209 addChildWithNumber(parent, "alpha", sinc->getAlpha());
210 addChildWithNumber(parent, "beta", sinc->getBeta());
211 addChildWithNumber(parent, "gamma", sinc->getGamma());
212 }
213 else if (const auto* gaussian = dynamic_cast<const antenna::Gaussian*>(&antenna))
214 {
215 parent.setAttribute("pattern", "gaussian");
216 addChildWithNumber(parent, "azscale", gaussian->getAzimuthScale());
217 addChildWithNumber(parent, "elscale", gaussian->getElevationScale());
218 }
219 else if (const auto* sh = dynamic_cast<const antenna::SquareHorn*>(&antenna))
220 {
221 parent.setAttribute("pattern", "squarehorn");
222 addChildWithNumber(parent, "diameter", sh->getDimension());
223 }
224 else if (const auto* parabolic = dynamic_cast<const antenna::Parabolic*>(&antenna))
225 {
226 parent.setAttribute("pattern", "parabolic");
227 addChildWithNumber(parent, "diameter", parabolic->getDiameter());
228 }
229 else if (const auto* xml_ant = dynamic_cast<const antenna::XmlAntenna*>(&antenna))
230 {
231 parent.setAttribute("pattern", "xml");
232 parent.setAttribute("filename", xml_ant->getFilename());
233 }
234 else if (const auto* h5_ant = dynamic_cast<const antenna::H5Antenna*>(&antenna))
235 {
236 parent.setAttribute("pattern", "file");
237 parent.setAttribute("filename", h5_ant->getFilename());
238 }
239 else
240 {
241 parent.setAttribute("pattern", "isotropic");
242 }
243
244 if (antenna.getEfficiencyFactor() != 1.0)
245 {
246 addChildWithNumber(parent, "efficiency", antenna.getEfficiencyFactor());
247 }
248 }
249
251 {
252 switch (path.getType())
253 {
255 parent.setAttribute("interpolation", "static");
256 break;
258 parent.setAttribute("interpolation", "linear");
259 break;
261 parent.setAttribute("interpolation", "cubic");
262 break;
263 }
264
265 for (const auto& [pos, t] : path.getCoords())
266 {
267 XmlElement const wp_elem = parent.addChild("positionwaypoint");
268 addChildWithNumber(wp_elem, "x", pos.x);
269 addChildWithNumber(wp_elem, "y", pos.y);
270 addChildWithNumber(wp_elem, "altitude", pos.z);
271 addChildWithNumber(wp_elem, "time", t);
272 }
273 }
274
276 {
278 {
279 const XmlElement fixed_elem = parent.addChild("fixedrotation");
280 const auto start = rotPath.getStart();
281 const auto rate = rotPath.getRate();
282 const auto unit = params::rotationAngleUnit();
283
286 {
287 start_az = std::fmod(start_az + 360.0, 360.0);
288 }
292
293 addChildWithNumber(fixed_elem, "startazimuth", start_az);
294 addChildWithNumber(fixed_elem, "startelevation", start_el);
295 addChildWithNumber(fixed_elem, "azimuthrate", rate_az);
296 addChildWithNumber(fixed_elem, "elevationrate", rate_el);
297 }
298 else
299 {
300 const XmlElement rot_elem = parent.addChild("rotationpath");
301 switch (rotPath.getType())
302 {
304 rot_elem.setAttribute("interpolation", "static");
305 break;
307 rot_elem.setAttribute("interpolation", "linear");
308 break;
310 rot_elem.setAttribute("interpolation", "cubic");
311 break;
312 default:
313 break;
314 }
315 const auto unit = params::rotationAngleUnit();
316 for (const auto& wp : rotPath.getCoords())
317 {
318 XmlElement const wp_elem = rot_elem.addChild("rotationwaypoint");
321 {
322 azimuth = std::fmod(azimuth + 360.0, 360.0);
323 }
324 const RealType elevation = rotation_angle_utils::internal_elevation_to_external(wp.elevation, unit);
325 addChildWithNumber(wp_elem, "azimuth", azimuth);
326 addChildWithNumber(wp_elem, "elevation", elevation);
327 addChildWithNumber(wp_elem, "time", wp.t);
328 }
329 }
330 }
331
333 {
334 const XmlElement tx_elem = parent.addChild("transmitter");
335 tx_elem.setAttribute("name", tx.getName());
336 tx_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
337 tx_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
338 tx_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
339
340 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
341 {
342 const XmlElement mode_elem = tx_elem.addChild("pulsed_mode");
343 addChildWithNumber(mode_elem, "prf", tx.getPrf());
344 }
345 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
346 {
347 (void)tx_elem.addChild("fmcw_mode");
348 }
349 else if (tx.getMode() == radar::OperationMode::SFCW_MODE)
350 {
351 (void)tx_elem.addChild("sfcw_mode");
352 }
353 else
354 {
355 (void)tx_elem.addChild("cw_mode");
356 }
357
358 serializeSchedule(tx.getSchedule(), tx_elem);
359 }
360
362 {
363 if (!rx.isDechirpEnabled())
364 {
365 return;
366 }
367
368 const auto& reference = rx.getDechirpReference();
369 mode_elem.setAttribute("dechirp_mode", radar::dechirpModeToken(rx.getDechirpMode()));
370 const XmlElement ref_elem = mode_elem.addChild("dechirp_reference");
371 ref_elem.setAttribute("source", radar::dechirpReferenceSourceToken(reference.source));
373 {
374 ref_elem.setAttribute("transmitter_name",
375 !reference.transmitter_name.empty() ? reference.transmitter_name : reference.name);
376 }
378 {
379 ref_elem.setAttribute("waveform_name",
380 !reference.waveform_name.empty() ? reference.waveform_name : reference.name);
381 }
382 const auto& if_chain = rx.getFmcwIfChainRequest();
383 if (if_chain.sample_rate_hz.has_value())
384 {
385 addChildWithNumber(mode_elem, "if_sample_rate", *if_chain.sample_rate_hz);
386 }
387 if (if_chain.filter_bandwidth_hz.has_value())
388 {
389 addChildWithNumber(mode_elem, "if_filter_bandwidth", *if_chain.filter_bandwidth_hz);
390 }
391 if (if_chain.filter_transition_width_hz.has_value())
392 {
393 addChildWithNumber(mode_elem, "if_filter_transition_width", *if_chain.filter_transition_width_hz);
394 }
395 }
396
398 {
399 const XmlElement rx_elem = parent.addChild("receiver");
400 rx_elem.setAttribute("name", rx.getName());
401 rx_elem.setAttribute("antenna", (rx.getAntenna() != nullptr) ? rx.getAntenna()->getName() : "");
402 rx_elem.setAttribute("timing", rx.getTiming() ? rx.getTiming()->getName() : "");
405
406 if (rx.getMode() == radar::OperationMode::PULSED_MODE)
407 {
408 const XmlElement mode_elem = rx_elem.addChild("pulsed_mode");
409 addChildWithNumber(mode_elem, "prf", rx.getWindowPrf());
410 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
411 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
412 }
413 else if (rx.getMode() == radar::OperationMode::FMCW_MODE)
414 {
415 serializeReceiverFmcwMode(rx, rx_elem.addChild("fmcw_mode"));
416 }
417 else if (rx.getMode() == radar::OperationMode::SFCW_MODE)
418 {
419 (void)rx_elem.addChild("sfcw_mode");
420 }
421 else
422 {
423 (void)rx_elem.addChild("cw_mode");
424 }
425
426 if (rx.getNoiseTemperature() > 0)
427 {
428 addChildWithNumber(rx_elem, "noise_temp", rx.getNoiseTemperature());
429 }
430
431 serializeSchedule(rx.getSchedule(), rx_elem);
432 }
433
435 {
436 const XmlElement mono_elem = parent.addChild("monostatic");
437 mono_elem.setAttribute("name", tx.getName());
438 mono_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
439 mono_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
440 mono_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
443
444 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
445 {
446 const XmlElement mode_elem = mono_elem.addChild("pulsed_mode");
447 addChildWithNumber(mode_elem, "prf", tx.getPrf());
448 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
449 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
450 }
451 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
452 {
453 serializeReceiverFmcwMode(rx, mono_elem.addChild("fmcw_mode"));
454 }
455 else if (tx.getMode() == radar::OperationMode::SFCW_MODE)
456 {
457 (void)mono_elem.addChild("sfcw_mode");
458 }
459 else
460 {
461 (void)mono_elem.addChild("cw_mode");
462 }
463
464 if (rx.getNoiseTemperature() > 0)
465 {
466 addChildWithNumber(mono_elem, "noise_temp", rx.getNoiseTemperature());
467 }
468
469 serializeSchedule(tx.getSchedule(), mono_elem);
470 }
471
473 {
474 const XmlElement target_elem = parent.addChild("target");
475 target_elem.setAttribute("name", target.getName());
476
477 const XmlElement rcs_elem = target_elem.addChild("rcs");
478 if (const auto* iso = dynamic_cast<const radar::IsoTarget*>(&target))
479 {
480 rcs_elem.setAttribute("type", "isotropic");
481 addChildWithNumber(rcs_elem, "value", iso->getConstRcs());
482 }
483 else if (const auto* file_target = dynamic_cast<const radar::FileTarget*>(&target))
484 {
485 rcs_elem.setAttribute("type", "file");
486 rcs_elem.setAttribute("filename", file_target->getFilename());
487 }
488
489 // Serialize fluctuation model if present
490 if (const auto* model = target.getFluctuationModel())
491 {
492 if (const auto* chi = dynamic_cast<const radar::RcsChiSquare*>(model))
493 {
494 XmlElement const model_elem = target_elem.addChild("model");
495 model_elem.setAttribute("type", "chisquare");
496 addChildWithNumber(model_elem, "k", chi->getK());
497 }
498 }
499 }
500
502 {
503 parent.setAttribute("name", platform.getName());
504
505 const XmlElement motion_elem = parent.addChild("motionpath");
506 serializeMotionPath(*platform.getMotionPath(), motion_elem);
507
508 serializeRotation(*platform.getRotationPath(), parent);
509
510 for (const auto& tx : world.getTransmitters())
511 {
512 if (tx->getPlatform() == &platform)
513 {
514 if (tx->getAttached() != nullptr)
515 {
516 serializeMonostatic(*tx, *dynamic_cast<const radar::Receiver*>(tx->getAttached()), parent);
517 }
518 else
519 {
521 }
522 }
523 }
524
525 for (const auto& rx : world.getReceivers())
526 {
527 if (rx->getPlatform() == &platform && (rx->getAttached() == nullptr))
528 {
530 }
531 }
532
533 for (const auto& target : world.getTargets())
534 {
535 if (target->getPlatform() == &platform)
536 {
538 }
539 }
540 }
541}
Header file defining various types of antennas and their gain patterns.
Class representing a node in an XML document.
void setAttribute(const std::string_view name, const std::string_view value) const
Set an attribute on the XML element.
Abstract base class representing an antenna.
Represents a Gaussian-shaped antenna gain pattern.
Represents an antenna whose gain pattern is loaded from a HDF5 file.
Represents a parabolic reflector antenna.
Represents a sinc function-based antenna gain pattern.
Represents a square horn antenna.
Represents an antenna whose gain pattern is defined by an XML file.
The World class manages the simulator environment.
Definition world.h:39
const std::vector< std::unique_ptr< radar::Target > > & getTargets() const noexcept
Retrieves the list of radar targets.
Definition world.h:226
const std::vector< std::unique_ptr< radar::Transmitter > > & getTransmitters() const noexcept
Retrieves the list of radar transmitters.
Definition world.h:246
const std::vector< std::unique_ptr< radar::Receiver > > & getReceivers() const noexcept
Retrieves the list of radar receivers.
Definition world.h:236
Continuous-wave signal implementation.
Class representing a radar signal with associated properties.
const class SteppedFrequencySignal * getSteppedFrequencySignal() const noexcept
Gets the stepped-frequency implementation, if this signal owns one.
const std::optional< std::string > & getFilename() const noexcept
Gets the filename associated with this signal.
const class FmcwTriangleSignal * getFmcwTriangleSignal() const noexcept
Gets the FMCW triangle implementation, if this signal owns one.
const std::string & getName() const noexcept
Gets the name of the radar signal.
RealType getCarrier() const noexcept
Gets the carrier frequency of the radar signal.
const Signal * getSignal() const noexcept
Gets the underlying signal object.
const class FmcwChirpSignal * getFmcwChirpSignal() const noexcept
Gets the FMCW chirp implementation, if this signal owns one.
RealType getPower() const noexcept
Gets the power of the radar signal.
Represents a path with coordinates and allows for various interpolation methods.
Definition path.h:31
const std::vector< Coord > & getCoords() const noexcept
Gets the list of coordinates in the path.
Definition path.h:84
@ INTERP_STATIC
Hold the first coordinate for all query times.
@ INTERP_LINEAR
Linearly interpolate between neighboring coordinates.
@ INTERP_CUBIC
Cubically interpolate between neighboring coordinates.
InterpType getType() const noexcept
Retrieves the current interpolation type of the path.
Definition path.h:77
Manages rotational paths with different interpolation techniques.
@ INTERP_STATIC
Hold the first rotation for all query times.
@ INTERP_LINEAR
Linearly interpolate between neighboring rotations.
@ INTERP_CONSTANT
Hold the most recent rotation sample.
@ INTERP_CUBIC
Cubically interpolate between neighboring rotations.
RealType x
The x component of the vector.
RealType z
The z component of the vector.
RealType y
The y component of the vector.
File-based radar target.
Definition target.h:226
Isotropic radar target.
Definition target.h:188
Represents a simulation platform with motion and rotation paths.
Definition platform.h:32
Chi-square distributed RCS model.
Definition target.h:82
Manages radar signal reception and response processing.
Definition receiver.h:47
@ Transmitter
Use a named transmitter.
@ Custom
Use a named top-level waveform with the receiver schedule.
@ FLAG_NODIRECT
Disable direct-path reception.
@ FLAG_NOPROPLOSS
Disable propagation-loss scaling.
Base class for radar targets.
Definition target.h:118
Represents a radar transmitter system.
Definition transmitter.h:34
Manages timing properties such as frequency, offsets, and synchronization.
double RealType
Type for real numbers.
Definition config.h:27
constexpr RealType EPSILON
Machine epsilon for real numbers.
Definition config.h:51
Coordinate and rotation structure operations.
std::string_view fmcwChirpDirectionToken(const FmcwChirpDirection direction) noexcept
Converts a chirp direction to the schema token.
@ UTM
Universal Transverse Mercator.
@ ENU
East-North-Up local tangent plane (default)
@ ECEF
Earth-Centered, Earth-Fixed.
RotationAngleUnit rotationAngleUnit() noexcept
Gets the external rotation angle unit.
Definition parameters.h:327
@ Degrees
Compass azimuth and elevation expressed in degrees.
constexpr std::string_view rotationAngleUnitToken(const RotationAngleUnit unit) noexcept
Converts a rotation angle unit to its XML token.
Definition parameters.h:352
std::string_view dechirpReferenceSourceToken(const Receiver::DechirpReferenceSource source) noexcept
Converts a dechirp reference source to its scenario token.
Definition receiver.cpp:76
@ SFCW_MODE
The component operates in a stepped-frequency CW streaming mode.
@ PULSED_MODE
The component operates in a pulsed mode.
@ FMCW_MODE
The component operates in an FMCW streaming mode.
std::string_view dechirpModeToken(const Receiver::DechirpMode mode) noexcept
Converts a dechirp mode to its scenario token.
Definition receiver.cpp:45
RealType internal_elevation_to_external(const RealType elevation, const params::RotationAngleUnit unit) noexcept
Converts an internal elevation angle to the external unit.
RealType internal_azimuth_rate_to_external(const RealType azimuth_rate, const params::RotationAngleUnit unit) noexcept
Converts an internal azimuth rate to the external compass convention.
RealType internal_elevation_rate_to_external(const RealType elevation_rate, const params::RotationAngleUnit unit) noexcept
Converts an internal elevation rate to the external unit.
RealType internal_azimuth_to_external(const RealType azimuth, const params::RotationAngleUnit unit) noexcept
Converts an internal azimuth angle to the external compass convention.
void serializeMotionPath(const math::Path &path, const XmlElement &parent)
Serializes a motion path into a parent XML element.
void addChildWithNumber(const XmlElement &parent, const std::string &name, T value)
Adds a child element with the specified numeric content.
void addChildWithText(const XmlElement &parent, const std::string &name, const std::string &text)
Adds a child element with the specified text content.
static void serializeReceiverFmcwMode(const radar::Receiver &rx, const XmlElement &mode_elem)
void serializeReceiver(const radar::Receiver &rx, const XmlElement &parent)
Serializes a receiver into a parent XML element.
void serializeAntenna(const antenna::Antenna &antenna, const XmlElement &parent)
Serializes an antenna into a parent XML element.
void serializeMonostatic(const radar::Transmitter &tx, const radar::Receiver &rx, const XmlElement &parent)
Serializes a monostatic radar setup containing both a transmitter and receiver.
void serializeRotation(const math::RotationPath &rotPath, const XmlElement &parent)
Serializes a rotation path into a parent XML element.
void serializeSchedule(const std::vector< radar::SchedulePeriod > &schedule, const XmlElement &parent)
Serializes a schedule (active periods) into a parent XML element.
void serializePlatform(const radar::Platform &platform, const core::World &world, const XmlElement &parent)
Serializes a platform and its attached components into a parent XML element.
void serializeTransmitter(const radar::Transmitter &tx, const XmlElement &parent)
Serializes a transmitter into a parent XML element.
void serializeTarget(const radar::Target &target, const XmlElement &parent)
Serializes a target into a parent XML element.
void serializeTiming(const timing::PrototypeTiming &timing, const XmlElement &parent)
Serializes a timing object into a parent XML element.
void serializeWaveform(const fers_signal::RadarSignal &waveform, const XmlElement &parent)
Serializes a waveform into a parent XML element.
void setAttributeFromBool(const XmlElement &element, const std::string &name, const bool value)
Sets a boolean attribute on an XML element.
void serializeParameters(const XmlElement &parent, const params::Parameters &p)
Serializes a Parameters object into a parent XML element.
Provides the definition and functionality of the Path class for handling coordinate-based paths with ...
Defines the Platform class used in radar simulation.
Header file for the PrototypeTiming class.
Classes for handling radar waveforms and signals.
Radar Receiver class for managing signal reception and response handling.
Defines the RotationPath class for handling rotational paths with different interpolation types.
math::Vec3 max
Struct to hold simulation parameters.
Definition parameters.h:52
static constexpr RealType DEFAULT_C
Speed of light (m/s)
Definition parameters.h:53
Defines classes for radar targets and their Radar Cross-Section (RCS) models.
Timing source for simulation objects.
Header file for the Transmitter class in the radar namespace.
Header file for the World class in the simulator.
Core utility layer for serializing FERS XML scenario files.