kf_tracking: fuse pilot and data correlation into a single wipe-off pass

Results are bit-for-bit equivalent to the previous two-correlator
implementation, verified over 3- and 5-tap configurations with both the
normal and high-dynamics resampler paths.
This commit is contained in:
Carles Fernandez
2026-07-02 22:36:01 +02:00
parent fa96ce13a0
commit 0328dd38b6
3 changed files with 28 additions and 25 deletions
+10
View File
@@ -18,6 +18,16 @@ All notable changes to GNSS-SDR will be documented in this file.
- Improved TOW rollover handling in Telemetry Decoder blocks.
### Improvements in Efficiency:
- Fused the pilot and data-component correlations in the CPU DLL/PLL VEML
tracking block into a single carrier wipe-off pass. When tracking the pilot
signal, the data prompt is now computed as an extra correlator tap under the
same carrier rotator instead of performing a second, redundant wipe-off pass
over the same samples. This reduces tracking-loop time by about 33% (~1.5x
throughput) for pilot-tracked signals (GPS L5, Galileo E1/E5a/E5b/E6, QZSS
L5), with bit-for-bit equivalent results.
### Improvements in Interoperability:
- Added a new Signal Source implementation `Pocket_SDR_Signal_Source`, which
@@ -506,7 +506,7 @@ kf_tracking::kf_tracking(const Kf_Conf &conf_)
d_prompt_data_shift = &d_local_code_shift_chips[1];
}
d_multicorrelator_cpu.init(static_cast<int>(2 * d_trk_parameters.vector_length), d_n_correlator_taps);
d_multicorrelator_cpu.init(static_cast<int>(2 * d_trk_parameters.vector_length), d_n_correlator_taps, d_trk_parameters.track_pilot);
if (d_trk_parameters.extend_correlation_symbols > 1)
{
@@ -521,9 +521,6 @@ kf_tracking::kf_tracking(const Kf_Conf &conf_)
// Enable Data component prompt correlator (slave to Pilot prompt) if tracking uses Pilot signal
if (d_trk_parameters.track_pilot)
{
// Extra correlator for the data component
d_correlator_data_cpu.init(static_cast<int>(2 * d_trk_parameters.vector_length), 1);
d_correlator_data_cpu.set_high_dynamics_resampler(d_trk_parameters.high_dyn);
d_data_code.resize(2 * d_code_length_chips, 0.0);
}
@@ -688,7 +685,7 @@ void kf_tracking::start_tracking()
gps_l5q_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN);
gps_l5i_code_gen_float(d_data_code, d_acquisition_gnss_synchro->PRN);
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
d_correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
d_multicorrelator_cpu.set_data_code_and_prompt_tap(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
}
else
{
@@ -703,7 +700,7 @@ void kf_tracking::start_tracking()
galileo_e1_code_gen_sinboc11_float(d_tracking_code, pilot_signal, d_acquisition_gnss_synchro->PRN);
galileo_e1_code_gen_sinboc11_float(d_data_code, Signal_, d_acquisition_gnss_synchro->PRN);
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
d_correlator_data_cpu.set_local_code_and_taps(d_code_samples_per_chip * d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
d_multicorrelator_cpu.set_data_code_and_prompt_tap(d_code_samples_per_chip * d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
}
else
{
@@ -724,7 +721,7 @@ void kf_tracking::start_tracking()
d_data_code[i] = aux_code[i].real(); // the same because it is generated the full signal (E5aI + E5aQ)
}
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
d_correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
d_multicorrelator_cpu.set_data_code_and_prompt_tap(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
}
else
{
@@ -748,7 +745,7 @@ void kf_tracking::start_tracking()
d_data_code[i] = aux_code[i].real(); // the same because it is generated the full signal (E5bI + E5bsQ)
}
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
d_correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
d_multicorrelator_cpu.set_data_code_and_prompt_tap(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
}
else
{
@@ -995,10 +992,6 @@ kf_tracking::~kf_tracking()
}
try
{
if (d_trk_parameters.track_pilot)
{
d_correlator_data_cpu.free();
}
d_multicorrelator_cpu.free();
}
catch (const std::exception &ex)
@@ -1116,20 +1109,21 @@ void kf_tracking::do_correlation_step(const gr_complex *input_samples)
{
// ################# CARRIER WIPEOFF AND CORRELATORS ##############################
// perform carrier wipe-off and compute Early, Prompt and Late correlation
d_multicorrelator_cpu.set_input_output_vectors(d_correlator_outs.data(), input_samples);
d_multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler(
d_rem_carr_phase_rad,
static_cast<float>(d_carrier_phase_step_rad), static_cast<float>(d_carrier_phase_rate_step_rad),
static_cast<float>(d_rem_code_phase_chips) * static_cast<float>(d_code_samples_per_chip),
static_cast<float>(d_code_phase_step_chips) * static_cast<float>(d_code_samples_per_chip),
static_cast<float>(d_code_phase_rate_step_chips) * static_cast<float>(d_code_samples_per_chip),
d_trk_parameters.vector_length);
// DATA CORRELATOR (if tracking tracks the pilot signal)
if (d_trk_parameters.track_pilot)
{
d_correlator_data_cpu.set_input_output_vectors(d_Prompt_Data.data(), input_samples);
d_correlator_data_cpu.Carrier_wipeoff_multicorrelator_resampler(
d_multicorrelator_cpu.set_input_output_vectors(d_correlator_outs.data(), d_Prompt_Data.data(), input_samples);
d_multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler_with_data_prompt(
d_rem_carr_phase_rad,
static_cast<float>(d_carrier_phase_step_rad), static_cast<float>(d_carrier_phase_rate_step_rad),
static_cast<float>(d_rem_code_phase_chips) * static_cast<float>(d_code_samples_per_chip),
static_cast<float>(d_code_phase_step_chips) * static_cast<float>(d_code_samples_per_chip),
static_cast<float>(d_code_phase_rate_step_chips) * static_cast<float>(d_code_samples_per_chip),
d_trk_parameters.vector_length);
}
else
{
d_multicorrelator_cpu.set_input_output_vectors(d_correlator_outs.data(), input_samples);
d_multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler(
d_rem_carr_phase_rad,
static_cast<float>(d_carrier_phase_step_rad), static_cast<float>(d_carrier_phase_rate_step_rad),
static_cast<float>(d_rem_code_phase_chips) * static_cast<float>(d_code_samples_per_chip),
@@ -95,7 +95,6 @@ private:
int32_t save_matfile() const;
Cpu_Multicorrelator_Real_Codes d_multicorrelator_cpu;
Cpu_Multicorrelator_Real_Codes d_correlator_data_cpu; // for data channel
Kf_Conf d_trk_parameters;