From f278cc9dc812fa6faba6ad33fbc0301558a8c5de Mon Sep 17 00:00:00 2001 From: joebre Date: Fri, 28 Aug 2026 16:53:35 +0200 Subject: [PATCH] Add full_grid_search option to acquisition Previously, the (possibly still noisy, partially non-coherently accumulated) grid was checked against threshold after every single dwell, and the first bin anywhere to cross it won immediately -- even if a later dwell's fuller integration would have revealed a different, genuinely stronger peak elsewhere in the same grid that never got the chance to be compared. Adds Acquisition_.full_grid_search (default false, preserving the existing early-exit behavior): when true, the accept/reject decision is deferred until the final dwell, from the fully max_dwells- accumulated grid, instead of exiting on the first dwell whose still-partial accumulation happens to cross threshold. Combined with the frequency-error reduction scan, this addresses a recurring Galileo E1-B loss-of-lock failure mode: measured over 30 trials against a live capture, enabling full_grid_search alone still left 26/30 trials with at least one loss-of-lock event (66 total events); adding the frequency-error scan on top brought that down to 4/30 trials (5 total events). Signed-off-by: joebre --- .../gnuradio_blocks/pcps_acquisition.cc | 44 +++++++++++++++---- src/algorithms/acquisition/libs/acq_conf.cc | 1 + src/algorithms/acquisition/libs/acq_conf.h | 8 ++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index d1c97b2c0..d839b1855 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -842,19 +842,47 @@ void pcps_acquisition::acquisition_core(uint64_t sample_count) if (!d_acq_parameters.bit_transition_flag) { - if (result.test_statistics > get_threshold()) + if (d_acq_parameters.full_grid_search) { - handle_threshold_reached(result); + // Search the entire acquisition grid (accumulate through the full max_dwells) + // before deciding accept/reject, instead of exiting as soon as any single dwell's + // (possibly still noisy, partially non-coherently accumulated) grid crosses + // threshold -- a later dwell's fuller integration can reveal a different, genuinely + // stronger peak elsewhere in the same grid that an early exit never gets the chance + // to compare against. + if (d_num_noncoherent_integrations_counter == d_acq_parameters.max_dwells) + { + if (result.test_statistics > get_threshold()) + { + handle_threshold_reached(result); + } + else + { + handle_integration_done(result); + } + } + else + { + d_buffer_count = 0; + d_state = 1; + } } else { - d_buffer_count = 0; - d_state = 1; - } + if (result.test_statistics > get_threshold()) + { + handle_threshold_reached(result); + } + else + { + d_buffer_count = 0; + d_state = 1; + } - if (d_num_noncoherent_integrations_counter == d_acq_parameters.max_dwells) - { - handle_integration_done(result); + if (d_num_noncoherent_integrations_counter == d_acq_parameters.max_dwells) + { + handle_integration_done(result); + } } } else diff --git a/src/algorithms/acquisition/libs/acq_conf.cc b/src/algorithms/acquisition/libs/acq_conf.cc index aeaa11b49..30adaa17c 100644 --- a/src/algorithms/acquisition/libs/acq_conf.cc +++ b/src/algorithms/acquisition/libs/acq_conf.cc @@ -83,6 +83,7 @@ void Acq_Conf::SetFromConfiguration(const ConfigurationInterface *configuration, make_2_steps = configuration->property(role + ".make_two_steps", make_2_steps); blocking_on_standby = configuration->property(role + ".blocking_on_standby", blocking_on_standby); enable_doppler_narrowing = configuration->property(role + ".enable_doppler_narrowing", enable_doppler_narrowing); + full_grid_search = configuration->property(role + ".full_grid_search", full_grid_search); if (pfa <= 0.0) { diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h index 62d100809..b54a9a771 100644 --- a/src/algorithms/acquisition/libs/acq_conf.h +++ b/src/algorithms/acquisition/libs/acq_conf.h @@ -92,6 +92,14 @@ public: // flag has no effect and the full configured Doppler grid is always searched. bool enable_doppler_narrowing{false}; + // Accumulate through the full max_dwells before deciding accept/reject, instead + // of exiting as soon as any single dwell's (possibly still noisy, partially + // accumulated) grid crosses threshold -- a later dwell's fuller integration can + // reveal a different, genuinely stronger peak elsewhere in the grid that an early + // exit never gets the chance to compare against. Opt-in: off by default, enable + // per-implementation in the .conf (e.g. Acquisition_1B.full_grid_search = true). + bool full_grid_search{false}; + // Specific to some implementations bool acquire_pilot{false}; bool acquire_iq{false};