Description
There is a fundamental error in the physical modeling of how noise is applied to the signal in the receiver's final rendering stage. The function serial::exportReceiverBinary combines the rendered radar signal, thermal noise, and local oscillator (LO) phase noise in a physically incorrect order.
Current Behavior
The implementation in serial/receiver_export.cpp follows this sequence:
- An empty data window is created.
- Thermal Noise is added to the empty window (
addNoiseToWindow).
- The radar signal (from targets/clutter) is rendered and added to the window containing the thermal noise (
renderWindow).
- The combined
(Signal + ThermalNoise) result is multiplied by the LO phase noise (addPhaseNoiseToWindow).
This corresponds to the incorrect physical model: Output = (Signal + ThermalNoise) * PhaseNoise.
Expected Behavior
The signal chain in a real receiver dictates a different order of operations:
- The radar signal arrives at the receiver front-end.
- During down-conversion, the signal is multiplied by the local oscillator's signal, which includes its phase noise. The model for this is
Signal * PhaseNoise.
- Additive white Gaussian noise (AWGN), primarily from the Low Noise Amplifier (LNA) and other front-end components, is introduced. This thermal noise is added to the signal.
The correct physical model is: Output = (Signal * PhaseNoise) + ThermalNoise.
Impact
This is a critical modeling error. The current implementation incorrectly applies a time-varying phase rotation to the thermal noise. This has the non-physical effect of modulating the thermal noise, which will:
- Artificially spread the spectrum of the noise floor.
- Result in an incorrect final signal-to-noise ratio (SNR) in the baseband data.
- Make any analysis of Doppler performance, receiver sensitivity, or system noise figure fundamentally unreliable.
Code Evidence
- File:
serial/receiver_export.cpp
- Function:
exportReceiverBinary
- Sequence of Calls:
// ...
std::vector<ComplexType> window(size);
addNoiseToWindow(window, recv->getNoiseTemperature()); // 1. Thermal noise ADDED to empty window
renderWindow(window, length, start, frac_delay, responses, pool); // 2. Signal ADDED to window
// ...
if (pn_enabled) { addPhaseNoiseToWindow(pnoise, window); } // 3. Phase noise MULTIPLIED with (Signal + ThermalNoise)
// ...
Proposed Solution
The fix requires reordering the operations within exportReceiverBinary to match the correct physical model.
-
Refactor exportReceiverBinary:
Change the sequence of operations in the function to the following:
// file: serial/receiver_export.cpp
void exportReceiverBinary(...)
{
// ... (setup code remains the same) ...
for (unsigned i = 0; i < window_count; ++i)
{
auto pnoise = generatePhaseNoise(recv, size, rate, carrier, pn_enabled);
// ... (time and delay calculation remains the same) ...
// --- START REORDERING ---
// 1. Create a clean window and render the signal into it.
std::vector<ComplexType> window(size); // Starts as all zeros
renderWindow(window, length, start, frac_delay, responses, pool);
// 2. Downsample if necessary (acts on signal only).
if (params::oversampleRatio() > 1) {
window = std::move(signal::downsample(window));
}
// 3. Apply multiplicative LO phase noise to the signal.
if (pn_enabled) {
addPhaseNoiseToWindow(pnoise, window);
}
// 4. Apply additive thermal noise to the (Signal * PhaseNoise) result.
addNoiseToWindow(window, recv->getNoiseTemperature());
// 5. Quantize the final result. This is correct.
const RealType fullscale = quantizeWindow(window);
// --- END REORDERING ---
// ... (HDF5 export code remains the same) ...
}
}
-
(Optional) Improve Code Clarity:
To prevent future confusion, consider renaming addNoiseToWindow to addThermalNoise to make its purpose explicit. This is a minor change but improves long-term code maintainability.
Description
There is a fundamental error in the physical modeling of how noise is applied to the signal in the receiver's final rendering stage. The function
serial::exportReceiverBinarycombines the rendered radar signal, thermal noise, and local oscillator (LO) phase noise in a physically incorrect order.Current Behavior
The implementation in
serial/receiver_export.cppfollows this sequence:addNoiseToWindow).renderWindow).(Signal + ThermalNoise)result is multiplied by the LO phase noise (addPhaseNoiseToWindow).This corresponds to the incorrect physical model:
Output = (Signal + ThermalNoise) * PhaseNoise.Expected Behavior
The signal chain in a real receiver dictates a different order of operations:
Signal * PhaseNoise.The correct physical model is:
Output = (Signal * PhaseNoise) + ThermalNoise.Impact
This is a critical modeling error. The current implementation incorrectly applies a time-varying phase rotation to the thermal noise. This has the non-physical effect of modulating the thermal noise, which will:
Code Evidence
serial/receiver_export.cppexportReceiverBinaryProposed Solution
The fix requires reordering the operations within
exportReceiverBinaryto match the correct physical model.Refactor
exportReceiverBinary:Change the sequence of operations in the function to the following:
(Optional) Improve Code Clarity:
To prevent future confusion, consider renaming
addNoiseToWindowtoaddThermalNoiseto make its purpose explicit. This is a minor change but improves long-term code maintainability.