62 LinkGeometry computeLink(
const Vec3& p_from,
const Vec3& p_to)
64 const Vec3 vec = p_to - p_from;
76 return {vec / dist, dist};
89 return radar->getGain(
SVec3(direction_vec),
radar->getRotation(time), lambda);
104 const RealType numerator = tx_gain * rx_gain * lambda * lambda;
109 denominator *= dist * dist;
112 return numerator / denominator;
129 const RealType numerator = tx_gain * rx_gain * rcs * lambda * lambda;
134 denominator *= r_tx * r_tx * r_rx * r_rx;
137 return numerator / denominator;
154 const RealType delta_f = tx_timing->getFreqOffset() - rx_timing->getFreqOffset();
155 const RealType delta_phi = tx_timing->getPhaseOffset() - rx_timing->getPhaseOffset();
156 return 2 *
PI * delta_f * time + delta_phi;
165 return power_watts > noise_floor;
180 return 10.0 * std::log10(watts * 1000.0);
195 return 10.0 * std::log10(watts);
206 bool isComponentActive(
const std::vector<radar::SchedulePeriod>& schedule,
RealType time)
208 if (schedule.empty())
212 for (
const auto& period : schedule)
214 if (time >= period.start && time <= period.end)
232 const RealType t_val = time.count();
238 LinkGeometry link_tx_tgt;
240 LinkGeometry link_tgt_rx;
244 link_tx_tgt = computeLink(p_tx, p_tgt);
245 link_tgt_rx = computeLink(p_tgt, p_rx);
249 LOG(Level::INFO,
"Transmitter or Receiver too close to Target for accurate simulation");
253 results.
delay = (link_tx_tgt.dist + link_tgt_rx.dist) /
params::c();
260 SVec3 in_angle(link_tx_tgt.u_vec);
261 SVec3 out_angle(-link_tgt_rx.u_vec);
262 const auto rcs = targ->
getRcs(in_angle, out_angle, t_val);
267 const auto tx_gain = computeAntennaGain(trans, link_tx_tgt.u_vec, t_val, wavelength);
270 const auto rx_gain = computeAntennaGain(recv, -link_tgt_rx.u_vec, results.
delay + t_val, wavelength);
272 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
274 computeReflectedPathPower(tx_gain, rx_gain, rcs, wavelength, link_tx_tgt.dist, link_tgt_rx.dist, no_loss);
282 const RealType t_val = time.count();
289 link = computeLink(p_tx, p_rx);
293 LOG(Level::INFO,
"Transmitter or Receiver too close for accurate simulation");
306 const auto tx_gain = computeAntennaGain(trans, link.u_vec, t_val, wavelength);
307 const auto rx_gain = computeAntennaGain(recv, -link.u_vec, t_val + results.
delay, wavelength);
309 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
310 results.
power = computeDirectPathPower(tx_gain, rx_gain, wavelength, link.dist, no_loss);
331 link = computeLink(p_tx, p_rx);
344 const RealType tx_gain = computeAntennaGain(trans, link.u_vec, timeK, lambda);
346 const RealType rx_gain = computeAntennaGain(recv, -link.u_vec, timeK + tau, lambda);
348 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
349 const RealType scaling_factor = computeDirectPathPower(tx_gain, rx_gain, lambda, link.dist, no_loss);
352 const RealType amplitude = std::sqrt(signal->getPower() * scaling_factor);
355 const RealType phase = -2 *
PI * carrier_freq * tau;
356 ComplexType contribution = std::polar(amplitude, phase);
359 const RealType non_coherent_phase = computeTimingPhase(trans, recv, timeK);
360 contribution *= std::polar(1.0, non_coherent_phase);
379 LinkGeometry link_tx_tgt;
380 LinkGeometry link_tgt_rx;
384 link_tx_tgt = computeLink(p_tx, p_tgt);
385 link_tgt_rx = computeLink(p_tgt, p_rx);
398 SVec3 in_angle(link_tx_tgt.u_vec);
399 SVec3 out_angle(-link_tgt_rx.u_vec);
403 const RealType tx_gain = computeAntennaGain(trans, link_tx_tgt.u_vec, timeK, lambda);
405 const RealType rx_gain = computeAntennaGain(recv, -link_tgt_rx.u_vec, timeK + tau, lambda);
407 const bool no_loss = recv->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
409 computeReflectedPathPower(tx_gain, rx_gain, rcs, lambda, link_tx_tgt.dist, link_tgt_rx.dist, no_loss);
412 const RealType amplitude = std::sqrt(signal->getPower() * scaling_factor);
414 const RealType phase = -2 *
PI * carrier_freq * tau;
415 ComplexType contribution = std::polar(amplitude, phase);
418 const RealType non_coherent_phase = computeTimingPhase(trans, recv, timeK);
419 contribution *= std::polar(1.0, non_coherent_phase);
441 if (targ !=
nullptr &&
445 "Skipping reflected path calculation for Target {} co-located with Transmitter {} or Receiver {}",
450 const auto start_time_chrono = std::chrono::duration<RealType>(startTime);
451 const auto end_time_chrono = start_time_chrono + std::chrono::duration<RealType>(signal->
getLength());
453 const int point_count =
static_cast<int>(std::ceil(signal->
getLength() / sample_time_chrono.count()));
455 if ((targ !=
nullptr) && point_count == 0)
457 LOG(Level::FATAL,
"No time points are available for execution!");
458 throw std::runtime_error(
"No time points are available for execution!");
461 auto response = std::make_unique<serial::Response>(signal, trans);
465 for (
int i = 0; i <= point_count; ++i)
467 const auto current_time =
468 i < point_count ? start_time_chrono + i * sample_time_chrono : end_time_chrono;
473 solveRe(trans, recv, targ, current_time, signal, results);
481 .time = current_time.count() + results.delay,
482 .delay = results.delay,
483 .phase = results.phase};
484 response->addInterpPoint(point);
489 LOG(Level::INFO,
"Receiver or Transmitter too close for accurate simulation");
498 std::vector<PreviewLink> links;
501 const RealType lambda_default = 0.3;
514 const RealType lambda = (waveform !=
nullptr) ? (
params::c() / waveform->getCarrier()) : lambda_default;
525 const auto p_tgt = tgt->getPosition(time);
526 const Vec3 vec_tx_tgt = p_tgt - p_tx;
532 const Vec3 u_tx_tgt = vec_tx_tgt / r1;
534 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
537 const RealType p_density = (pt * gt) / (4.0 *
PI * r1 * r1);
541 .label = std::format(
"{:.1f} dBW/m\u00B2", wattsToDb(p_density)),
542 .source_id = tx->
getId(),
543 .dest_id = tgt->getId(),
544 .origin_id = tx->
getId()});
556 const bool is_monostatic = (tx->
getAttached() == rx.get());
557 const bool no_loss = rx->
checkFlag(Receiver::RecvFlag::FLAG_NOPROPLOSS);
565 const auto p_tgt = tgt->getPosition(time);
569 const Vec3 vec_tx_tgt = p_tgt - p_tx;
575 const Vec3 u_tx_tgt = vec_tx_tgt / dist;
579 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
581 const RealType gr = computeAntennaGain(rx.get(), u_tx_tgt, time, lambda);
584 SVec3 in_angle(u_tx_tgt);
585 SVec3 out_angle(-u_tx_tgt);
586 const RealType rcs = tgt->getRcs(in_angle, out_angle, time);
591 computeReflectedPathPower(gt, gr, rcs, lambda, dist, dist, no_loss);
593 const RealType pr_watts = pt * power_ratio;
599 .label = std::format(
"{:.1f} dBm (RCS: {:.1f}m\u00B2)", wattsToDbm(pr_watts), rcs),
600 .source_id = tx->
getId(),
601 .dest_id = tgt->getId(),
602 .origin_id = tx->
getId()});
610 if (!rx->
checkFlag(Receiver::RecvFlag::FLAG_NODIRECT))
612 const Vec3 vec_direct = p_rx - p_tx;
617 const Vec3 u_tx_rx = vec_direct / dist;
620 const RealType gt = computeAntennaGain(tx.get(), u_tx_rx, time, lambda);
622 const RealType gr = computeAntennaGain(rx.get(), -u_tx_rx, time, lambda);
624 const RealType power_ratio = computeDirectPathPower(gt, gr, lambda, dist, no_loss);
625 const RealType pr_watts = pt * power_ratio;
629 .label = std::format(
"Direct: {:.1f} dBm", wattsToDbm(pr_watts)),
630 .source_id = tx->
getId(),
631 .dest_id = rx->
getId(),
632 .origin_id = tx->
getId()});
639 const auto p_tgt = tgt->getPosition(time);
640 const Vec3 vec_tx_tgt = p_tgt - p_tx;
641 const Vec3 vec_tgt_rx = p_rx - p_tgt;
649 const Vec3 u_tx_tgt = vec_tx_tgt / r1;
650 const Vec3 u_tgt_rx = vec_tgt_rx / r2;
653 const RealType gt = computeAntennaGain(tx.get(), u_tx_tgt, time, lambda);
655 const RealType gr = computeAntennaGain(rx.get(), -u_tgt_rx, time, lambda);
658 SVec3 in_angle(u_tx_tgt);
659 SVec3 out_angle(-u_tgt_rx);
660 const RealType rcs = tgt->getRcs(in_angle, out_angle, time);
662 const RealType power_ratio = computeReflectedPathPower(gt, gr, rcs, lambda, r1, r2, no_loss);
663 const RealType pr_watts = pt * power_ratio;
672 .label = std::format(
"{:.1f} dBm", wattsToDbm(pr_watts)),
673 .source_id = tgt->getId(),
674 .dest_id = rx->
getId(),
675 .origin_id = tx->
getId()});
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.
SimId getId() const noexcept
Retrieves the unique ID of the receiver.
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.
SimId getId() const noexcept
Retrieves the unique ID of the transmitter.
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.