-
Notifications
You must be signed in to change notification settings - Fork 1
Description
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 renamingaddNoiseToWindowtoaddThermalNoiseto make its purpose explicit. This is a minor change but improves long-term code maintainability.