11#include <highfive/highfive.hpp>
32 if ((timing_model ==
nullptr) || !timing_model->
isEnabled())
49 timing_model->
reset();
50 const auto skip_samples =
static_cast<long long>(std::floor(rate * receiver->
getWindowSkip()));
53 timing_model->
skipSamples(
static_cast<std::size_t
>(skip_samples));
59 const auto samples_to_skip =
static_cast<long long>(std::floor(rate * inter_pulse_skip_duration));
60 if (samples_to_skip > 0)
62 timing_model->
skipSamples(
static_cast<std::size_t
>(samples_to_skip));
70 const RealType actual_start = ideal_start + first_phase_noise / (2.0 *
PI * carrier_freq);
71 const RealType rounded_start = std::round(actual_start * rate) / rate;
72 const RealType fractional_delay = actual_start * rate - std::round(actual_start * rate);
73 return {rounded_start, fractional_delay};
77 const radar::Receiver* receiver,
const std::vector<radar::Transmitter*>& cw_sources,
78 const std::vector<std::unique_ptr<radar::Target>>* targets)
81 for (
auto& window_sample : window)
84 for (
const auto* cw_source : cw_sources)
88 cw_interference_sample +=
91 for (
const auto& target_ptr : *targets)
93 cw_interference_sample +=
97 window_sample += cw_interference_sample;
103 const std::vector<std::unique_ptr<serial::Response>>& interference_log)
105 for (
const auto& response : interference_log)
109 const auto rendered_pulse = response->renderBinary(prate, psize, 0.0);
111 const RealType dt_sim = 1.0 / prate;
112 const auto start_index =
static_cast<size_t>((response->startTime() -
params::startTime()) / dt_sim);
114 for (
size_t i = 0; i < psize; ++i)
116 if (start_index + i < iq_buffer.size())
118 iq_buffer[start_index + i] += rendered_pulse[i];
126 for (
auto [n, w] : std::views::zip(
noise, window))
128 w *= std::polar(1.0, n);
141 void exportCwToHdf5(
const std::string& filename,
const std::vector<ComplexType>& iq_buffer,
147 HighFive::File file(filename, HighFive::File::Truncate);
149 std::vector<RealType> i_data(iq_buffer.size());
150 std::vector<RealType> q_data(iq_buffer.size());
151 std::ranges::transform(iq_buffer, i_data.begin(), [](
const auto& c) { return c.real(); });
152 std::ranges::transform(iq_buffer, q_data.begin(), [](
const auto& c) { return c.imag(); });
154 HighFive::DataSet i_dataset = file.createDataSet<
RealType>(
"I_data", HighFive::DataSpace::From(i_data));
155 i_dataset.write(i_data);
156 HighFive::DataSet q_dataset = file.createDataSet<
RealType>(
"Q_data", HighFive::DataSpace::From(q_data));
157 q_dataset.write(q_data);
161 file.createAttribute(
"fullscale", fullscale);
162 file.createAttribute(
"reference_carrier_frequency", ref_freq);
163 if (metadata !=
nullptr)
170 catch (
const HighFive::Exception& err)
Header for radar channel propagation and interaction models.
Manages radar signal reception and response processing.
bool checkFlag(RecvFlag flag) const noexcept
Checks if a specific flag is set.
RealType getWindowPrf() const noexcept
Retrieves the pulse repetition frequency (PRF) of the radar window.
RealType getWindowSkip() const noexcept
Retrieves the window skip time.
RealType getWindowLength() const noexcept
Retrieves the radar window length.
Represents a timing source for simulation.
void reset() noexcept
Resets the timing model.
void skipSamples(std::size_t samples) noexcept
Skips a number of samples in the timing model.
bool getSyncOnPulse() const noexcept
Checks if the timing source synchronizes on pulse.
bool isEnabled() const noexcept
Checks if the timing source is enabled.
double RealType
Type for real numbers.
std::complex< RealType > ComplexType
Type for complex numbers.
constexpr RealType PI
Mathematical constant π (pi).
Header file for Digital Signal Processing (DSP) filters and upsampling/downsampling functionality.
Declares focused, testable pipeline steps for receiver finalization.
Header file for HDF5 data export and import functions.
Header file for the logging system.
std::vector< ComplexType > downsample(std::span< const ComplexType > in)
Downsamples a signal by a given ratio.
@ FATAL
Fatal level for severe error events.
@ INFO
Info level for informational messages.
RealType rate() noexcept
Get the rendering sample rate.
RealType startTime() noexcept
Get the start time for the simulation.
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
void addPhaseNoiseToWindow(std::span< const RealType > noise, std::span< ComplexType > window)
Applies a pre-generated sequence of phase noise samples to an I/Q buffer.
RealType applyDownsamplingAndQuantization(std::vector< ComplexType > &buffer)
Downsamples and quantizes an IQ buffer.
void advanceTimingModel(timing::Timing *timing_model, const radar::Receiver *receiver, const RealType rate)
Advances the receiver's timing model to the start of the next processing window.
void exportCwToHdf5(const std::string &filename, const std::vector< ComplexType > &iq_buffer, const RealType fullscale, const RealType ref_freq, const core::OutputFileMetadata *metadata)
Exports a finalized continuous-wave IQ buffer to an HDF5 file.
std::tuple< RealType, RealType > calculateJitteredStart(const RealType ideal_start, const RealType first_phase_noise, const RealType carrier_freq, const RealType rate)
Calculates the jittered start time and fractional delay from a phase noise sample.
void applyPulsedInterference(std::vector< ComplexType > &iq_buffer, const std::vector< std::unique_ptr< serial::Response > > &interference_log)
Renders and applies pulsed interference to a continuous-wave IQ buffer.
void applyCwInterference(std::span< ComplexType > window, const RealType actual_start, const RealType dt, const radar::Receiver *receiver, const std::vector< radar::Transmitter * > &cw_sources, const std::vector< std::unique_ptr< radar::Target > > *targets)
Applies continuous-wave interference to a time window.
RealType quantizeAndScaleWindow(std::span< ComplexType > window)
Simulates ADC quantization and scales a window of complex I/Q samples.
std::mutex hdf5_global_mutex
Global mutex to protect all HDF5 C-library calls, which are not thread-safe.
void writeOutputFileMetadataAttributes(HighFive::File &file, const core::OutputFileMetadata &metadata)
Writes additive FERS output metadata attributes to an open HDF5 file.
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...
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...
Defines the Parameters struct and provides methods for managing simulation parameters.
Radar Receiver class for managing signal reception and response handling.
Classes for managing radar signal responses.
Header for receiver-side signal processing and rendering.
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.