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* triangle = waveform.getFmcwTriangleSignal(); triangle != nullptr)
135 {
136 const XmlElement fmcw_elem = parent.addChild("fmcw_triangle");
137 addChildWithNumber(fmcw_elem, "chirp_bandwidth", triangle->getChirpBandwidth());
138 addChildWithNumber(fmcw_elem, "chirp_duration", triangle->getChirpDuration());
139 if (std::abs(triangle->getStartFrequencyOffset()) > EPSILON)
140 {
141 addChildWithNumber(fmcw_elem, "start_frequency_offset", triangle->getStartFrequencyOffset());
142 }
143 if (triangle->getTriangleCount().has_value())
144 {
145 addChildWithNumber(fmcw_elem, "triangle_count", static_cast<RealType>(*triangle->getTriangleCount()));
146 }
147 }
148 else
149 {
150 const XmlElement pulsed_file = parent.addChild("pulsed_from_file");
151 const auto& filename = waveform.getFilename();
152 pulsed_file.setAttribute("filename", filename.value_or(""));
153 }
154 }
155
157 {
158 parent.setAttribute("name", timing.getName());
159 setAttributeFromBool(parent, "synconpulse", timing.getSyncOnPulse());
160
161 addChildWithNumber(parent, "frequency", timing.getFrequency());
162 if (const auto val = timing.getFreqOffset())
163 {
164 addChildWithNumber(parent, "freq_offset", *val);
165 }
166 if (const auto val = timing.getRandomFreqOffsetStdev())
167 {
168 addChildWithNumber(parent, "random_freq_offset_stdev", *val);
169 }
170 if (const auto val = timing.getPhaseOffset())
171 {
172 addChildWithNumber(parent, "phase_offset", *val);
173 }
174 if (const auto val = timing.getRandomPhaseOffsetStdev())
175 {
176 addChildWithNumber(parent, "random_phase_offset_stdev", *val);
177 }
178
179 std::vector<RealType> alphas, weights;
180 timing.copyAlphas(alphas, weights);
181 for (size_t i = 0; i < alphas.size(); ++i)
182 {
183 XmlElement const entry = parent.addChild("noise_entry");
184 addChildWithNumber(entry, "alpha", alphas[i]);
185 addChildWithNumber(entry, "weight", weights[i]);
186 }
187 }
188
190 {
191 parent.setAttribute("name", antenna.getName());
192
193 if (const auto* sinc = dynamic_cast<const antenna::Sinc*>(&antenna))
194 {
195 parent.setAttribute("pattern", "sinc");
196 addChildWithNumber(parent, "alpha", sinc->getAlpha());
197 addChildWithNumber(parent, "beta", sinc->getBeta());
198 addChildWithNumber(parent, "gamma", sinc->getGamma());
199 }
200 else if (const auto* gaussian = dynamic_cast<const antenna::Gaussian*>(&antenna))
201 {
202 parent.setAttribute("pattern", "gaussian");
203 addChildWithNumber(parent, "azscale", gaussian->getAzimuthScale());
204 addChildWithNumber(parent, "elscale", gaussian->getElevationScale());
205 }
206 else if (const auto* sh = dynamic_cast<const antenna::SquareHorn*>(&antenna))
207 {
208 parent.setAttribute("pattern", "squarehorn");
209 addChildWithNumber(parent, "diameter", sh->getDimension());
210 }
211 else if (const auto* parabolic = dynamic_cast<const antenna::Parabolic*>(&antenna))
212 {
213 parent.setAttribute("pattern", "parabolic");
214 addChildWithNumber(parent, "diameter", parabolic->getDiameter());
215 }
216 else if (const auto* xml_ant = dynamic_cast<const antenna::XmlAntenna*>(&antenna))
217 {
218 parent.setAttribute("pattern", "xml");
219 parent.setAttribute("filename", xml_ant->getFilename());
220 }
221 else if (const auto* h5_ant = dynamic_cast<const antenna::H5Antenna*>(&antenna))
222 {
223 parent.setAttribute("pattern", "file");
224 parent.setAttribute("filename", h5_ant->getFilename());
225 }
226 else
227 {
228 parent.setAttribute("pattern", "isotropic");
229 }
230
231 if (antenna.getEfficiencyFactor() != 1.0)
232 {
233 addChildWithNumber(parent, "efficiency", antenna.getEfficiencyFactor());
234 }
235 }
236
238 {
239 switch (path.getType())
240 {
242 parent.setAttribute("interpolation", "static");
243 break;
245 parent.setAttribute("interpolation", "linear");
246 break;
248 parent.setAttribute("interpolation", "cubic");
249 break;
250 }
251
252 for (const auto& [pos, t] : path.getCoords())
253 {
254 XmlElement const wp_elem = parent.addChild("positionwaypoint");
255 addChildWithNumber(wp_elem, "x", pos.x);
256 addChildWithNumber(wp_elem, "y", pos.y);
257 addChildWithNumber(wp_elem, "altitude", pos.z);
258 addChildWithNumber(wp_elem, "time", t);
259 }
260 }
261
263 {
265 {
266 const XmlElement fixed_elem = parent.addChild("fixedrotation");
267 const auto start = rotPath.getStart();
268 const auto rate = rotPath.getRate();
269 const auto unit = params::rotationAngleUnit();
270
273 {
274 start_az = std::fmod(start_az + 360.0, 360.0);
275 }
279
280 addChildWithNumber(fixed_elem, "startazimuth", start_az);
281 addChildWithNumber(fixed_elem, "startelevation", start_el);
282 addChildWithNumber(fixed_elem, "azimuthrate", rate_az);
283 addChildWithNumber(fixed_elem, "elevationrate", rate_el);
284 }
285 else
286 {
287 const XmlElement rot_elem = parent.addChild("rotationpath");
288 switch (rotPath.getType())
289 {
291 rot_elem.setAttribute("interpolation", "static");
292 break;
294 rot_elem.setAttribute("interpolation", "linear");
295 break;
297 rot_elem.setAttribute("interpolation", "cubic");
298 break;
299 default:
300 break;
301 }
302 const auto unit = params::rotationAngleUnit();
303 for (const auto& wp : rotPath.getCoords())
304 {
305 XmlElement const wp_elem = rot_elem.addChild("rotationwaypoint");
308 {
309 azimuth = std::fmod(azimuth + 360.0, 360.0);
310 }
311 const RealType elevation = rotation_angle_utils::internal_elevation_to_external(wp.elevation, unit);
312 addChildWithNumber(wp_elem, "azimuth", azimuth);
313 addChildWithNumber(wp_elem, "elevation", elevation);
314 addChildWithNumber(wp_elem, "time", wp.t);
315 }
316 }
317 }
318
320 {
321 const XmlElement tx_elem = parent.addChild("transmitter");
322 tx_elem.setAttribute("name", tx.getName());
323 tx_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
324 tx_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
325 tx_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
326
327 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
328 {
329 const XmlElement mode_elem = tx_elem.addChild("pulsed_mode");
330 addChildWithNumber(mode_elem, "prf", tx.getPrf());
331 }
332 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
333 {
334 (void)tx_elem.addChild("fmcw_mode");
335 }
336 else
337 {
338 (void)tx_elem.addChild("cw_mode");
339 }
340
341 serializeSchedule(tx.getSchedule(), tx_elem);
342 }
343
345 {
346 if (!rx.isDechirpEnabled())
347 {
348 return;
349 }
350
351 const auto& reference = rx.getDechirpReference();
352 mode_elem.setAttribute("dechirp_mode", radar::dechirpModeToken(rx.getDechirpMode()));
353 const XmlElement ref_elem = mode_elem.addChild("dechirp_reference");
354 ref_elem.setAttribute("source", radar::dechirpReferenceSourceToken(reference.source));
356 {
357 ref_elem.setAttribute("transmitter_name",
358 !reference.transmitter_name.empty() ? reference.transmitter_name : reference.name);
359 }
361 {
362 ref_elem.setAttribute("waveform_name",
363 !reference.waveform_name.empty() ? reference.waveform_name : reference.name);
364 }
365 const auto& if_chain = rx.getFmcwIfChainRequest();
366 if (if_chain.sample_rate_hz.has_value())
367 {
368 addChildWithNumber(mode_elem, "if_sample_rate", *if_chain.sample_rate_hz);
369 }
370 if (if_chain.filter_bandwidth_hz.has_value())
371 {
372 addChildWithNumber(mode_elem, "if_filter_bandwidth", *if_chain.filter_bandwidth_hz);
373 }
374 if (if_chain.filter_transition_width_hz.has_value())
375 {
376 addChildWithNumber(mode_elem, "if_filter_transition_width", *if_chain.filter_transition_width_hz);
377 }
378 }
379
381 {
382 const XmlElement rx_elem = parent.addChild("receiver");
383 rx_elem.setAttribute("name", rx.getName());
384 rx_elem.setAttribute("antenna", (rx.getAntenna() != nullptr) ? rx.getAntenna()->getName() : "");
385 rx_elem.setAttribute("timing", rx.getTiming() ? rx.getTiming()->getName() : "");
388
389 if (rx.getMode() == radar::OperationMode::PULSED_MODE)
390 {
391 const XmlElement mode_elem = rx_elem.addChild("pulsed_mode");
392 addChildWithNumber(mode_elem, "prf", rx.getWindowPrf());
393 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
394 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
395 }
396 else if (rx.getMode() == radar::OperationMode::FMCW_MODE)
397 {
398 serializeReceiverFmcwMode(rx, rx_elem.addChild("fmcw_mode"));
399 }
400 else
401 {
402 (void)rx_elem.addChild("cw_mode");
403 }
404
405 if (rx.getNoiseTemperature() > 0)
406 {
407 addChildWithNumber(rx_elem, "noise_temp", rx.getNoiseTemperature());
408 }
409
410 serializeSchedule(rx.getSchedule(), rx_elem);
411 }
412
414 {
415 const XmlElement mono_elem = parent.addChild("monostatic");
416 mono_elem.setAttribute("name", tx.getName());
417 mono_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
418 mono_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
419 mono_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
422
423 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
424 {
425 const XmlElement mode_elem = mono_elem.addChild("pulsed_mode");
426 addChildWithNumber(mode_elem, "prf", tx.getPrf());
427 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
428 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
429 }
430 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
431 {
432 serializeReceiverFmcwMode(rx, mono_elem.addChild("fmcw_mode"));
433 }
434 else
435 {
436 (void)mono_elem.addChild("cw_mode");
437 }
438
439 if (rx.getNoiseTemperature() > 0)
440 {
441 addChildWithNumber(mono_elem, "noise_temp", rx.getNoiseTemperature());
442 }
443
444 serializeSchedule(tx.getSchedule(), mono_elem);
445 }
446
448 {
449 const XmlElement target_elem = parent.addChild("target");
450 target_elem.setAttribute("name", target.getName());
451
452 const XmlElement rcs_elem = target_elem.addChild("rcs");
453 if (const auto* iso = dynamic_cast<const radar::IsoTarget*>(&target))
454 {
455 rcs_elem.setAttribute("type", "isotropic");
456 addChildWithNumber(rcs_elem, "value", iso->getConstRcs());
457 }
458 else if (const auto* file_target = dynamic_cast<const radar::FileTarget*>(&target))
459 {
460 rcs_elem.setAttribute("type", "file");
461 rcs_elem.setAttribute("filename", file_target->getFilename());
462 }
463
464 // Serialize fluctuation model if present
465 if (const auto* model = target.getFluctuationModel())
466 {
467 if (const auto* chi = dynamic_cast<const radar::RcsChiSquare*>(model))
468 {
469 XmlElement const model_elem = target_elem.addChild("model");
470 model_elem.setAttribute("type", "chisquare");
471 addChildWithNumber(model_elem, "k", chi->getK());
472 }
473 }
474 }
475
477 {
478 parent.setAttribute("name", platform.getName());
479
480 const XmlElement motion_elem = parent.addChild("motionpath");
481 serializeMotionPath(*platform.getMotionPath(), motion_elem);
482
483 serializeRotation(*platform.getRotationPath(), parent);
484
485 for (const auto& tx : world.getTransmitters())
486 {
487 if (tx->getPlatform() == &platform)
488 {
489 if (tx->getAttached() != nullptr)
490 {
491 serializeMonostatic(*tx, *dynamic_cast<const radar::Receiver*>(tx->getAttached()), parent);
492 }
493 else
494 {
496 }
497 }
498 }
499
500 for (const auto& rx : world.getReceivers())
501 {
502 if (rx->getPlatform() == &platform && (rx->getAttached() == nullptr))
503 {
505 }
506 }
507
508 for (const auto& target : world.getTargets())
509 {
510 if (target->getPlatform() == &platform)
511 {
513 }
514 }
515 }
516}
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 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
@ 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.