FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
xml_serializer.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2024-present FERS Contributors (see AUTHORS.md).
4//
5// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
6
7/**
8 * @file xml_serializer.cpp
9 * @brief Implementation for serializing the simulation world to XML.
10 *
11 * This file contains the logic to traverse the in-memory C++ object representation
12 * of a FERS simulation and build a corresponding XML document. The process involves
13 * converting internal data representations (like angles in radians) back to the
14 * user-facing format defined by the FERS XML schema (like compass degrees).
15 */
16
17#include "xml_serializer.h"
18
19#include <iomanip>
20#include <ranges>
21#include <sstream>
22
24#include "core/config.h"
25#include "core/parameters.h"
26#include "core/world.h"
27#include "libxml_wrapper.h"
28#include "math/coord.h"
29#include "math/path.h"
30#include "math/rotation_path.h"
31#include "radar/platform.h"
32#include "radar/receiver.h"
33#include "radar/target.h"
34#include "radar/transmitter.h"
35#include "signal/radar_signal.h"
37#include "timing/timing.h"
38
39namespace
40{
41 // --- Helper Functions ---
42
43 void addChildWithText(const XmlElement& parent, const std::string& name, const std::string& text)
44 {
45 parent.addChild(name).setText(text);
46 }
47
48 template <typename T>
49 void addChildWithNumber(const XmlElement& parent, const std::string& name, T value)
50 {
51 if constexpr (std::is_floating_point_v<T>)
52 {
53 // `std::to_chars` is used for floating-point types to ensure that the
54 // serialization is locale-independent and maintains full precision.
55 // This avoids issues where stream-based methods might be affected by
56 // the system's locale or might truncate precision.
57 std::array<char, 64> buffer{};
58 if (auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); ec == std::errc())
59 {
60 addChildWithText(parent, name, std::string(buffer.data(), ptr - buffer.data()));
61 }
62 else
63 {
64 // Fallback for the rare case that std::to_chars fails.
65 std::stringstream ss;
66 ss << std::setprecision(std::numeric_limits<T>::max_digits10) << value;
67 addChildWithText(parent, name, ss.str());
68 }
69 }
70 else
71 {
72 // For integer types, std::to_string is sufficient and clear.
73 addChildWithText(parent, name, std::to_string(value));
74 }
75 }
76
77 void setAttributeFromBool(const XmlElement& element, const std::string& name, const bool value)
78 {
79 element.setAttribute(name, value ? "true" : "false");
80 }
81
82 // --- Component Serialization Functions ---
83
84 void serializeSchedule(const std::vector<radar::SchedulePeriod>& schedule, const XmlElement& parent)
85 {
86 if (schedule.empty())
87 {
88 return;
89 }
90 const XmlElement sched_elem = parent.addChild("schedule");
91 for (const auto& period : schedule)
92 {
93 XmlElement p_elem = sched_elem.addChild("period");
94 p_elem.setAttribute("start", std::to_string(period.start));
95 p_elem.setAttribute("end", std::to_string(period.end));
96 }
97 }
98
99 void serializeParameters(const XmlElement& parent)
100 {
101 addChildWithNumber(parent, "starttime", params::startTime());
102 addChildWithNumber(parent, "endtime", params::endTime());
103 addChildWithNumber(parent, "rate", params::rate());
104
106 {
107 addChildWithNumber(parent, "c", params::c());
108 }
109 if (params::simSamplingRate() != 1000.0)
110 {
111 addChildWithNumber(parent, "simSamplingRate", params::simSamplingRate());
112 }
113 if (params::params.random_seed)
114 {
115 addChildWithNumber(parent, "randomseed", *params::params.random_seed);
116 }
117 if (params::adcBits() != 0)
118 {
119 addChildWithNumber(parent, "adc_bits", params::adcBits());
120 }
121 if (params::oversampleRatio() != 1)
122 {
123 addChildWithNumber(parent, "oversample", params::oversampleRatio());
124 }
125
126 const XmlElement origin = parent.addChild("origin");
127 origin.setAttribute("latitude", std::to_string(params::originLatitude()));
128 origin.setAttribute("longitude", std::to_string(params::originLongitude()));
129 origin.setAttribute("altitude", std::to_string(params::originAltitude()));
130
131 const XmlElement cs = parent.addChild("coordinatesystem");
132 switch (params::coordinateFrame())
133 {
135 cs.setAttribute("frame", "ENU");
136 break;
138 cs.setAttribute("frame", "UTM");
139 cs.setAttribute("zone", std::to_string(params::utmZone()));
140 cs.setAttribute("hemisphere", params::utmNorthHemisphere() ? "N" : "S");
141 break;
143 cs.setAttribute("frame", "ECEF");
144 break;
145 }
146 }
147
148 void serializeWaveform(const fers_signal::RadarSignal& waveform, const XmlElement& parent)
149 {
150 parent.setAttribute("name", waveform.getName());
151
152 addChildWithNumber(parent, "power", waveform.getPower());
153 addChildWithNumber(parent, "carrier_frequency", waveform.getCarrier());
154
155 if (dynamic_cast<const fers_signal::CwSignal*>(waveform.getSignal()))
156 {
157 (void)parent.addChild("cw"); // Empty element
158 }
159 else
160 {
161 const XmlElement pulsed_file = parent.addChild("pulsed_from_file");
162 // Gracefully handle missing filename to prevent export crashes.
163 // While the schema requires a filename, it is better to export an empty string
164 // for work-in-progress scenarios than to crash the application.
165 const auto& filename = waveform.getFilename();
166 pulsed_file.setAttribute("filename", filename.value_or(""));
167 }
168 }
169
170 void serializeTiming(const timing::PrototypeTiming& timing, const XmlElement& parent)
171 {
172 parent.setAttribute("name", timing.getName());
173 setAttributeFromBool(parent, "synconpulse", timing.getSyncOnPulse());
174
175 addChildWithNumber(parent, "frequency", timing.getFrequency());
176 if (const auto val = timing.getFreqOffset())
177 {
178 addChildWithNumber(parent, "freq_offset", *val);
179 }
180 if (const auto val = timing.getRandomFreqOffsetStdev())
181 {
182 addChildWithNumber(parent, "random_freq_offset_stdev", *val);
183 }
184 if (const auto val = timing.getPhaseOffset())
185 {
186 addChildWithNumber(parent, "phase_offset", *val);
187 }
188 if (const auto val = timing.getRandomPhaseOffsetStdev())
189 {
190 addChildWithNumber(parent, "random_phase_offset_stdev", *val);
191 }
192
193 std::vector<RealType> alphas, weights;
194 timing.copyAlphas(alphas, weights);
195 for (size_t i = 0; i < alphas.size(); ++i)
196 {
197 XmlElement entry = parent.addChild("noise_entry");
198 addChildWithNumber(entry, "alpha", alphas[i]);
199 addChildWithNumber(entry, "weight", weights[i]);
200 }
201 }
202
203 void serializeAntenna(const antenna::Antenna& antenna, const XmlElement& parent)
204 {
205 parent.setAttribute("name", antenna.getName());
206
207 if (const auto* sinc = dynamic_cast<const antenna::Sinc*>(&antenna))
208 {
209 parent.setAttribute("pattern", "sinc");
210 addChildWithNumber(parent, "alpha", sinc->getAlpha());
211 addChildWithNumber(parent, "beta", sinc->getBeta());
212 addChildWithNumber(parent, "gamma", sinc->getGamma());
213 }
214 else if (const auto* gaussian = dynamic_cast<const antenna::Gaussian*>(&antenna))
215 {
216 parent.setAttribute("pattern", "gaussian");
217 addChildWithNumber(parent, "azscale", gaussian->getAzimuthScale());
218 addChildWithNumber(parent, "elscale", gaussian->getElevationScale());
219 }
220 else if (const auto* sh = dynamic_cast<const antenna::SquareHorn*>(&antenna))
221 {
222 parent.setAttribute("pattern", "squarehorn");
223 addChildWithNumber(parent, "diameter", sh->getDimension());
224 }
225 else if (const auto* parabolic = dynamic_cast<const antenna::Parabolic*>(&antenna))
226 {
227 parent.setAttribute("pattern", "parabolic");
228 addChildWithNumber(parent, "diameter", parabolic->getDiameter());
229 }
230 else if (const auto* xml_ant = dynamic_cast<const antenna::XmlAntenna*>(&antenna))
231 {
232 parent.setAttribute("pattern", "xml");
233 parent.setAttribute("filename", xml_ant->getFilename());
234 }
235 else if (const auto* h5_ant = dynamic_cast<const antenna::H5Antenna*>(&antenna))
236 {
237 parent.setAttribute("pattern", "file");
238 parent.setAttribute("filename", h5_ant->getFilename());
239 }
240 else
241 {
242 parent.setAttribute("pattern", "isotropic");
243 }
244
245 if (antenna.getEfficiencyFactor() != 1.0)
246 {
247 addChildWithNumber(parent, "efficiency", antenna.getEfficiencyFactor());
248 }
249 }
250
251 void serializeMotionPath(const math::Path& path, const XmlElement& parent)
252 {
253 switch (path.getType())
254 {
256 parent.setAttribute("interpolation", "static");
257 break;
259 parent.setAttribute("interpolation", "linear");
260 break;
262 parent.setAttribute("interpolation", "cubic");
263 break;
264 }
265
266 for (const auto& [pos, t] : path.getCoords())
267 {
268 XmlElement wp_elem = parent.addChild("positionwaypoint");
269 addChildWithNumber(wp_elem, "x", pos.x);
270 addChildWithNumber(wp_elem, "y", pos.y);
271 addChildWithNumber(wp_elem, "altitude", pos.z);
272 addChildWithNumber(wp_elem, "time", t);
273 }
274 }
275
276 void serializeRotation(const math::RotationPath& rotPath, const XmlElement& parent)
277 {
279 {
280 const XmlElement fixed_elem = parent.addChild("fixedrotation");
281 const auto start = rotPath.getStart();
282 const auto rate = rotPath.getRate();
283
284 // Convert internal mathematical angles (radians, CCW from East) back to
285 // the XML format's compass degrees (CW from North). This transformation
286 // is necessary at the serialization boundary to ensure the output XML
287 // conforms to the user-facing FERS schema and is human-readable.
288 const RealType start_az_deg = std::fmod(90.0 - start.azimuth * 180.0 / PI + 360.0, 360.0);
289 const RealType start_el_deg = start.elevation * 180.0 / PI;
290 const RealType rate_az_deg_s = -rate.azimuth * 180.0 / PI; // Invert for CW rotation
291 const RealType rate_el_deg_s = rate.elevation * 180.0 / PI;
292
293 addChildWithNumber(fixed_elem, "startazimuth", start_az_deg);
294 addChildWithNumber(fixed_elem, "startelevation", start_el_deg);
295 addChildWithNumber(fixed_elem, "azimuthrate", rate_az_deg_s);
296 addChildWithNumber(fixed_elem, "elevationrate", rate_el_deg_s);
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; // Should not happen
314 }
315 for (const auto& wp : rotPath.getCoords())
316 {
317 XmlElement wp_elem = rot_elem.addChild("rotationwaypoint");
318 // Convert angles back to compass degrees for XML output. This is
319 // done to ensure the output conforms to the FERS XML schema.
320 const RealType az_deg = std::fmod(90.0 - wp.azimuth * 180.0 / PI + 360.0, 360.0);
321 const RealType el_deg = wp.elevation * 180.0 / PI;
322 addChildWithNumber(wp_elem, "azimuth", az_deg);
323 addChildWithNumber(wp_elem, "elevation", el_deg);
324 addChildWithNumber(wp_elem, "time", wp.t);
325 }
326 }
327 }
328
329 void serializeTransmitter(const radar::Transmitter& tx, const XmlElement& parent)
330 {
331 const XmlElement tx_elem = parent.addChild("transmitter");
332 tx_elem.setAttribute("name", tx.getName());
333 tx_elem.setAttribute("waveform", tx.getSignal() ? tx.getSignal()->getName() : "");
334 tx_elem.setAttribute("antenna", tx.getAntenna() ? tx.getAntenna()->getName() : "");
335 tx_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
336
338 {
339 const XmlElement mode_elem = tx_elem.addChild("pulsed_mode");
340 addChildWithNumber(mode_elem, "prf", tx.getPrf());
341 }
342 else
343 {
344 (void)tx_elem.addChild("cw_mode");
345 }
346
347 serializeSchedule(tx.getSchedule(), tx_elem);
348 }
349
350 void serializeReceiver(const radar::Receiver& rx, const XmlElement& parent)
351 {
352 const XmlElement rx_elem = parent.addChild("receiver");
353 rx_elem.setAttribute("name", rx.getName());
354 rx_elem.setAttribute("antenna", rx.getAntenna() ? rx.getAntenna()->getName() : "");
355 rx_elem.setAttribute("timing", rx.getTiming() ? rx.getTiming()->getName() : "");
356 setAttributeFromBool(rx_elem, "nodirect", rx.checkFlag(radar::Receiver::RecvFlag::FLAG_NODIRECT));
357 setAttributeFromBool(rx_elem, "nopropagationloss", rx.checkFlag(radar::Receiver::RecvFlag::FLAG_NOPROPLOSS));
358
360 {
361 const XmlElement mode_elem = rx_elem.addChild("pulsed_mode");
362 addChildWithNumber(mode_elem, "prf", rx.getWindowPrf());
363 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
364 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
365 }
366 else
367 {
368 (void)rx_elem.addChild("cw_mode");
369 }
370
371 if (rx.getNoiseTemperature() > 0)
372 {
373 addChildWithNumber(rx_elem, "noise_temp", rx.getNoiseTemperature());
374 }
375
376 serializeSchedule(rx.getSchedule(), rx_elem);
377 }
378
379 void serializeMonostatic(const radar::Transmitter& tx, const radar::Receiver& rx, const XmlElement& parent)
380 {
381 const XmlElement mono_elem = parent.addChild("monostatic");
382 mono_elem.setAttribute("name", tx.getName());
383 mono_elem.setAttribute("antenna", tx.getAntenna() ? tx.getAntenna()->getName() : "");
384 mono_elem.setAttribute("waveform", tx.getSignal() ? tx.getSignal()->getName() : "");
385 mono_elem.setAttribute("timing", tx.getTiming() ? tx.getTiming()->getName() : "");
386 setAttributeFromBool(mono_elem, "nodirect", rx.checkFlag(radar::Receiver::RecvFlag::FLAG_NODIRECT));
387 setAttributeFromBool(mono_elem, "nopropagationloss", rx.checkFlag(radar::Receiver::RecvFlag::FLAG_NOPROPLOSS));
388
390 {
391 const XmlElement mode_elem = mono_elem.addChild("pulsed_mode");
392 addChildWithNumber(mode_elem, "prf", tx.getPrf());
393 addChildWithNumber(mode_elem, "window_skip", rx.getWindowSkip());
394 addChildWithNumber(mode_elem, "window_length", rx.getWindowLength());
395 }
396 else
397 {
398 (void)mono_elem.addChild("cw_mode");
399 }
400
401 if (rx.getNoiseTemperature() > 0)
402 {
403 addChildWithNumber(mono_elem, "noise_temp", rx.getNoiseTemperature());
404 }
405
406 serializeSchedule(tx.getSchedule(), mono_elem);
407 }
408
409 void serializeTarget(const radar::Target& target, const XmlElement& parent)
410 {
411 const XmlElement target_elem = parent.addChild("target");
412 target_elem.setAttribute("name", target.getName());
413
414 const XmlElement rcs_elem = target_elem.addChild("rcs");
415 if (const auto* iso = dynamic_cast<const radar::IsoTarget*>(&target))
416 {
417 rcs_elem.setAttribute("type", "isotropic");
418 addChildWithNumber(rcs_elem, "value", iso->getConstRcs());
419 }
420 else if (const auto* file_target = dynamic_cast<const radar::FileTarget*>(&target))
421 {
422 rcs_elem.setAttribute("type", "file");
423 rcs_elem.setAttribute("filename", file_target->getFilename());
424 }
425
426 // Serialize fluctuation model if present (e.g. Swerling/Chi-Square)
427 if (const auto* model = target.getFluctuationModel())
428 {
429 if (const auto* chi = dynamic_cast<const radar::RcsChiSquare*>(model))
430 {
431 XmlElement model_elem = target_elem.addChild("model");
432 model_elem.setAttribute("type", "chisquare");
433 addChildWithNumber(model_elem, "k", chi->getK());
434 }
435 }
436 }
437
438 void serializePlatform(const radar::Platform& platform, const core::World& world, const XmlElement& parent)
439 {
440 parent.setAttribute("name", platform.getName());
441
442 const XmlElement motion_elem = parent.addChild("motionpath");
443 serializeMotionPath(*platform.getMotionPath(), motion_elem);
444
445 serializeRotation(*platform.getRotationPath(), parent);
446
447 // Transmitters (including Monostatic pairs)
448 for (const auto& tx : world.getTransmitters())
449 {
450 if (tx->getPlatform() == &platform)
451 {
452 if (tx->getAttached())
453 {
454 // Serialize as <monostatic> if it is part of a pair
455 serializeMonostatic(*tx, *dynamic_cast<const radar::Receiver*>(tx->getAttached()), parent);
456 }
457 else
458 {
459 // Serialize as <transmitter>
460 serializeTransmitter(*tx, parent);
461 }
462 }
463 }
464
465 // Standalone Receivers
466 for (const auto& rx : world.getReceivers())
467 {
468 // Only serialize receivers that are NOT attached to a transmitter,
469 // as those were handled in the loop above.
470 if (rx->getPlatform() == &platform && !rx->getAttached())
471 {
472 serializeReceiver(*rx, parent);
473 }
474 }
475
476 // Targets
477 for (const auto& target : world.getTargets())
478 {
479 if (target->getPlatform() == &platform)
480 {
481 serializeTarget(*target, parent);
482 }
483 }
484 }
485}
486
487namespace serial
488{
489 std::string world_to_xml_string(const core::World& world)
490 {
491 XmlDocument doc;
492 xmlNodePtr sim_node = xmlNewNode(nullptr, reinterpret_cast<const xmlChar*>("simulation"));
493 XmlElement root(sim_node);
494 doc.setRootElement(root);
495
496 if (!params::params.simulation_name.empty())
497 {
498 root.setAttribute("name", params::params.simulation_name);
499 }
500 else
501 {
502 root.setAttribute("name", "FERS Scenario");
503 }
504
505 const XmlElement params_elem = root.addChild("parameters");
506 serializeParameters(params_elem);
507
508 // Assets (waveforms, timings, antennas) are serialized first. This is
509 // necessary because platforms reference these assets by name. By defining
510 // them at the top of the document, we ensure that any XML parser can
511 // resolve these references when it later encounters the platform definitions.
512 for (const auto& waveform : world.getWaveforms() | std::views::values)
513 {
514 XmlElement waveform_elem = root.addChild("waveform");
515 serializeWaveform(*waveform, waveform_elem);
516 }
517 for (const auto& timing : world.getTimings() | std::views::values)
518 {
519 XmlElement timing_elem = root.addChild("timing");
520 serializeTiming(*timing, timing_elem);
521 }
522 for (const auto& antenna : world.getAntennas() | std::views::values)
523 {
524 XmlElement antenna_elem = root.addChild("antenna");
525 serializeAntenna(*antenna, antenna_elem);
526 }
527 for (const auto& platform : world.getPlatforms())
528 {
529 XmlElement plat_elem = root.addChild("platform");
530 serializePlatform(*platform, world, plat_elem);
531 }
532
533 return doc.dumpToString();
534 }
535}
Header file defining various types of antennas and their gain patterns.
Class for managing XML documents.
void setRootElement(const XmlElement &root) const
Set the root element of the document.
std::string dumpToString() const
Dumps the document to a string.
Class representing a node in an XML document.
XmlElement addChild(const std::string_view name) const noexcept
Add a child element to the current node.
void setAttribute(const std::string_view name, const std::string_view value) const
Set an attribute on the XML element.
void setText(const std::string_view text) const
Set the text content of the XML element.
Abstract base class representing an antenna.
std::string getName() const noexcept
Retrieves the name of the 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:38
const std::unordered_map< std::string, std::unique_ptr< fers_signal::RadarSignal > > & getWaveforms() const noexcept
Retrieves the map of radar signals (waveforms).
Definition world.h:173
const std::vector< std::unique_ptr< radar::Platform > > & getPlatforms() const noexcept
Retrieves the list of platforms.
Definition world.h:133
const std::unordered_map< std::string, std::unique_ptr< timing::PrototypeTiming > > & getTimings() const noexcept
Retrieves the map of timing prototypes.
Definition world.h:193
const std::unordered_map< std::string, std::unique_ptr< antenna::Antenna > > & getAntennas() const noexcept
Retrieves the map of antennas.
Definition world.h:183
Class representing a radar signal with associated properties.
const std::optional< std::string > & getFilename() const noexcept
Gets the filename associated with this signal.
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.
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:30
InterpType getType() const noexcept
Retrieves the current interpolation type of the path.
Definition path.h:76
Manages rotational paths with different interpolation techniques.
InterpType getType() const noexcept
Gets the interpolation type of the path.
RotationCoord getRate() const noexcept
Gets the rate of change for the rotation.
RotationCoord getStart() const noexcept
Gets the starting rotation coordinate.
File-based radar target.
Definition target.h:210
Isotropic radar target.
Definition target.h:172
const std::string & getName() const noexcept
Retrieves the name of the object.
Definition object.h:68
Platform * getPlatform() const noexcept
Retrieves the associated platform of the object.
Definition object.h:61
Represents a simulation platform with motion and rotation paths.
Definition platform.h:31
math::Path * getMotionPath() const noexcept
Gets the motion path of the platform.
Definition platform.h:59
const std::string & getName() const noexcept
Gets the name of the platform.
Definition platform.h:89
math::RotationPath * getRotationPath() const noexcept
Gets the rotation path of the platform.
Definition platform.h:66
const Radar * getAttached() const noexcept
Retrieves the attached radar object.
Definition radar_obj.h:71
const antenna::Antenna * getAntenna() const noexcept
Gets the antenna associated with this radar.
Definition radar_obj.h:78
std::shared_ptr< timing::Timing > getTiming() const
Retrieves the timing source for the radar.
Definition radar_obj.cpp:66
Chi-square distributed RCS model.
Definition target.h:81
Manages radar signal reception and response processing.
Definition receiver.h:36
bool checkFlag(RecvFlag flag) const noexcept
Checks if a specific flag is set.
Definition receiver.h:86
const std::vector< SchedulePeriod > & getSchedule() const noexcept
Retrieves the list of active reception periods.
Definition receiver.h:255
RealType getNoiseTemperature() const noexcept
Retrieves the noise temperature of the receiver.
Definition receiver.h:93
OperationMode getMode() const noexcept
Gets the operational mode of the receiver.
Definition receiver.h:151
RealType getWindowPrf() const noexcept
Retrieves the pulse repetition frequency (PRF) of the radar window.
Definition receiver.h:107
RealType getWindowSkip() const noexcept
Retrieves the window skip time.
Definition receiver.h:114
RealType getWindowLength() const noexcept
Retrieves the radar window length.
Definition receiver.h:100
Base class for radar targets.
Definition target.h:117
const RcsModel * getFluctuationModel() const
Gets the RCS fluctuation model.
Definition target.h:159
Represents a radar transmitter system.
Definition transmitter.h:32
RealType getPrf() const noexcept
Retrieves the pulse repetition frequency (PRF).
Definition transmitter.h:61
fers_signal::RadarSignal * getSignal() const noexcept
Retrieves the radar signal currently being transmitted.
Definition transmitter.h:68
const std::vector< SchedulePeriod > & getSchedule() const noexcept
Retrieves the list of active transmission periods.
OperationMode getMode() const noexcept
Gets the operational mode of the transmitter.
Definition transmitter.h:75
Manages timing properties such as frequency, offsets, and synchronization.
Global configuration file for the project.
double RealType
Type for real numbers.
Definition config.h:27
constexpr RealType PI
Mathematical constant π (pi).
Definition config.h:43
Coordinate and rotation structure operations.
Wrapper for managing XML documents and elements using libxml2.
RealType simSamplingRate() noexcept
Get the simulation sampling rate.
Definition parameters.h:103
RealType endTime() noexcept
Get the end time for the simulation.
Definition parameters.h:97
RealType rate() noexcept
Get the rendering sample rate.
Definition parameters.h:109
RealType startTime() noexcept
Get the start time for the simulation.
Definition parameters.h:91
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
Definition parameters.h:139
double originLongitude() noexcept
Definition parameters.h:238
int utmZone() noexcept
Definition parameters.h:274
@ UTM
Universal Transverse Mercator.
@ ENU
East-North-Up local tangent plane (default)
@ ECEF
Earth-Centered, Earth-Fixed.
unsigned adcBits() noexcept
Get the ADC quantization bits.
Definition parameters.h:121
CoordinateFrame coordinateFrame() noexcept
Definition parameters.h:272
double originLatitude() noexcept
Definition parameters.h:236
bool utmNorthHemisphere() noexcept
Definition parameters.h:276
Parameters params
Definition parameters.h:73
RealType c() noexcept
Get the speed of light.
Definition parameters.h:79
double originAltitude() noexcept
Definition parameters.h:240
@ PULSED_MODE
The component operates in a pulsed mode.
std::string world_to_xml_string(const core::World &world)
Serializes the entire simulation world into an XML formatted string.
Defines the Parameters struct and provides methods for managing simulation parameters.
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.
static constexpr RealType DEFAULT_C
Speed of light (m/s)
Definition parameters.h:41
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.
Provides functions to serialize the simulation world back into the FERS XML format.