FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
finalizer_pipeline.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 finalizer_pipeline.h
9 * @brief Declares focused, testable pipeline steps for receiver finalization.
10 *
11 * This header defines the individual, single-responsibility functions that
12 * constitute the signal processing pipeline for both pulsed and continuous-wave
13 * receivers. By breaking the finalization process into these discrete steps,
14 * each function becomes highly cohesive, easier to understand, and independently
15 * testable.
16 */
17
18#pragma once
19
20#include <memory>
21#include <span>
22#include <string>
23#include <tuple>
24#include <vector>
25
26#include "core/config.h"
27
28namespace timing
29{
30 class Timing;
31}
32namespace radar
33{
34 class Receiver;
35 class Transmitter;
36 class Target;
37}
38namespace serial
39{
40 class Response;
41}
42namespace core
43{
44 struct OutputFileMetadata;
45}
46
48{
49 /**
50 * @brief Advances the receiver's timing model to the start of the next processing window.
51 *
52 * This function handles the "dead time" between receive windows. For sync-on-pulse
53 * models, it resets the phase and skips to the window's start offset. For
54 * free-running models, it skips the number of samples corresponding to the
55 * inter-pulse period.
56 *
57 * @param timing_model The stateful timing model instance to advance.
58 * @param receiver The receiver whose properties (sync mode, PRF, etc.) determine how to advance the model.
59 * @param rate The oversampled simulation rate, used to calculate samples to skip.
60 */
61 void advanceTimingModel(timing::Timing* timing_model, const radar::Receiver* receiver, RealType rate);
62
63 /**
64 * @brief Calculates the jittered start time and fractional delay from a phase noise sample.
65 *
66 * Converts the first phase noise sample (in radians) of a window into a time
67 * jitter offset. It then decomposes the resulting "actual" start time into a
68 * component aligned with the sample clock and a fractional delay to be handled
69 * by the rendering engine's interpolation filter.
70 *
71 * @param ideal_start The perfect, jitter-free start time of the window.
72 * @param first_phase_noise The first phase noise sample (radians) for this window.
73 * @param carrier_freq The carrier frequency, needed to convert phase to time.
74 * @param rate The sampling rate, used for sample clock alignment.
75 * @return A tuple containing:
76 * 1. The sample-aligned start time (RealType).
77 * 2. The fractional sample delay (RealType).
78 */
79 std::tuple<RealType, RealType> calculateJitteredStart(RealType ideal_start, RealType first_phase_noise,
80 RealType carrier_freq, RealType rate);
81
82 /**
83 * @brief Applies continuous-wave interference to a time window.
84 *
85 * Iterates through each sample of a processing window, calculating the combined
86 * direct and reflected path contributions from all active CW sources at that
87 * precise moment in time. The resulting complex sample is added to the window.
88 *
89 * @param window The I/Q buffer for the receive window to which interference will be added.
90 * @param actual_start The jittered, sample-aligned start time of the window.
91 * @param dt The time step between samples (1.0 / rate).
92 * @param receiver The receiver being interfered with.
93 * @param cw_sources A list of currently active CW transmitters.
94 * @param targets The list of all targets for calculating reflected paths.
95 */
96 void applyCwInterference(std::span<ComplexType> window, RealType actual_start, RealType dt,
97 const radar::Receiver* receiver, const std::vector<radar::Transmitter*>& cw_sources,
98 const std::vector<std::unique_ptr<radar::Target>>* targets);
99
100 /**
101 * @brief Renders and applies pulsed interference to a continuous-wave IQ buffer.
102 *
103 * Processes a log of `Response` objects that represent pulsed signals received
104 * during a CW receiver's operation. Each response is rendered into a temporary
105 * buffer and then added to the main CW IQ buffer at the correct time offset.
106 *
107 * @param iq_buffer The main, simulation-long IQ buffer for the CW receiver.
108 * @param interference_log A list of `Response` objects representing the pulsed interference.
109 */
110 void applyPulsedInterference(std::vector<ComplexType>& iq_buffer,
111 const std::vector<std::unique_ptr<serial::Response>>& interference_log);
112
113 /**
114 * @brief Applies a pre-generated sequence of phase noise samples to an I/Q buffer.
115 *
116 * This function performs the complex multiplication `IQ_out = IQ_in * e^(j*phase_noise)`
117 * for each sample in the window, effectively modulating the phase of the signal.
118 *
119 * @param noise A span of phase noise samples in radians.
120 * @param window The I/Q buffer to be modified.
121 */
122 void addPhaseNoiseToWindow(std::span<const RealType> noise, std::span<ComplexType> window);
123
124 /**
125 * @brief Downsamples and quantizes an IQ buffer.
126 *
127 * This function performs the final processing steps. If oversampling is enabled,
128 * it first downsamples the buffer to the final output rate. It then simulates
129 * an ADC by quantizing and scaling the data.
130 *
131 * @param buffer The I/Q buffer to be processed. This is an in-out parameter; it will
132 * be replaced by the downsampled buffer if applicable.
133 * @return The full-scale value (RealType) calculated during quantization, which is
134 * needed for HDF5 metadata.
135 */
136 RealType applyDownsamplingAndQuantization(std::vector<ComplexType>& buffer);
137
138 /**
139 * @brief Exports a finalized continuous-wave IQ buffer to an HDF5 file.
140 *
141 * Creates an HDF5 file, splits the complex buffer into real (I) and imaginary (Q)
142 * components, writes them as separate datasets, and adds relevant simulation
143 * parameters (sample rate, start time, etc.) as file attributes.
144 *
145 * @param filename The path to the output HDF5 file.
146 * @param iq_buffer The final, processed I/Q data to write.
147 * @param fullscale The full-scale value from quantization, saved as metadata.
148 * @param ref_freq The reference carrier frequency, saved as metadata.
149 */
150 void exportCwToHdf5(const std::string& filename, const std::vector<ComplexType>& iq_buffer, RealType fullscale,
151 RealType ref_freq, const core::OutputFileMetadata* metadata = nullptr);
152}
Manages radar signal reception and response processing.
Definition receiver.h:37
Represents a timing source for simulation.
Definition timing.h:36
Global configuration file for the project.
double RealType
Type for real numbers.
Definition config.h:27
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.