FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
xml_parser_utils.h
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
7/**
8 * @file xml_parser_utils.h
9 * @brief Core utility layer for parsing FERS XML scenario files.
10 *
11 * This file provides the internal mechanisms and data structures required to parse
12 * individual XML elements into their corresponding simulation objects. It defines
13 * a context-driven parsing approach, separating the extraction of XML data from
14 * the global simulation state and managing external file dependencies through
15 * function hooks.
16 */
17
18#pragma once
19
20#include <cstdint>
21#include <filesystem>
22#include <functional>
23#include <memory>
24#include <random>
25#include <string>
26#include <unordered_map>
27#include <vector>
28
29#include "core/parameters.h"
30#include "core/sim_id.h"
33
34// Forward declarations to minimize include dependencies
35namespace antenna
36{
37 class Antenna;
38}
39namespace fers_signal
40{
41 enum class FileWaveformKind : std::uint8_t;
42 class RadarSignal;
43}
44namespace timing
45{
46 class Timing;
47}
48namespace radar
49{
50 class Receiver;
51 class Target;
52 class Transmitter;
53 class Platform;
54}
55namespace core
56{
57 class World;
58}
59
61{
62 /**
63 * @struct ReferenceLookup
64 * @brief Holds maps to resolve string names to internal SimId references during XML parsing.
65 *
66 * XML documents often cross-reference entities by name (e.g., a transmitter references
67 * an antenna by its string name). This struct provides the lookup tables needed to link
68 * these entities using their generated `SimId`.
69 */
71 {
72 const std::unordered_map<std::string, SimId>* waveforms; ///< Map of waveform names to IDs.
73 const std::unordered_map<std::string, SimId>* antennas; ///< Map of antenna names to IDs.
74 const std::unordered_map<std::string, SimId>* timings; ///< Map of timing object names to IDs.
75 };
76
77 /**
78 * @struct AssetLoaders
79 * @brief Container for functions that load external file-backed assets.
80 *
81 * Asset loading operations (such as reading waveforms, antenna patterns, and target
82 * RCS data from disk) are delegated to these `std::function` hooks. This allows
83 * the parser to flexibly resolve external file references during the XML parsing phase.
84 */
86 {
87 /// Hook to load a mode-tagged waveform from an external file.
88 std::function<std::unique_ptr<fers_signal::RadarSignal>(
89 const std::string& name, const std::filesystem::path& waveform_path, RealType power, RealType carrierFreq,
92
93 /// Hook to load an antenna pattern defined in a legacy XML format.
94 std::function<std::unique_ptr<antenna::Antenna>(const std::string& name, const std::string& filename, SimId id)>
96
97 /// Hook to load an antenna pattern from an HDF5 file.
98 std::function<std::unique_ptr<antenna::Antenna>(const std::string& name, const std::string& filename, SimId id)>
100
101 /// Hook to load a target's Radar Cross Section (RCS) from a file.
102 std::function<std::unique_ptr<radar::Target>(radar::Platform* platform, const std::string& name,
103 const std::string& filename, unsigned seed, SimId id)>
105 };
106
107 /**
108 * @struct ParserContext
109 * @brief Encapsulates the state required during the XML parsing process.
110 *
111 * This context object holds the intermediate simulation parameters, a pointer to
112 * the simulation world, the base directory for resolving relative paths, the
113 * master random number generator, and the asset loading hooks. It is passed
114 * through the parsing functions to aggregate the scenario definition.
115 */
117 {
118 params::Parameters parameters; ///< An isolated copy of the simulation parameters being built.
119 core::World* world = nullptr; ///< Pointer to the World where parsed objects are inserted.
120 std::filesystem::path base_dir; ///< The directory of the main XML file (used to resolve relative asset paths).
121 std::mt19937* master_seeder = nullptr; ///< RNG used to generate independent seeds for simulated objects.
122 AssetLoaders loaders; ///< The injected asset loaders for external files.
123 std::unordered_map<SimId, std::shared_ptr<timing::Timing>>
124 timing_instances; ///< Shared timing instances keyed by prototype ID.
125 };
126
127 /**
128 * @brief Extracts a floating-point (RealType) value from a named child element.
129 * @param element The parent XML element.
130 * @param elementName The name of the child element to extract text from.
131 * @return The parsed floating-point value.
132 * @throws XmlException if the child element is missing or empty.
133 */
134 RealType get_child_real_type(const XmlElement& element, const std::string& elementName);
135
136 /**
137 * @brief Extracts a boolean value from a named attribute.
138 * @param element The XML element containing the attribute.
139 * @param attributeName The name of the attribute.
140 * @param defaultVal The value to return if the attribute is missing or invalid.
141 * @return The parsed boolean value, or the default if the attribute is missing or invalid.
142 */
143 bool get_attribute_bool(const XmlElement& element, const std::string& attributeName, bool defaultVal);
144
145 /**
146 * @brief Generates a unique SimId based on the requested object type.
147 * @param owner The name/description of the object requesting the ID (used for logging).
148 * @param type The category/type of the object.
149 * @return A newly generated SimId.
150 */
151 SimId assign_id_from_attribute(const std::string& owner, ObjectType type);
152
153 /**
154 * @brief Resolves an XML string reference into an internal SimId.
155 * @param element The XML element containing the string reference attribute.
156 * @param attributeName The name of the attribute containing the reference string.
157 * @param owner A description of the object making the reference (used for error messages).
158 * @param name_map The lookup table mapping string names to SimIds.
159 * @return The resolved SimId.
160 * @throws XmlException if the reference cannot be resolved or is missing.
161 */
162 SimId resolve_reference_id(const XmlElement& element, const std::string& attributeName, const std::string& owner,
163 const std::unordered_map<std::string, SimId>& name_map);
164
165 /**
166 * @brief Parses a schedule (active periods) for a transmitter or receiver.
167 * @param parent The parent XML element that might contain a `<schedule>` block.
168 * @param parentName Name of the parent for error logging.
169 * @param isPulsed True if the owning object operates in pulsed mode (used for PRI validation).
170 * @param pri The pulse repetition interval, if applicable.
171 * @return A vector of parsed and validated `SchedulePeriod` objects.
172 */
173 std::vector<radar::SchedulePeriod> parseSchedule(const XmlElement& parent, const std::string& parentName,
174 bool isPulsed, RealType pri = 0.0);
175
176 /**
177 * @brief Parses the `<parameters>` block into the isolated context parameters.
178 * @param parameters The `<parameters>` XML element.
179 * @param params_out The `Parameters` struct to mutate with parsed values.
180 */
182
183 /**
184 * @brief Parses a `<waveform>` block and adds it to the World.
185 * @param waveform The `<waveform>` XML element.
186 * @param ctx The current parser context.
187 */
188 void parseWaveform(const XmlElement& waveform, ParserContext& ctx);
189
190 /**
191 * @brief Parses a `<timing>` block and adds the prototype timing to the World.
192 * @param timing The `<timing>` XML element.
193 * @param ctx The current parser context.
194 */
196
197 /**
198 * @brief Parses an `<antenna>` block and adds it to the World.
199 * @param antenna The `<antenna>` XML element.
200 * @param ctx The current parser context.
201 */
203
204 /**
205 * @brief Parses a `<motionpath>` block and attaches it to a Platform.
206 * @param motionPath The `<motionpath>` XML element.
207 * @param platform The platform to modify.
208 */
210
211 /**
212 * @brief Parses a `<rotationpath>` block and attaches it to a Platform.
213 * @param rotation The `<rotationpath>` XML element.
214 * @param platform The platform to modify.
215 */
217
218 /**
219 * @brief Parses a `<fixedrotation>` block and attaches it to a Platform.
220 * @param rotation The `<fixedrotation>` XML element.
221 * @param platform The platform to modify.
222 */
224
225 /**
226 * @brief Parses a `<transmitter>` block, resolves its dependencies, and adds it to the World.
227 * @param transmitter The `<transmitter>` XML element.
228 * @param platform The platform this transmitter belongs to.
229 * @param ctx The current parser context.
230 * @param refs Lookup tables for resolving waveform, antenna, and timing references.
231 * @return A pointer to the newly created Transmitter object.
232 */
234 const ReferenceLookup& refs);
235
236 /**
237 * @brief Parses a `<receiver>` block, resolves its dependencies, and adds it to the World.
238 * @param receiver The `<receiver>` XML element.
239 * @param platform The platform this receiver belongs to.
240 * @param ctx The current parser context.
241 * @param refs Lookup tables for resolving antenna and timing references.
242 * @return A pointer to the newly created Receiver object.
243 */
245 const ReferenceLookup& refs);
246
247 /**
248 * @brief Parses a `<monostatic>` block, creating a linked transmitter and receiver pair.
249 * @param monostatic The `<monostatic>` XML element.
250 * @param platform The platform this radar belongs to.
251 * @param ctx The current parser context.
252 * @param refs Lookup tables for resolving references.
253 */
255 const ReferenceLookup& refs);
256
257 /**
258 * @brief Parses a `<target>` block and adds it to the World.
259 * @param target The `<target>` XML element.
260 * @param platform The platform this target belongs to.
261 * @param ctx The current parser context.
262 */
264
265 /**
266 * @brief Iterates and parses all children elements (radars, targets) of a platform.
267 * @param platform The `<platform>` XML element.
268 * @param ctx The current parser context.
269 * @param plat The Platform object to attach parsed elements to.
270 * @param register_name Callback used to ensure unique naming globally across parsed objects.
271 * @param refs Lookup tables for resolving references.
272 */
274 const std::function<void(const XmlElement&, std::string_view)>& register_name,
275 const ReferenceLookup& refs);
276
277 /**
278 * @brief Parses a complete `<platform>` block, including its motion paths and sub-elements.
279 * @param platform The `<platform>` XML element.
280 * @param ctx The current parser context.
281 * @param register_name Callback used to ensure unique naming.
282 * @param refs Lookup tables for resolving references.
283 */
285 const std::function<void(const XmlElement&, std::string_view)>& register_name,
286 const ReferenceLookup& refs);
287
288 /**
289 * @brief Recursively finds all `<include>` tags in a document and resolves their absolute paths.
290 * @param doc The XML document to search.
291 * @param currentDir The base directory for resolving relative paths.
292 * @param includePaths A vector populated with the absolute paths of included files.
293 */
294 void collectIncludeElements(const XmlDocument& doc, const std::filesystem::path& currentDir,
295 std::vector<std::filesystem::path>& includePaths);
296
297 /**
298 * @brief Resolves and merges all `<include>` files directly into the provided main document.
299 * @param mainDoc The primary XML document that will be mutated.
300 * @param currentDir The base directory used to resolve include paths.
301 * @return True if at least one file was included and merged, false otherwise.
302 */
303 bool addIncludeFilesToMainDocument(const XmlDocument& mainDoc, const std::filesystem::path& currentDir);
304
305 /**
306 * @brief Validates an XML document against the embedded DTD and XSD schemas.
307 * @param didCombine Flag indicating whether the document contains merged includes (used for formatting log
308 * messages).
309 * @param mainDoc The XML document to validate.
310 * @throws XmlException if validation fails.
311 */
312 void validateXml(bool didCombine, const XmlDocument& mainDoc);
313
314 /**
315 * @brief Coordinates the full parsing of a validated XML document tree.
316 *
317 * This is the root parsing function that iterates over parameters, waveforms, timings,
318 * antennas, and platforms. It populates the World in the proper order and triggers
319 * initial event scheduling.
320 *
321 * @param doc The parsed XML document tree.
322 * @param ctx The parser context containing the World, isolated parameters, and asset loaders.
323 */
325
326 /**
327 * @brief Creates an `AssetLoaders` struct populated with standard file-I/O implementations.
328 *
329 * Provides the default hooks to load actual HDF5, XML, and binary waveform files
330 * from the filesystem into the simulation environment.
331 *
332 * @return An `AssetLoaders` instance with standard file handlers attached.
333 */
335}
const Transmitter & transmitter
const Receiver & receiver
Class for managing XML documents.
Class representing a node in an XML document.
The World class manages the simulator environment.
Definition world.h:39
Represents a simulation platform with motion and rotation paths.
Definition platform.h:32
Manages radar signal reception and response processing.
Definition receiver.h:47
Represents a radar transmitter system.
Definition transmitter.h:34
double RealType
Type for real numbers.
Definition config.h:27
Wrapper for managing XML documents and elements using libxml2.
FileWaveformKind
Simulation mode assigned to samples loaded from a waveform file.
RotationAngleUnit
Defines the units used at external rotation-path boundaries.
Definition parameters.h:42
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 &currentDir, 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 &currentDir)
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)> &register_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 &parameters, params::Parameters &params_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)> &register_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.
Defines the Parameters struct and provides methods for managing simulation parameters.
uint64_t SimId
64-bit Unique Simulation ID.
Definition sim_id.h:18
ObjectType
Categorizes objects for ID generation.
Definition sim_id.h:25
math::Vec3 max
Struct to hold simulation parameters.
Definition parameters.h:52
Container for functions that load external file-backed assets.
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< fers_signal::RadarSignal >(const std::string &name, const std::filesystem::path &waveform_path, RealType power, RealType carrierFreq, SimId id, fers_signal::FileWaveformKind kind)> loadWaveform
Hook to load a mode-tagged waveform from an external 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::unordered_map< SimId, std::shared_ptr< timing::Timing > > timing_instances
Shared timing instances keyed by prototype ID.
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.