9#include <GeographicLib/UTMUPS.hpp>
20#include "fers_xml_dtd.h"
21#include "fers_xml_xsd.h"
38namespace fs = std::filesystem;
44 [[nodiscard]]
unsigned next_seed(std::mt19937& master_seeder)
46 static_assert(std::mt19937::max() <= std::numeric_limits<unsigned>::max(),
47 "std::mt19937 output must fit into unsigned seeds.");
48 return static_cast<unsigned>(master_seeder());
57 throw XmlException(
"Element " + elementName +
" is empty!");
59 return std::stod(text);
71 attributeName, defaultVal);
84 const std::unordered_map<std::string, SimId>& name_map)
89 throw XmlException(
"Missing " + attributeName +
" for " + owner +
".");
91 const auto it = name_map.find(value);
92 if (it != name_map.end())
96 throw XmlException(
"Unknown " + attributeName +
" '" + value +
"' for " + owner +
".");
100 const bool isPulsed,
const RealType pri)
102 std::vector<radar::SchedulePeriod> raw_periods;
117 raw_periods.push_back({start, end});
119 catch (
const std::exception& e)
136 if (params_out.
rate <= 0)
138 throw std::runtime_error(
"Sampling rate must be > 0");
142 const auto parse_unsigned_parameter = [&](
const std::string_view param_name,
const RealType raw_value)
144 if (!std::isfinite(raw_value))
146 throw XmlException(std::format(
"Parameter '{}' must be finite.", param_name));
150 throw XmlException(std::format(
"Parameter '{}' must be non-negative.", param_name));
153 const RealType floored_value = std::floor(raw_value);
154 if (floored_value >
static_cast<RealType>(std::numeric_limits<unsigned>::max()))
156 throw XmlException(std::format(
"Parameter '{}' exceeds the supported unsigned range.", param_name));
159 return static_cast<unsigned>(floored_value);
162 auto set_optional_real_parameter = [&](
const std::string& param_name,
const RealType default_value,
auto setter)
174 auto set_optional_unsigned_parameter =
175 [&](
const std::string& param_name,
const unsigned default_value,
auto setter)
190 params_out.
c = value;
194 set_optional_real_parameter(
"simSamplingRate", 1000.0,
203 const auto seed = parse_unsigned_parameter(
"randomseed",
get_child_real_type(parameters,
"randomseed"));
208 set_optional_unsigned_parameter(
"adc_bits", 0,
209 [&](
const unsigned value)
215 set_optional_unsigned_parameter(
"oversample", 1,
216 [&](
const unsigned value)
220 throw std::runtime_error(
"Oversample ratio must be >= 1");
229 if (!unit_token.empty())
237 throw XmlException(
"Unsupported rotation angle unit '" + unit_token +
"'.");
245 bool origin_set =
false;
257 catch (
const std::exception& e)
269 if (frame_str ==
"UTM")
275 if (params_out.
utm_zone < GeographicLib::UTMUPS::MINUTMZONE ||
276 params_out.
utm_zone > GeographicLib::UTMUPS::MAXUTMZONE)
279 " is invalid; must be in [1, 60].");
281 if (hem_str ==
"N" || hem_str ==
"n")
285 else if (hem_str ==
"S" || hem_str ==
"s")
291 throw XmlException(
"UTM hemisphere '" + hem_str +
"' is invalid; must be 'N' or 'S'.");
296 else if (frame_str ==
"ECEF")
301 else if (frame_str ==
"ENU")
307 "ENU frame specified but no <origin> tag found. Using default origin at UCT.");
313 throw XmlException(
"Unsupported coordinate frame: " + frame_str);
316 catch (
const std::exception& e)
338 fs::path pulse_path(filename_str);
340 if (!fs::exists(pulse_path))
342 pulse_path = ctx.
base_dir / filename_str;
351 auto cw_signal = std::make_unique<fers_signal::CwSignal>();
352 auto wave = std::make_unique<fers_signal::RadarSignal>(
359 throw XmlException(
"Unsupported waveform type for '" + name +
"'");
368 auto timing_obj = std::make_unique<timing::PrototypeTiming>(name,
id);
370 timing_obj->setFrequency(freq);
372 unsigned noise_index = 0;
375 XmlElement noise_element =
timing.childElement(
"noise_entry", noise_index++);
423 timing_obj->setSyncOnPulse();
426 ctx.
world->
add(std::move(timing_obj));
435 std::unique_ptr<antenna::Antenna> ant;
438 if (pattern ==
"isotropic")
440 ant = std::make_unique<antenna::Isotropic>(name,
id);
442 else if (pattern ==
"sinc")
448 else if (pattern ==
"gaussian")
453 else if (pattern ==
"squarehorn")
457 else if (pattern ==
"parabolic")
461 else if (pattern ==
"xml")
465 else if (pattern ==
"file")
472 throw XmlException(
"Unsupported antenna pattern: " + pattern);
496 else if (
interp ==
"cubic")
500 else if (
interp ==
"static")
514 "Failed to set MotionPath interpolation type for platform {}. Defaulting to static",
519 unsigned waypoint_index = 0;
557 else if (
interp ==
"cubic")
561 else if (
interp ==
"static")
573 "Failed to set RotationPath interpolation type for platform {}. Defaulting to static",
578 unsigned waypoint_index = 0;
595 const std::string owner =
596 std::format(
"platform '{}' rotation waypoint {}", platform->
getName(), waypoint_index);
624 const std::string owner = std::format(
"platform '{}' fixedrotation", platform->
getName());
656 const bool is_pulsed = pulsed_mode_element.
isValid();
661 throw XmlException(
"Transmitter '" + name +
"' must specify a radar mode (<pulsed_mode> or <cw_mode>).");
664 auto transmitter_obj = std::make_unique<radar::Transmitter>(platform, name, mode,
id);
666 const SimId waveform_id =
671 throw XmlException(
"Waveform ID '" + std::to_string(waveform_id) +
"' not found for transmitter '" + name +
674 transmitter_obj->setWave(wave);
681 const SimId antenna_id =
686 throw XmlException(
"Antenna ID '" + std::to_string(antenna_id) +
"' not found for transmitter '" + name +
689 transmitter_obj->setAntenna(ant);
691 const SimId timing_id =
694 if (proto ==
nullptr)
696 throw XmlException(
"Timing ID '" + std::to_string(timing_id) +
"' not found for transmitter '" + name +
699 const auto timing_obj =
701 timing_obj->initializeModel(proto);
702 transmitter_obj->setTiming(timing_obj);
704 RealType pri = is_pulsed ? (1.0 / transmitter_obj->getPrf()) : 0.0;
705 auto schedule =
parseSchedule(transmitter, name, is_pulsed, pri);
706 if (!schedule.empty())
708 transmitter_obj->setSchedule(std::move(schedule));
711 ctx.
world->
add(std::move(transmitter_obj));
721 const bool is_pulsed = pulsed_mode_element.
isValid();
724 auto receiver_obj = std::make_unique<radar::Receiver>(platform, name, next_seed(*ctx.
master_seeder), mode,
id);
730 throw XmlException(
"Antenna ID '" + std::to_string(ant_id) +
"' not found for receiver '" + name +
"'");
732 receiver_obj->setAntenna(
antenna);
741 receiver_obj->getName().c_str());
747 if (window_length <= 0)
749 throw XmlException(
"<window_length> must be positive for receiver '" + name +
"'");
755 throw XmlException(
"<prf> must be positive for receiver '" + name +
"'");
761 throw XmlException(
"<window_skip> must not be negative for receiver '" + name +
"'");
763 receiver_obj->setWindowProperties(window_length, prf, window_skip);
767 throw XmlException(
"Receiver '" + name +
"' must specify a radar mode (<pulsed_mode> or <cw_mode>).");
772 if (proto ==
nullptr)
774 throw XmlException(
"Timing ID '" + std::to_string(timing_id) +
"' not found for receiver '" + name +
"'");
776 const auto timing_obj =
778 timing_obj->initializeModel(proto);
779 receiver_obj->setTiming(timing_obj);
791 receiver_obj->getName().c_str());
794 RealType pri = is_pulsed ? (1.0 / receiver_obj->getWindowPrf()) : 0.0;
795 auto schedule =
parseSchedule(receiver, name, is_pulsed, pri);
796 if (!schedule.empty())
798 receiver_obj->setSchedule(std::move(schedule));
801 ctx.
world->
add(std::move(receiver_obj));
822 throw XmlException(
"<rcs> element is required in <target>!");
826 std::unique_ptr<radar::Target> target_obj;
829 if (rcs_type ==
"isotropic")
833 else if (rcs_type ==
"file")
841 throw XmlException(
"Unsupported RCS type: " + rcs_type);
848 target_obj->setFluctuationModel(std::make_unique<radar::RcsConst>());
850 else if (model_type ==
"chisquare" || model_type ==
"gamma")
852 target_obj->setFluctuationModel(
853 std::make_unique<radar::RcsChiSquare>(target_obj->getRngEngine(),
get_child_real_type(model,
"k")));
857 throw XmlException(
"Unsupported model type: " + model_type);
863 ctx.
world->
add(std::move(target_obj));
867 const std::function<
void(
const XmlElement&, std::string_view)>& register_name,
870 auto parseChildrenWithRefs = [&](
const std::string& elementName,
auto parseFunc)
878 register_name(element, elementName);
879 parseFunc(element, plat, ctx, refs);
883 auto parseChildrenWithoutRefs = [&](
const std::string& elementName,
auto parseFunc)
891 register_name(element, elementName);
892 parseFunc(element, plat, ctx);
903 const std::function<
void(
const XmlElement&, std::string_view)>& register_name,
908 auto plat = std::make_unique<radar::Platform>(name,
id);
919 rot_path.
isValid() && fixed_rot.isValid())
922 "Both <rotationpath> and <fixedrotation> are declared for platform {}. Only <rotationpath> will be "
931 else if (fixed_rot.isValid())
945 if (!include_element.
isValid())
948 std::string include_filename = include_element.
getText();
949 if (include_filename.empty())
955 fs::path include_path = currentDir / include_filename;
956 includePaths.push_back(include_path);
959 if (!included_doc.
loadFile(include_path.string()))
971 std::vector<fs::path> include_paths;
973 bool did_combine =
false;
975 for (
const auto& include_path : include_paths)
978 if (!included_doc.
loadFile(include_path.string()))
980 throw XmlException(
"Failed to load included XML file: " + include_path.string());
1012 if (root.
name() !=
"simulation")
1014 throw XmlException(
"Root element is not <simulation>!");
1017 std::unordered_map<std::string, std::string> name_registry;
1018 name_registry.reserve(64);
1019 const auto register_name = [&](
const XmlElement& element,
const std::string_view kind)
1022 const auto [iter, inserted] = name_registry.emplace(name, std::string(kind));
1025 throw XmlException(
"Duplicate name '" + name +
"' found for " + std::string(kind) +
1026 "; previously used by " + iter->second +
".");
1047 auto parseElements =
1056 parseFunction(element, parser_ctx);
1060 parseElements(root,
"waveform", ctx,
1063 register_name(p,
"waveform");
1067 parseElements(root,
"timing", ctx,
1070 register_name(p,
"timing");
1074 parseElements(root,
"antenna", ctx,
1077 register_name(p,
"antenna");
1081 std::unordered_map<std::string, SimId> waveform_refs;
1082 std::unordered_map<std::string, SimId> antenna_refs;
1083 std::unordered_map<std::string, SimId> timing_refs;
1089 waveform_refs.emplace(waveform->getName(), id);
1091 antenna_refs.emplace(
antenna->getName(), id);
1093 timing_refs.emplace(
timing->getName(), id);
1095 const ReferenceLookup refs{&waveform_refs, &antenna_refs, &timing_refs};
1097 parseElements(root,
"platform", ctx,
1100 register_name(p,
"platform");
1107 const auto num_samples =
static_cast<size_t>(std::ceil((end_time - start_time) / dt_sim));
1113 receiver->prepareCwData(num_samples);
1124 return {.
loadWaveform = [](
const std::string& name,
const fs::path& pulse_path,
RealType power,
1127 .loadXmlAntenna = [](
const std::string& name,
const std::string& filename,
SimId id)
1128 {
return std::make_unique<antenna::XmlAntenna>(name, filename,
id); },
1129 .loadH5Antenna = [](
const std::string& name,
const std::string& filename,
SimId id)
1130 {
return std::make_unique<antenna::H5Antenna>(name, filename,
id); },
1131 .loadFileTarget = [](
radar::Platform* platform,
const std::string& name,
const std::string& filename,
1132 unsigned seed,
SimId id)
Header file defining various types of antennas and their gain patterns.
SimId generateId(ObjectType type)
Generate a unique SimId for a given object type.
static SimIdGenerator & instance()
Get the singleton instance of SimIdGenerator.
Class for managing XML documents.
XmlElement getRootElement() const
Get the root element of the document.
bool loadFile(std::string_view filename)
Load an XML file into the document.
bool validateWithDtd(std::span< const unsigned char > dtdData) const
Validate the document using a DTD.
bool validateWithXsd(std::span< const unsigned char > xsdData) const
Validate the document using an XSD schema.
Class representing a node in an XML document.
XmlElement childElement(const std::string_view name="", const unsigned index=0) const noexcept
Retrieve a child element by name and index.
static std::string getSafeAttribute(const XmlElement &element, const std::string_view name)
Get the value of an attribute safely.
std::string_view name() const noexcept
Get the name of the XML element.
bool isValid() const noexcept
Check if the XML element is valid.
std::string getText() const
Get the text content of the XML element.
Exception class for handling XML-related errors.
Abstract base class representing an antenna.
void scheduleInitialEvents()
Populates the event queue with the initial events for the simulation.
void add(std::unique_ptr< radar::Platform > plat) noexcept
Adds a radar platform to the simulation world.
fers_signal::RadarSignal * findWaveform(const SimId id)
Finds a radar signal by ID.
const std::unordered_map< SimId, std::unique_ptr< antenna::Antenna > > & getAntennas() const noexcept
Retrieves the map of antennas.
const std::unordered_map< SimId, std::unique_ptr< fers_signal::RadarSignal > > & getWaveforms() const noexcept
Retrieves the map of radar signals (waveforms).
timing::PrototypeTiming * findTiming(const SimId id)
Finds a timing source by ID.
antenna::Antenna * findAntenna(const SimId id)
Finds an antenna by ID.
const std::unordered_map< SimId, std::unique_ptr< timing::PrototypeTiming > > & getTimings() const noexcept
Retrieves the map of timing prototypes.
std::string dumpEventQueue() const
Dumps the current state of the event queue to a string for debugging.
const std::vector< std::unique_ptr< radar::Transmitter > > & getTransmitters() const noexcept
Retrieves the list of radar transmitters.
const std::vector< std::unique_ptr< radar::Receiver > > & getReceivers() const noexcept
Retrieves the list of radar receivers.
Class representing a radar signal with associated properties.
Represents a path with coordinates and allows for various interpolation methods.
void setInterp(InterpType settype) noexcept
Changes the interpolation type.
void addCoord(const Coord &coord) noexcept
Adds a coordinate to the path.
void finalize()
Finalizes the path, preparing it for interpolation.
Manages rotational paths with different interpolation techniques.
void finalize()
Finalizes the rotation path for interpolation.
void setConstantRate(const RotationCoord &setstart, const RotationCoord &setrate) noexcept
Sets constant rate interpolation.
void setInterp(InterpType setinterp) noexcept
Sets the interpolation type for the path.
void addCoord(const RotationCoord &coord) noexcept
Adds a rotation coordinate to the path.
A class representing a vector in rectangular coordinates.
void setAttached(const Radar *obj)
Attaches another radar object to this radar.
Manages radar signal reception and response processing.
Represents a radar transmitter system.
Manages timing properties such as frequency, offsets, and synchronization.
std::string getName() const
Gets the name of the timing source.
SimId getId() const noexcept
Gets the unique ID of the timing source.
Global configuration file for the project.
double RealType
Type for real numbers.
Coordinate and rotation structure operations.
Classes and operations for 3D geometry.
void mergeXmlDocuments(const XmlDocument &mainDoc, const XmlDocument &includedDoc)
Merge two XML documents.
void removeIncludeElements(const XmlDocument &doc)
Remove "include" elements from the XML document.
Header file for the logging system.
@ WARNING
Warning level for potentially harmful situations.
@ FATAL
Fatal level for severe error events.
@ TRACE
Trace level for detailed debugging information.
@ INFO
Info level for informational messages.
@ ERROR
Error level for error events.
@ DEBUG
Debug level for general debugging information.
RotationAngleUnit
Defines the units used at external rotation-path boundaries.
@ UTM
Universal Transverse Mercator.
@ ENU
East-North-Up local tangent plane (default)
@ ECEF
Earth-Centered, Earth-Fixed.
std::optional< RotationAngleUnit > rotationAngleUnitFromToken(const std::string_view token) noexcept
std::unique_ptr< Target > createIsoTarget(Platform *platform, std::string name, RealType rcs, unsigned seed, const SimId id=0)
Creates an isotropic target.
std::unique_ptr< Target > createFileTarget(Platform *platform, std::string name, const std::string &filename, unsigned seed, const SimId id=0)
Creates a file-based target.
std::vector< SchedulePeriod > processRawSchedule(std::vector< SchedulePeriod > periods, const std::string &ownerName, const bool isPulsed, const RealType pri)
Processes a raw list of schedule periods.
OperationMode
Defines the operational mode of a radar component.
@ PULSED_MODE
The component operates in a pulsed mode.
@ CW_MODE
The component operates in a continuous-wave mode.
math::RotationCoord external_rotation_to_internal(const RealType azimuth, const RealType elevation, const RealType time, const params::RotationAngleUnit unit) noexcept
math::RotationCoord external_rotation_rate_to_internal(const RealType azimuth_rate, const RealType elevation_rate, const RealType time, const params::RotationAngleUnit unit) noexcept
void maybe_warn_about_rotation_value(const RealType value, const params::RotationAngleUnit declared_unit, const ValueKind kind, const std::string_view source, const std::string_view owner, const std::string_view field)
SimId assign_id_from_attribute(const std::string &owner, ObjectType type)
Generates a unique SimId based on the requested object type.
void collectIncludeElements(const XmlDocument &doc, const fs::path ¤tDir, std::vector< fs::path > &includePaths)
void parseAntenna(const XmlElement &antenna, ParserContext &ctx)
Parses an <antenna> block and adds it to the World.
void parseWaveform(const XmlElement &waveform, ParserContext &ctx)
Parses a <waveform> block and adds it to the World.
bool addIncludeFilesToMainDocument(const XmlDocument &mainDoc, const fs::path ¤tDir)
void processParsedDocument(const XmlDocument &doc, ParserContext &ctx)
Coordinates the full parsing of a validated XML document tree.
std::vector< radar::SchedulePeriod > parseSchedule(const XmlElement &parent, const std::string &parentName, const bool isPulsed, const RealType pri)
Parses a schedule (active periods) for a transmitter or receiver.
SimId resolve_reference_id(const XmlElement &element, const std::string &attributeName, const std::string &owner, const std::unordered_map< std::string, SimId > &name_map)
Resolves an XML string reference into an internal SimId.
void parseFixedRotation(const XmlElement &rotation, radar::Platform *platform, const params::RotationAngleUnit unit)
Parses a <fixedrotation> block and attaches it to a Platform.
void parseRotationPath(const XmlElement &rotation, radar::Platform *platform, const params::RotationAngleUnit unit)
Parses a <rotationpath> block and attaches it to a Platform.
radar::Transmitter * parseTransmitter(const XmlElement &transmitter, radar::Platform *platform, ParserContext &ctx, const ReferenceLookup &refs)
Parses a <transmitter> block, resolves its dependencies, and adds it to the World.
void parsePlatformElements(const XmlElement &platform, ParserContext &ctx, radar::Platform *plat, const std::function< void(const XmlElement &, std::string_view)> ®ister_name, const ReferenceLookup &refs)
Iterates and parses all children elements (radars, targets) of a platform.
void parseTiming(const XmlElement &timing, ParserContext &ctx)
Parses a <timing> block and adds the prototype timing to the World.
void parseParameters(const XmlElement ¶meters, params::Parameters ¶ms_out)
Parses the <parameters> block into the isolated context parameters.
void parsePlatform(const XmlElement &platform, ParserContext &ctx, const std::function< void(const XmlElement &, std::string_view)> ®ister_name, const ReferenceLookup &refs)
Parses a complete <platform> block, including its motion paths and sub-elements.
void parseTarget(const XmlElement &target, radar::Platform *platform, ParserContext &ctx)
Parses a <target> block and adds it to the World.
RealType get_child_real_type(const XmlElement &element, const std::string &elementName)
Extracts a floating-point (RealType) value from a named child element.
radar::Receiver * parseReceiver(const XmlElement &receiver, radar::Platform *platform, ParserContext &ctx, const ReferenceLookup &refs)
Parses a <receiver> block, resolves its dependencies, and adds it to the World.
bool get_attribute_bool(const XmlElement &element, const std::string &attributeName, const bool defaultVal)
Extracts a boolean value from a named attribute.
void validateXml(const bool didCombine, const XmlDocument &mainDoc)
Validates an XML document against the embedded DTD and XSD schemas.
void parseMotionPath(const XmlElement &motionPath, radar::Platform *platform)
Parses a <motionpath> block and attaches it to a Platform.
AssetLoaders createDefaultAssetLoaders()
Creates an AssetLoaders struct populated with standard file-I/O implementations.
void parseMonostatic(const XmlElement &monostatic, radar::Platform *platform, ParserContext &ctx, const ReferenceLookup &refs)
Parses a <monostatic> block, creating a linked transmitter and receiver pair.
std::unique_ptr< RadarSignal > loadWaveformFromFile(const std::string &name, const std::string &filename, const RealType power, const RealType carrierFreq, const SimId id)
Loads a radar waveform from a file and returns a RadarSignal object.
Provides the definition and functionality of the Path class for handling coordinate-based paths with ...
Header file for the PrototypeTiming class.
Defines the Radar class and associated functionality.
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.
uint64_t SimId
64-bit Unique Simulation ID.
ObjectType
Categorizes objects for ID generation.
Represents a position in 3D space with an associated time.
Represents a rotation in terms of azimuth, elevation, and time.
Struct to hold simulation parameters.
RealType rate
Rendering sample rate.
double origin_longitude
Geodetic origin longitude.
RealType start
Start time for the simulation.
double origin_altitude
Geodetic origin altitude (in meters)
CoordinateFrame coordinate_frame
Scenario coordinate frame.
RealType end
End time for the simulation.
int utm_zone
UTM zone (1-60), if applicable.
unsigned oversample_ratio
Oversampling ratio.
std::optional< unsigned > random_seed
Random seed for simulation.
RealType sim_sampling_rate
Temporal sampling rate (Hz) that determines time-step resolution for radar pulse simulation.
std::string simulation_name
The name of the simulation, from the XML.
RotationAngleUnit rotation_angle_unit
External rotation angle unit.
RealType c
Speed of light (modifiable)
static constexpr RealType DEFAULT_C
Speed of light (m/s)
unsigned adc_bits
ADC quantization bits.
bool utm_north_hemisphere
UTM hemisphere, if applicable.
double origin_latitude
Geodetic origin latitude.
Container for functions that load external file-backed assets.
std::function< std::unique_ptr< fers_signal::RadarSignal >(const std::string &name, const std::filesystem::path &pulse_path, RealType power, RealType carrierFreq, SimId id)> loadWaveform
Hook to load a pulsed waveform from an external file.
std::function< std::unique_ptr< radar::Target >(radar::Platform *platform, const std::string &name, const std::string &filename, unsigned seed, SimId id)> loadFileTarget
Hook to load a target's Radar Cross Section (RCS) from a file.
std::function< std::unique_ptr< antenna::Antenna >(const std::string &name, const std::string &filename, SimId id)> loadXmlAntenna
Hook to load an antenna pattern defined in a legacy XML format.
std::function< std::unique_ptr< antenna::Antenna >(const std::string &name, const std::string &filename, SimId id)> loadH5Antenna
Hook to load an antenna pattern from an HDF5 file.
Encapsulates the state required during the XML parsing process.
core::World * world
Pointer to the World where parsed objects are inserted.
std::mt19937 * master_seeder
RNG used to generate independent seeds for simulated objects.
std::filesystem::path base_dir
The directory of the main XML file (used to resolve relative asset paths).
params::Parameters parameters
An isolated copy of the simulation parameters being built.
AssetLoaders loaders
The injected asset loaders for external files.
Holds maps to resolve string names to internal SimId references during XML parsing.
const std::unordered_map< std::string, SimId > * timings
Map of timing object names to IDs.
const std::unordered_map< std::string, SimId > * waveforms
Map of waveform names to IDs.
const std::unordered_map< std::string, SimId > * antennas
Map of antenna names to IDs.
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 parsing FERS XML scenario files.