FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
world.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2006-2008 Marc Brooker and Michael Inggs
4// Copyright (c) 2008-present FERS Contributors (see AUTHORS.md).
5//
6// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
7
8/**
9 * @file world.cpp
10 * @brief Implementation of the World class for the radar simulation environment.
11 */
12
13#include "world.h"
14
15#include <iomanip>
16#include <sstream>
17
19#include "core/sim_events.h"
20#include "parameters.h"
21#include "radar/radar_obj.h"
22#include "signal/radar_signal.h"
24
27using radar::Platform;
28using radar::Receiver;
29using radar::Target;
32
33namespace core
34{
35 void World::add(std::unique_ptr<Platform> plat) noexcept { _platforms.push_back(std::move(plat)); }
36
37 void World::add(std::unique_ptr<Transmitter> trans) noexcept { _transmitters.push_back(std::move(trans)); }
38
39 void World::add(std::unique_ptr<Receiver> recv) noexcept { _receivers.push_back(std::move(recv)); }
40
41 void World::add(std::unique_ptr<Target> target) noexcept { _targets.push_back(std::move(target)); }
42
43 void World::add(std::unique_ptr<RadarSignal> waveform)
44 {
45 if (_waveforms.contains(waveform->getName()))
46 {
47 throw std::runtime_error("A waveform with the name " + waveform->getName() + " already exists.");
48 }
49 _waveforms[waveform->getName()] = std::move(waveform);
50 }
51
52 void World::add(std::unique_ptr<Antenna> antenna)
53 {
54 if (_antennas.contains(antenna->getName()))
55 {
56 throw std::runtime_error("An antenna with the name " + antenna->getName() + " already exists.");
57 }
58 _antennas[antenna->getName()] = std::move(antenna);
59 }
60
61 void World::add(std::unique_ptr<PrototypeTiming> timing)
62 {
63 if (_timings.contains(timing->getName()))
64 {
65 throw std::runtime_error("A timing source with the name " + timing->getName() + " already exists.");
66 }
67 _timings[timing->getName()] = std::move(timing);
68 }
69
70 RadarSignal* World::findWaveform(const std::string& name)
71 {
72 return _waveforms.contains(name) ? _waveforms[name].get() : nullptr;
73 }
74
75 Antenna* World::findAntenna(const std::string& name)
76 {
77 return _antennas.contains(name) ? _antennas[name].get() : nullptr;
78 }
79
80 PrototypeTiming* World::findTiming(const std::string& name)
81 {
82 return _timings.contains(name) ? _timings[name].get() : nullptr;
83 }
84
85 void World::clear() noexcept
86 {
87 _platforms.clear();
88 _transmitters.clear();
89 _receivers.clear();
90 _targets.clear();
91 _waveforms.clear();
92 _antennas.clear();
93 _timings.clear();
94 _event_queue = {};
95 _simulation_state = {};
96 }
97
99 {
100 const RealType sim_start = params::startTime();
101 const RealType sim_end = params::endTime();
102
103 for (const auto& transmitter : _transmitters)
104 {
105 if (transmitter->getMode() == radar::OperationMode::PULSED_MODE)
106 {
107 // Find the first valid pulse time starting from the simulation start time.
108 if (auto start_time = transmitter->getNextPulseTime(sim_start); start_time)
109 {
110 if (*start_time <= sim_end)
111 {
112 _event_queue.push({*start_time, EventType::TX_PULSED_START, transmitter.get()});
113 }
114 }
115 }
116 else // CW_MODE
117 {
118 const auto& schedule = transmitter->getSchedule();
119 if (schedule.empty())
120 {
121 // Legacy behavior: Always on for simulation duration
122 _event_queue.push({sim_start, EventType::TX_CW_START, transmitter.get()});
123 _event_queue.push({sim_end, EventType::TX_CW_END, transmitter.get()});
124 }
125 else
126 {
127 for (const auto& period : schedule)
128 {
129 // Clip periods to simulation bounds
130 const RealType start = std::max(sim_start, period.start);
131 const RealType end = std::min(sim_end, period.end);
132
133 if (start < end)
134 {
135 _event_queue.push({start, EventType::TX_CW_START, transmitter.get()});
136 _event_queue.push({end, EventType::TX_CW_END, transmitter.get()});
137 }
138 }
139 }
140 }
141 }
142
143 for (const auto& receiver : _receivers)
144 {
145 if (receiver->getMode() == radar::OperationMode::PULSED_MODE)
146 {
147 // Schedule the first receive window checking against schedule
148 const RealType nominal_start = receiver->getWindowStart(0);
149 if (auto start = receiver->getNextWindowTime(nominal_start); start && *start < params::endTime())
150 {
151 _event_queue.push({*start, EventType::RX_PULSED_WINDOW_START, receiver.get()});
152 }
153 }
154 else // CW_MODE
155 {
156 const auto& schedule = receiver->getSchedule();
157 if (schedule.empty())
158 {
159 // Legacy behavior: Always on for simulation duration
160 _event_queue.push({params::startTime(), EventType::RX_CW_START, receiver.get()});
161 _event_queue.push({params::endTime(), EventType::RX_CW_END, receiver.get()});
162 }
163 else
164 {
165 for (const auto& period : schedule)
166 {
167 const RealType start = std::max(params::startTime(), period.start);
168 const RealType end = std::min(params::endTime(), period.end);
169 if (start < end)
170 {
171 _event_queue.push({start, EventType::RX_CW_START, receiver.get()});
172 _event_queue.push({end, EventType::RX_CW_END, receiver.get()});
173 }
174 }
175 }
176 }
177 }
178 }
179
180 std::string World::dumpEventQueue() const
181 {
182 if (_event_queue.empty())
183 {
184 return "Event Queue is empty.\n";
185 }
186
187 std::stringstream ss;
188 ss << std::fixed << std::setprecision(6);
189
190 const std::string separator = "--------------------------------------------------------------------";
191 const std::string title = "| Event Queue Contents (" + std::to_string(_event_queue.size()) + " events)";
192
193 ss << separator << "\n"
194 << std::left << std::setw(separator.length() - 1) << title << "|\n"
195 << separator << "\n"
196 << "| " << std::left << std::setw(12) << "Timestamp" << " | " << std::setw(21) << "Event Type" << " | "
197 << std::setw(25) << "Source Object" << " |\n"
198 << separator << "\n";
199
200 auto queue_copy = _event_queue;
201
202 while (!queue_copy.empty())
203 {
204 const auto [timestamp, event_type, source_object] = queue_copy.top();
205 queue_copy.pop();
206
207 ss << "| " << std::right << std::setw(12) << timestamp << " | " << std::left << std::setw(21)
208 << toString(event_type) << " | " << std::left << std::setw(25) << source_object->getName() << " |\n";
209 }
210 ss << separator << "\n";
211
212 return ss.str();
213 }
214}
Header file defining various types of antennas and their gain patterns.
Abstract base class representing an antenna.
void scheduleInitialEvents()
Populates the event queue with the initial events for the simulation.
Definition world.cpp:98
timing::PrototypeTiming * findTiming(const std::string &name)
Finds a timing source by name.
Definition world.cpp:80
void add(std::unique_ptr< radar::Platform > plat) noexcept
Adds a radar platform to the simulation world.
Definition world.cpp:35
antenna::Antenna * findAntenna(const std::string &name)
Finds an antenna by name.
Definition world.cpp:75
fers_signal::RadarSignal * findWaveform(const std::string &name)
Finds a radar signal by name.
Definition world.cpp:70
void clear() noexcept
Clears all objects and assets from the simulation world.
Definition world.cpp:85
std::string dumpEventQueue() const
Dumps the current state of the event queue to a string for debugging.
Definition world.cpp:180
Class representing a radar signal with associated properties.
Represents a simulation platform with motion and rotation paths.
Definition platform.h:31
Manages radar signal reception and response processing.
Definition receiver.h:36
Base class for radar targets.
Definition target.h:117
Represents a radar transmitter system.
Definition transmitter.h:32
Manages timing properties such as frequency, offsets, and synchronization.
double RealType
Type for real numbers.
Definition config.h:27
std::string toString(const EventType type)
Converts an EventType enum to its string representation.
Definition sim_events.h:72
@ RX_PULSED_WINDOW_START
A pulsed receiver opens its listening window.
@ TX_CW_START
A continuous-wave transmitter starts transmitting.
@ TX_CW_END
A continuous-wave transmitter stops transmitting.
@ TX_PULSED_START
A pulsed transmitter begins emitting a pulse.
@ RX_CW_END
A continuous-wave receiver stops listening.
@ RX_CW_START
A continuous-wave receiver starts listening.
RealType endTime() noexcept
Get the end time for the simulation.
Definition parameters.h:97
RealType startTime() noexcept
Get the start time for the simulation.
Definition parameters.h:91
@ PULSED_MODE
The component operates in a pulsed mode.
Defines the Parameters struct and provides methods for managing simulation parameters.
Header file for the PrototypeTiming class.
Defines the Radar class and associated functionality.
Classes for handling radar waveforms and signals.
Defines the core structures for the event-driven simulation engine.
Header file for the World class in the simulator.