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 (const auto* file = waveform.getFileSignal(); file != nullptr)
114 {
115 std::string_view element_name = "pulsed_from_file";
116 if (file->getKind() == fers_signal::FileWaveformKind::Cw)
117 {
118 element_name = "cw_from_file";
119 }
120 else if (file->getKind() == fers_signal::FileWaveformKind::Fmcw)
121 {
122 element_name = "fmcw_from_file";
123 }
124 const XmlElement file_element = parent.addChild(element_name);
125 file_element.setAttribute("filename", waveform.getFilename().value_or(""));
126 }
127 else if (dynamic_cast<const fers_signal::CwSignal*>(waveform.getSignal()) != nullptr)
128 {
129 (void)parent.addChild("cw"); // Empty element
130 }
131 else if (const auto* fmcw = waveform.getFmcwChirpSignal(); fmcw != nullptr)
132 {
133 const XmlElement fmcw_elem = parent.addChild("fmcw_linear_chirp");
134 fmcw_elem.setAttribute("direction",
135 std::string(fers_signal::fmcwChirpDirectionToken(fmcw->getDirection())));
136 addChildWithNumber(fmcw_elem, "chirp_bandwidth", fmcw->getChirpBandwidth());
137 addChildWithNumber(fmcw_elem, "chirp_duration", fmcw->getChirpDuration());
138 addChildWithNumber(fmcw_elem, "chirp_period", fmcw->getChirpPeriod());
139 if (std::abs(fmcw->getStartFrequencyOffset()) > EPSILON)
140 {
141 addChildWithNumber(fmcw_elem, "start_frequency_offset", fmcw->getStartFrequencyOffset());
142 }
143 if (fmcw->getChirpCount().has_value())
144 {
145 addChildWithNumber(fmcw_elem, "chirp_count", static_cast<RealType>(*fmcw->getChirpCount()));
146 }
147 }
148 else if (const auto* sfcw = waveform.getSteppedFrequencySignal(); sfcw != nullptr)
149 {
150 const XmlElement sfcw_elem = parent.addChild("stepped_frequency");
151 addChildWithNumber(sfcw_elem, "start_frequency_offset", sfcw->getStartFrequencyOffset());
152 addChildWithNumber(sfcw_elem, "step_size", sfcw->getStepSize());
153 addChildWithNumber(sfcw_elem, "step_count", static_cast<RealType>(sfcw->getStepCount()));
154 addChildWithNumber(sfcw_elem, "dwell_time", sfcw->getDwellTime());
155 addChildWithNumber(sfcw_elem, "step_period", sfcw->getStepPeriod());
156 if (sfcw->getSweepCount().has_value())
157 {
158 addChildWithNumber(sfcw_elem, "sweep_count", static_cast<RealType>(*sfcw->getSweepCount()));
159 }
160 }
161 else if (const auto* triangle = waveform.getFmcwTriangleSignal(); triangle != nullptr)
162 {
163 const XmlElement fmcw_elem = parent.addChild("fmcw_triangle");
164 addChildWithNumber(fmcw_elem, "chirp_bandwidth", triangle->getChirpBandwidth());
165 addChildWithNumber(fmcw_elem, "chirp_duration", triangle->getChirpDuration());
166 if (std::abs(triangle->getStartFrequencyOffset()) > EPSILON)
167 {
168 addChildWithNumber(fmcw_elem, "start_frequency_offset", triangle->getStartFrequencyOffset());
169 }
170 if (triangle->getTriangleCount().has_value())
171 {
172 addChildWithNumber(fmcw_elem, "triangle_count", static_cast<RealType>(*triangle->getTriangleCount()));
173 }
174 }
175 else
176 {
177 const XmlElement pulsed_file = parent.addChild("pulsed_from_file");
178 pulsed_file.setAttribute("filename", waveform.getFilename().value_or(""));
179 }
180 }
181
183 {
184 parent.setAttribute("name", timing.getName());
185 setAttributeFromBool(parent, "synconpulse", timing.getSyncOnPulse());
186
187 addChildWithNumber(parent, "frequency", timing.getFrequency());
188 if (const auto val = timing.getFreqOffset())
189 {
190 addChildWithNumber(parent, "freq_offset", *val);
191 }
192 if (const auto val = timing.getRandomFreqOffsetStdev())
193 {
194 addChildWithNumber(parent, "random_freq_offset_stdev", *val);
195 }
196 if (const auto val = timing.getPhaseOffset())
197 {
198 addChildWithNumber(parent, "phase_offset", *val);
199 }
200 if (const auto val = timing.getRandomPhaseOffsetStdev())
201 {
202 addChildWithNumber(parent, "random_phase_offset_stdev", *val);
203 }
204
205 std::vector<RealType> alphas, weights;
206 timing.copyAlphas(alphas, weights);
207 for (size_t i = 0; i < alphas.size(); ++i)
208 {
209 XmlElement const entry = parent.addChild("noise_entry");
210 addChildWithNumber(entry, "alpha", alphas[i]);
211 addChildWithNumber(entry, "weight", weights[i]);
212 }
213 }
214
216 {
217 parent.setAttribute("name", antenna.getName());
218
219 if (const auto* sinc = dynamic_cast<const antenna::Sinc*>(&antenna))
220 {
221 parent.setAttribute("pattern", "sinc");
222 addChildWithNumber(parent, "alpha", sinc->getAlpha());
223 addChildWithNumber(parent, "beta", sinc->getBeta());
224 addChildWithNumber(parent, "gamma", sinc->getGamma());
225 }
226 else if (const auto* gaussian = dynamic_cast<const antenna::Gaussian*>(&antenna))
227 {
228 parent.setAttribute("pattern", "gaussian");
229 addChildWithNumber(parent, "azscale", gaussian->getAzimuthScale());
230 addChildWithNumber(parent, "elscale", gaussian->getElevationScale());
231 }
232 else if (const auto* sh = dynamic_cast<const antenna::SquareHorn*>(&antenna))
233 {
234 parent.setAttribute("pattern", "squarehorn");
235 addChildWithNumber(parent, "diameter", sh->getDimension());
236 }
237 else if (const auto* parabolic = dynamic_cast<const antenna::Parabolic*>(&antenna))
238 {
239 parent.setAttribute("pattern", "parabolic");
240 addChildWithNumber(parent, "diameter", parabolic->getDiameter());
241 }
242 else if (const auto* xml_ant = dynamic_cast<const antenna::XmlAntenna*>(&antenna))
243 {
244 parent.setAttribute("pattern", "xml");
245 parent.setAttribute("filename", xml_ant->getFilename());
246 }
247 else if (const auto* h5_ant = dynamic_cast<const antenna::H5Antenna*>(&antenna))
248 {
249 parent.setAttribute("pattern", "file");
250 parent.setAttribute("filename", h5_ant->getFilename());
251 }
252 else
253 {
254 parent.setAttribute("pattern", "isotropic");
255 }
256
257 if (antenna.getEfficiencyFactor() != 1.0)
258 {
259 addChildWithNumber(parent, "efficiency", antenna.getEfficiencyFactor());
260 }
261 }
262
264 {
265 switch (path.getType())
266 {
268 parent.setAttribute("interpolation", "static");
269 break;
271 parent.setAttribute("interpolation", "linear");
272 break;
274 parent.setAttribute("interpolation", "cubic");
275 break;
276 }
277
278 for (const auto& [pos, t] : path.getCoords())
279 {
280 XmlElement const wp_elem = parent.addChild("positionwaypoint");
281 addChildWithNumber(wp_elem, "x", pos.x);
282 addChildWithNumber(wp_elem, "y", pos.y);
283 addChildWithNumber(wp_elem, "altitude", pos.z);
284 addChildWithNumber(wp_elem, "time", t);
285 }
286 }
287
289 {
291 {
292 const XmlElement fixed_elem = parent.addChild("fixedrotation");
293 const auto start = rotPath.getStart();
294 const auto rate = rotPath.getRate();
295 const auto unit = params::rotationAngleUnit();
296
299 {
300 start_az = std::fmod(start_az + 360.0, 360.0);
301 }
305
306 addChildWithNumber(fixed_elem, "startazimuth", start_az);
307 addChildWithNumber(fixed_elem, "startelevation", start_el);
308 addChildWithNumber(fixed_elem, "azimuthrate", rate_az);
309 addChildWithNumber(fixed_elem, "elevationrate", rate_el);
310 }
311 else
312 {
313 const XmlElement rot_elem = parent.addChild("rotationpath");
314 switch (rotPath.getType())
315 {
317 rot_elem.setAttribute("interpolation", "static");
318 break;
320 rot_elem.setAttribute("interpolation", "linear");
321 break;
323 rot_elem.setAttribute("interpolation", "cubic");
324 break;
325 default:
326 break;
327 }
328 const auto unit = params::rotationAngleUnit();
329 for (const auto& wp : rotPath.getCoords())
330 {
331 XmlElement const wp_elem = rot_elem.addChild("rotationwaypoint");
334 {
335 azimuth = std::fmod(azimuth + 360.0, 360.0);
336 }
337 const RealType elevation = rotation_angle_utils::internal_elevation_to_external(wp.elevation, unit);
338 addChildWithNumber(wp_elem, "azimuth", azimuth);
339 addChildWithNumber(wp_elem, "elevation", elevation);
340 addChildWithNumber(wp_elem, "time", wp.t);
341 }
342 }
343 }
344
346 {
347 const XmlElement tx_elem = parent.addChild("transmitter");
348 tx_elem.setAttribute("name", tx.getName());
349 tx_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
350 tx_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
351 tx_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
352
353 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
354 {
355 const XmlElement mode_elem = tx_elem.addChild("pulsed_mode");
356 addChildWithNumber(mode_elem, "prf", tx.getPrf());
357 }
358 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
359 {
360 (void)tx_elem.addChild("fmcw_mode");
361 }
362 else if (tx.getMode() == radar::OperationMode::SFCW_MODE)
363 {
364 (void)tx_elem.addChild("sfcw_mode");
365 }
366 else
367 {
368 (void)tx_elem.addChild("cw_mode");
369 }
370
371 serializeSchedule(tx.getSchedule(), tx_elem);
372 }
373
375 {
376 if (!rx.isDechirpEnabled())
377 {
378 return;
379 }
380
381 const auto& reference = rx.getDechirpReference();
382 mode_elem.setAttribute("dechirp_mode", radar::dechirpModeToken(rx.getDechirpMode()));
383 const XmlElement ref_elem = mode_elem.addChild("dechirp_reference");
384 ref_elem.setAttribute("source", radar::dechirpReferenceSourceToken(reference.source));
386 {
387 ref_elem.setAttribute("transmitter_name",
388 !reference.transmitter_name.empty() ? reference.transmitter_name : reference.name);
389 }
391 {
392 ref_elem.setAttribute("waveform_name",
393 !reference.waveform_name.empty() ? reference.waveform_name : reference.name);
394 }
395 const auto& if_chain = rx.getFmcwIfChainRequest();
396 if (if_chain.sample_rate_hz.has_value())
397 {
398 addChildWithNumber(mode_elem, "if_sample_rate", *if_chain.sample_rate_hz);
399 }
400 if (if_chain.filter_bandwidth_hz.has_value())
401 {
402 addChildWithNumber(mode_elem, "if_filter_bandwidth", *if_chain.filter_bandwidth_hz);
403 }
404 if (if_chain.filter_transition_width_hz.has_value())
405 {
406 addChildWithNumber(mode_elem, "if_filter_transition_width", *if_chain.filter_transition_width_hz);
407 }
408 }
409
411 {
412 const XmlElement rx_elem = parent.addChild("receiver");
413 rx_elem.setAttribute("name", rx.getName());
414 rx_elem.setAttribute("antenna", (rx.getAntenna() != nullptr) ? rx.getAntenna()->getName() : "");
415 rx_elem.setAttribute("timing", rx.getTiming() ? rx.getTiming()->getName() : "");
418
419 if (rx.getMode() == radar::OperationMode::PULSED_MODE)
420 {
421 const XmlElement mode_elem = rx_elem.addChild("pulsed_mode");
422 addChildWithNumber(mode_elem, "prf", rx.getWindowPrf());
423 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
424 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
425 }
426 else if (rx.getMode() == radar::OperationMode::FMCW_MODE)
427 {
428 serializeReceiverFmcwMode(rx, rx_elem.addChild("fmcw_mode"));
429 }
430 else if (rx.getMode() == radar::OperationMode::SFCW_MODE)
431 {
432 (void)rx_elem.addChild("sfcw_mode");
433 }
434 else
435 {
436 (void)rx_elem.addChild("cw_mode");
437 }
438
439 if (rx.getNoiseTemperature() > 0)
440 {
441 addChildWithNumber(rx_elem, "noise_temp", rx.getNoiseTemperature());
442 }
443
444 serializeSchedule(rx.getSchedule(), rx_elem);
445 }
446
448 {
449 const XmlElement mono_elem = parent.addChild("monostatic");
450 mono_elem.setAttribute("name", tx.getName());
451 mono_elem.setAttribute("antenna", (tx.getAntenna() != nullptr) ? tx.getAntenna()->getName() : "");
452 mono_elem.setAttribute("waveform", (tx.getSignal() != nullptr) ? tx.getSignal()->getName() : "");
453 mono_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
456
457 if (tx.getMode() == radar::OperationMode::PULSED_MODE)
458 {
459 const XmlElement mode_elem = mono_elem.addChild("pulsed_mode");
460 addChildWithNumber(mode_elem, "prf", tx.getPrf());
461 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
462 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
463 }
464 else if (tx.getMode() == radar::OperationMode::FMCW_MODE)
465 {
466 serializeReceiverFmcwMode(rx, mono_elem.addChild("fmcw_mode"));
467 }
468 else if (tx.getMode() == radar::OperationMode::SFCW_MODE)
469 {
470 (void)mono_elem.addChild("sfcw_mode");
471 }
472 else
473 {
474 (void)mono_elem.addChild("cw_mode");
475 }
476
477 if (rx.getNoiseTemperature() > 0)
478 {
479 addChildWithNumber(mono_elem, "noise_temp", rx.getNoiseTemperature());
480 }
481
482 serializeSchedule(tx.getSchedule(), mono_elem);
483 }
484
486 {
487 const XmlElement target_elem = parent.addChild("target");
488 target_elem.setAttribute("name", target.getName());
489
490 const XmlElement rcs_elem = target_elem.addChild("rcs");
491 if (const auto* iso = dynamic_cast<const radar::IsoTarget*>(&target))
492 {
493 rcs_elem.setAttribute("type", "isotropic");
494 addChildWithNumber(rcs_elem, "value", iso->getConstRcs());
495 }
496 else if (const auto* file_target = dynamic_cast<const radar::FileTarget*>(&target))
497 {
498 rcs_elem.setAttribute("type", "file");
499 rcs_elem.setAttribute("filename", file_target->getFilename());
500 }
501
502 // Serialize fluctuation model if present
503 if (const auto* model = target.getFluctuationModel())
504 {
505 if (const auto* chi = dynamic_cast<const radar::RcsChiSquare*>(model))
506 {
507 XmlElement const model_elem = target_elem.addChild("model");
508 model_elem.setAttribute("type", "chisquare");
509 addChildWithNumber(model_elem, "k", chi->getK());
510 }
511 }
512 }
513
515 {
516 parent.setAttribute("name", platform.getName());
517
518 const XmlElement motion_elem = parent.addChild("motionpath");
519 serializeMotionPath(*platform.getMotionPath(), motion_elem);
520
521 serializeRotation(*platform.getRotationPath(), parent);
522
523 for (const auto& tx : world.getTransmitters())
524 {
525 if (tx->getPlatform() == &platform)
526 {
527 if (tx->getAttached() != nullptr)
528 {
529 serializeMonostatic(*tx, *dynamic_cast<const radar::Receiver*>(tx->getAttached()), parent);
530 }
531 else
532 {
534 }
535 }
536 }
537
538 for (const auto& rx : world.getReceivers())
539 {
540 if (rx->getPlatform() == &platform && (rx->getAttached() == nullptr))
541 {
543 }
544 }
545
546 for (const auto& target : world.getTargets())
547 {
548 if (target->getPlatform() == &platform)
549 {
551 }
552 }
553 }
554}
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 FileSignal * getFileSignal() const noexcept
Gets the file-backed signal implementation, if this signal owns one.
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.