61 LinkGeometry computeLink(
const Vec3& p_from,
const Vec3& p_to)
63 const Vec3 vec = p_to - p_from;
75 return {vec / dist, dist};
88 return radar->getGain(
SVec3(direction_vec),
radar->getRotation(time), lambda);
103 const RealType numerator = tx_gain * rx_gain * lambda * lambda;
108 denominator *= dist * dist;
111 return numerator / denominator;
128 const RealType numerator = tx_gain * rx_gain * rcs * lambda * lambda;
133 denominator *= r_tx * r_tx * r_rx * r_rx;
136 return numerator / denominator;
153 const RealType delta_f = tx_timing->getFreqOffset() - rx_timing->getFreqOffset();
154 const RealType delta_phi = tx_timing->getPhaseOffset() - rx_timing->getPhaseOffset();
155 return 2 *
PI * delta_f * time + delta_phi;
164 return power_watts > noise_floor;
179 return 10.0 * std::log10(watts * 1000.0);
194 return 10.0 * std::log10(watts);
205 bool isComponentActive(
const std::vector<radar::SchedulePeriod>& schedule,
RealType time)
207 if (schedule.empty())
211 for (
const auto& period : schedule)
213 if (time >= period.start && time <= period.end)
231 const RealType t_val = time.count();
237 LinkGeometry link_tx_tgt;
239 LinkGeometry link_tgt_rx;
243 link_tx_tgt = computeLink(p_tx, p_tgt);
244 link_tgt_rx = computeLink(p_tgt, p_rx);
248 LOG(Level::FATAL,
"Transmitter or Receiver too close to Target for accurate simulation");
252 results.
delay = (link_tx_tgt.dist + link_tgt_rx.dist) /
params::c();
259 SVec3 in_angle(link_tx_tgt.u_vec);
260 SVec3 out_angle(-link_tgt_rx.u_vec);
261 const auto rcs = targ->
getRcs(in_angle, out_angle, t_val);
266 const auto tx_gain = computeAntennaGain(trans, link_tx_tgt.u_vec, t_val, wavelength);
269 const auto rx_gain = computeAntennaGain(recv, -link_tgt_rx.u_vec, results.
delay + t_val, wavelength);
271 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
273 computeReflectedPathPower(tx_gain, rx_gain, rcs, wavelength, link_tx_tgt.dist, link_tgt_rx.dist, no_loss);
281 const RealType t_val = time.count();
288 link = computeLink(p_tx, p_rx);
292 LOG(Level::FATAL,
"Transmitter or Receiver too close for accurate simulation");
305 const auto tx_gain = computeAntennaGain(trans, link.u_vec, t_val, wavelength);
306 const auto rx_gain = computeAntennaGain(recv, -link.u_vec, t_val + results.
delay, wavelength);
308 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
309 results.
power = computeDirectPathPower(tx_gain, rx_gain, wavelength, link.dist, no_loss);
330 link = computeLink(p_tx, p_rx);
343 const RealType tx_gain = computeAntennaGain(trans, link.u_vec, timeK, lambda);
345 const RealType rx_gain = computeAntennaGain(recv, -link.u_vec, timeK + tau, lambda);
347 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
348 const RealType scaling_factor = computeDirectPathPower(tx_gain, rx_gain, lambda, link.dist, no_loss);
351 const RealType amplitude = std::sqrt(signal->getPower() * scaling_factor);
354 const RealType phase = -2 *
PI * carrier_freq * tau;
355 ComplexType contribution = std::polar(amplitude, phase);
358 const RealType non_coherent_phase = computeTimingPhase(trans, recv, timeK);
359 contribution *= std::polar(1.0, non_coherent_phase);
378 LinkGeometry link_tx_tgt;
379 LinkGeometry link_tgt_rx;
383 link_tx_tgt = computeLink(p_tx, p_tgt);
384 link_tgt_rx = computeLink(p_tgt, p_rx);
397 SVec3 in_angle(link_tx_tgt.u_vec);
398 SVec3 out_angle(-link_tgt_rx.u_vec);
402 const RealType tx_gain = computeAntennaGain(trans, link_tx_tgt.u_vec, timeK, lambda);
404 const RealType rx_gain = computeAntennaGain(recv, -link_tgt_rx.u_vec, timeK + tau, lambda);
406 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
408 computeReflectedPathPower(tx_gain, rx_gain, rcs, lambda, link_tx_tgt.dist, link_tgt_rx.dist, no_loss);
411 const RealType amplitude = std::sqrt(signal->getPower() * scaling_factor);
413 const RealType phase = -2 *
PI * carrier_freq * tau;
414 ComplexType contribution = std::polar(amplitude, phase);
417 const RealType non_coherent_phase = computeTimingPhase(trans, recv, timeK);
418 contribution *= std::polar(1.0, non_coherent_phase);
434 LOG(Level::TRACE,
"Skipping direct path calculation for co-located Transmitter {} and Receiver {}",
442 if (targ !=
nullptr &&
446 "Skipping reflected path calculation for Target {} co-located with Transmitter {} or Receiver {}",
451 const auto start_time_chrono = std::chrono::duration<RealType>(startTime);
452 const auto end_time_chrono = start_time_chrono + std::chrono::duration<RealType>(signal->
getLength());
454 const int point_count =
static_cast<int>(std::ceil(signal->
getLength() / sample_time_chrono.count()));
456 if (targ && point_count == 0)
458 LOG(Level::FATAL,
"No time points are available for execution!");
459 throw std::runtime_error(
"No time points are available for execution!");
462 auto response = std::make_unique<serial::Response>(signal, trans);
466 for (
int i = 0; i <= point_count; ++i)
468 const auto current_time =
469 i < point_count ? start_time_chrono + i * sample_time_chrono : end_time_chrono;
474 solveRe(trans, recv, targ, current_time, signal, results);
482 .time = current_time.count() + results.delay,
483 .delay = results.delay,
484 .phase = results.phase};
485 response->addInterpPoint(point);
490 LOG(Level::FATAL,
"Receiver or Transmitter too close for accurate simulation");
499 std::vector<PreviewLink> links;
502 const RealType lambda_default = 0.3;
515 const RealType lambda = waveform ? (
params::c() / waveform->getCarrier()) : lambda_default;
526 const auto p_tgt = tgt->getPosition(time);
527 const Vec3 vec_tx_tgt = p_tgt - p_tx;
533 const Vec3 u_tx_tgt = vec_tx_tgt / r1;
535 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
538 const RealType p_density = (pt * gt) / (4.0 *
PI * r1 * r1);
542 .label = std::format(
"{:.1f} dBW/m\u00B2", wattsToDb(p_density)),
544 .dest_name = tgt->getName(),
545 .origin_name = tx->
getName()});
557 const bool is_monostatic = (tx->
getAttached() == rx.get());
558 const bool no_loss = rx->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
566 const auto p_tgt = tgt->getPosition(time);
570 const Vec3 vec_tx_tgt = p_tgt - p_tx;
576 const Vec3 u_tx_tgt = vec_tx_tgt / dist;
580 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
582 const RealType gr = computeAntennaGain(rx.get(), u_tx_tgt, time, lambda);
585 SVec3 in_angle(u_tx_tgt);
586 SVec3 out_angle(-u_tx_tgt);
587 const RealType rcs = tgt->getRcs(in_angle, out_angle, time);
592 computeReflectedPathPower(gt, gr, rcs, lambda, dist, dist, no_loss);
594 const RealType pr_watts = pt * power_ratio;
600 .label = std::format(
"{:.1f} dBm (RCS: {:.1f}m\u00B2)", wattsToDbm(pr_watts), rcs),
602 .dest_name = tgt->getName(),
603 .origin_name = tx->
getName()});
611 if (!rx->
checkFlag(Receiver::RecvFlag::FLAG_NODIRECT))
613 const Vec3 vec_direct = p_rx - p_tx;
618 const Vec3 u_tx_rx = vec_direct / dist;
621 const RealType gt = computeAntennaGain(tx.get(), u_tx_rx, time, lambda);
623 const RealType gr = computeAntennaGain(rx.get(), -u_tx_rx, time, lambda);
625 const RealType power_ratio = computeDirectPathPower(gt, gr, lambda, dist, no_loss);
626 const RealType pr_watts = pt * power_ratio;
630 .label = std::format(
"Direct: {:.1f} dBm", wattsToDbm(pr_watts)),
633 .origin_name = tx->
getName()});
640 const auto p_tgt = tgt->getPosition(time);
641 const Vec3 vec_tx_tgt = p_tgt - p_tx;
642 const Vec3 vec_tgt_rx = p_rx - p_tgt;
650 const Vec3 u_tx_tgt = vec_tx_tgt / r1;
651 const Vec3 u_tgt_rx = vec_tgt_rx / r2;
654 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
656 const RealType gr = computeAntennaGain(rx.get(), -u_tgt_rx, time, lambda);
659 SVec3 in_angle(u_tx_tgt);
660 SVec3 out_angle(-u_tgt_rx);
661 const RealType rcs = tgt->getRcs(in_angle, out_angle, time);
663 const RealType power_ratio = computeReflectedPathPower(gt, gr, rcs, lambda, r1, r2, no_loss);
664 const RealType pr_watts = pt * power_ratio;
673 .label = std::format(
"{:.1f} dBm", wattsToDbm(pr_watts)),
674 .source_name = tgt->getName(),
676 .origin_name = tx->
getName()});
Header for radar channel propagation and interaction models.
The World class manages the simulator environment.
const std::vector< std::unique_ptr< radar::Target > > & getTargets() const noexcept
Retrieves the list of radar targets.
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.
RealType getCarrier() const noexcept
Gets the carrier frequency of the radar signal.
RealType getLength() const noexcept
Gets the length of the radar signal.
RealType getPower() const noexcept
Gets the power of the radar signal.
A class representing a vector in spherical coordinates.
A class representing a vector in rectangular coordinates.
RealType length() const noexcept
Calculates the length (magnitude) of the vector.
const std::string & getName() const noexcept
Retrieves the name of the object.
Platform * getPlatform() const noexcept
Retrieves the associated platform of the object.
math::Vec3 getPosition(const RealType time) const
Retrieves the position of the object.
Represents a radar system on a platform.
const Radar * getAttached() const noexcept
Retrieves the attached radar object.
std::shared_ptr< timing::Timing > getTiming() const
Retrieves the timing source for the radar.
Manages radar signal reception and response processing.
bool checkFlag(RecvFlag flag) const noexcept
Checks if a specific flag is set.
const std::vector< SchedulePeriod > & getSchedule() const noexcept
Retrieves the list of active reception periods.
RealType getNoiseTemperature() const noexcept
Retrieves the noise temperature of the receiver.
Base class for radar targets.
virtual RealType getRcs(math::SVec3 &inAngle, math::SVec3 &outAngle, RealType time) const =0
Gets the RCS value for the target.
Represents a radar transmitter system.
fers_signal::RadarSignal * getSignal() const noexcept
Retrieves the radar signal currently being transmitted.
const std::vector< SchedulePeriod > & getSchedule() const noexcept
Retrieves the list of active transmission periods.
Exception thrown when a range calculation fails, typically due to objects being too close.
double RealType
Type for real numbers.
constexpr RealType EPSILON
Machine epsilon for real numbers.
std::complex< RealType > ComplexType
Type for complex numbers.
constexpr RealType PI
Mathematical constant π (pi).
Classes and operations for 3D geometry.
Defines a structure to store interpolation point data for signal processing.
Header file for the logging system.
RealType simSamplingRate() noexcept
Get the simulation sampling rate.
RealType rate() noexcept
Get the rendering sample rate.
RealType boltzmannK() noexcept
Get the Boltzmann constant.
RealType c() noexcept
Get the speed of light.
@ Weak
SNR < 0 dB (Geometric line of sight, but below noise floor)
ComplexType calculateDirectPathContribution(const Transmitter *trans, const Receiver *recv, const RealType timeK)
Calculates the complex envelope contribution for a direct propagation path (Tx -> Rx) at a specific t...
void solveReDirect(const Transmitter *trans, const Receiver *recv, const std::chrono::duration< RealType > &time, const RadarSignal *wave, ReResults &results)
Solves the radar equation for a direct path (Tx -> Rx).
void solveRe(const Transmitter *trans, const Receiver *recv, const Target *targ, const std::chrono::duration< RealType > &time, const RadarSignal *wave, ReResults &results)
Solves the bistatic radar equation for a reflected path (Tx -> Tgt -> Rx).
std::vector< PreviewLink > calculatePreviewLinks(const core::World &world, const RealType time)
Calculates all visual links for the current world state at a specific time.
std::unique_ptr< serial::Response > calculateResponse(const Transmitter *trans, const Receiver *recv, const RadarSignal *signal, const RealType startTime, const Target *targ)
Creates a Response object by simulating a signal's interaction over its duration.
ComplexType calculateReflectedPathContribution(const Transmitter *trans, const Receiver *recv, const Target *targ, const RealType timeK)
Calculates the complex envelope contribution for a reflected path (Tx -> Tgt -> Rx) at a specific tim...
@ DirectTxRx
Interference path.
@ Monostatic
Combined Tx/Rx path.
@ BistaticTgtRx
Scattered path.
@ BistaticTxTgt
Illuminator path.
Defines the Parameters struct and provides methods for managing simulation parameters.
Defines the Radar class and associated functionality.
Classes for handling radar waveforms and signals.
Radar Receiver class for managing signal reception and response handling.
Classes for managing radar signal responses.
Stores data for an interpolation point.
RealType power
Power level of the signal at the interpolation point.
Stores the intermediate results of a radar equation calculation for a single time point.
RealType delay
Signal propagation delay in seconds.
RealType power
Power scaling factor (dimensionless, relative to transmitted power).
RealType phase
Phase shift in radians due to propagation delay.
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.