Files
joebre 8f67752b9e Address review: memory safety, candidate selection, PFA, dump, naming
- Rename doppler_uncertanty -> doppler_uncertainty throughout (interface,
  adapter, block, comments, log message).

- Fix the out-of-bounds write and mis-detection in narrowed-mode
  activation: track it with an explicit d_doppler_search_narrowed flag,
  set directly in set_doppler_uncertainty() and guarded on
  d_num_doppler_bins > 1, instead of inferring it from
  "d_num_doppler_bins_active < d_num_doppler_bins". That inferred check
  broke two ways: for a 1-bin full grid (a valid, already-accepted
  config), it still forced 2 active bins, writing past the grid/wipeoff
  allocations sized to d_num_doppler_bins; for a 2-bin full grid, an
  actually-narrowed request computes the same active count as the full
  grid (2 < 2 is false), so it silently searched the full grid's own
  bin layout instead of the assisted {center, center + doppler_max}
  pair. Reproduced the out-of-bounds write directly (temporarily
  reverting to the inferred check crashes with "corrupted double-linked
  list" under the new NarrowingEnabledOneBinGrid test) and the
  mis-detection (NarrowingEnabledTwoBinGrid).

- Keep the noise-reference bin out of candidate selection: both
  max_to_input_power_statistic() and first_vs_second_peak_statistic()
  now take a separate candidate_count, used only for the peak-search
  loop bound; the CFAR path's own num_doppler_bins (used for the
  "opposite bin" reference lookup) is unchanged. In narrowed mode,
  candidate_count is 1 -- the noise-reference bin can no longer win and
  be reported as the acquisition result, regardless of its own power
  (verified against a live signal deliberately placed in the reference
  bin instead of the known/candidate bin: reverting this fix, both the
  CFAR and peak-ratio statistic mistakenly report the reference bin's
  Doppler as if it were the assisted center).

- Recalibrate the acceptance threshold for narrowed acquisition: adds
  d_threshold_narrowed, computed like d_threshold but with
  num_doppler_bins = 1 (the true candidate count in narrowed mode)
  instead of the full grid's bin count, since compute_threshold() folds
  the candidate count into the false-alarm probability and reusing the
  full-grid threshold in narrowed mode was effectively far stricter
  than the requested PFA. get_threshold() returns it whenever
  d_doppler_search_narrowed is true.

- Fix narrowed dump layout/metadata: ensure_dump_grid_allocated() now
  sizes acq_grid to d_num_doppler_bins_active (not the full grid width),
  matching what copy_magnitude_grid_to_dump_grid() actually writes each
  cycle -- this also makes narrow<->full transitions between dumps
  self-correcting. dump_results() writes accurate, mode-appropriate
  doppler_max/doppler_step (the same {0, doppler_max} encoding
  compute_statistics() uses internally when narrowed), plus new
  doppler_center and doppler_narrowed fields so offline post-processing
  can tell which encoding is in effect. Verified end to end against a
  live dump (NarrowedDumpMetadata).

- Strengthen Acq_Conf::enable_doppler_narrowing's doc comment (default,
  which implementations it applies to, its dependency on the caller
  passing doppler_uncertainty == 0) and add a commented usage example
  next to GNSS-SDR.assist_dual_frequency_acq in a dual-frequency
  Galileo E1B+E5a example config.

- Add tests/.../pcps_acquisition_doppler_narrowing_test.cc: 8 focused
  tests (narrowing enabled/disabled, 1-bin and 2-bin full-grid
  configurations, CFAR and peak-ratio statistics, a full-narrow-full
  transition, two-step acquisition with step-1 narrowing, and narrowed
  dump metadata), built on the same real-capture/known-ground-truth
  pattern as gps_l1_ca_pcps_acquisition_test.cc. Confirmed each targeted
  regression test actually fails without its corresponding fix before
  finalizing them.

Signed-off-by: joebre <joel.brenner@saphyrion.ch>
2026-08-31 09:38:13 +02:00

351 lines
10 KiB
Plaintext

; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2020 (see AUTHORS file for a list of contributors)
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=9937500
GNSS-SDR.telecommand_enabled=true
GNSS-SDR.telecommand_tcp_port=3333
GNSS-SDR.osnma_enable=false
; Once a satellite's primary frequency (here, Galileo E1B) is tracked, project its
; Doppler onto the secondary frequency (E5a) and pass it to that channel's
; acquisition as an already-known estimate, instead of acquiring E5a cold.
; GNSS-SDR.assist_dual_frequency_acq=true
;######### SUPL RRLP GPS assistance configuration #####
; Check https://www.mcc-mnc.com/
; On Android: https://play.google.com/store/apps/details?id=net.its_here.cellidinfo&hl=en
GNSS-SDR.SUPL_gps_enabled=false
GNSS-SDR.SUPL_read_gps_assistance_xml=true
GNSS-SDR.SUPL_gps_ephemeris_server=supl.google.com
GNSS-SDR.SUPL_gps_ephemeris_port=7275
GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com
GNSS-SDR.SUPL_gps_acquisition_port=7275
GNSS-SDR.SUPL_MCC=244
GNSS-SDR.SUPL_MNC=5
GNSS-SDR.SUPL_LAC=0x59e2
GNSS-SDR.SUPL_CI=0x31b0
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=NTLab_File_Signal_Source
SignalSource.filename=ntlab.bin ; <- PUT YOUR FILE HERE
SignalSource.sampling_frequency=79500000
SignalSource.sample_type=real
SignalSource.item_type=byte
SignalSource.RF_channels=4
SignalSource.dump=false
;######### SIGNAL_CONDITIONER CONFIG ############
; RF CHANNEL 0
SignalConditioner0.implementation=Signal_Conditioner
; RF CHANNEL 1
SignalConditioner1.implementation=Signal_Conditioner
; RF CHANNEL 2
SignalConditioner2.implementation=Signal_Conditioner
; RF CHANNEL 3
SignalConditioner3.implementation=Signal_Conditioner
;######### DATA_TYPE_ADAPTER CONFIG ############
; RF CHANNEL 0
DataTypeAdapter0.implementation=Pass_Through
DataTypeAdapter0.item_type=float
DataTypeAdapter0.inverted_spectrum=true
; RF CHANNEL 1
DataTypeAdapter1.implementation=Pass_Through
DataTypeAdapter1.item_type=float
; RF CHANNEL 2
DataTypeAdapter2.implementation=Pass_Through
DataTypeAdapter2.item_type=float
DataTypeAdapter2.inverted_spectrum=true
; RF CHANNEL 3
DataTypeAdapter3.implementation=Pass_Through
DataTypeAdapter3.item_type=float
;######### INPUT_FILTER CONFIG ############
; RF CHANNEL 0
InputFilter0.implementation=Freq_Xlating_Fir_Filter
InputFilter0.dump=false
InputFilter0.input_item_type=float
InputFilter0.output_item_type=gr_complex
InputFilter0.taps_item_type=float
InputFilter0.number_of_taps=5
InputFilter0.number_of_bands=2
InputFilter0.band1_begin=0.0
InputFilter0.band1_end=0.45
InputFilter0.band2_begin=0.55
InputFilter0.band2_end=1.0
InputFilter0.ampl1_begin=1.0
InputFilter0.ampl1_end=1.0
InputFilter0.ampl2_begin=0.0
InputFilter0.ampl2_end=0.0
InputFilter0.band1_error=1.0
InputFilter0.band2_error=1.0
InputFilter0.filter_type=bandpass
InputFilter0.grid_density=16
InputFilter0.sampling_frequency=79500000
InputFilter0.IF=14580000
InputFilter0.decimation_factor=8
; RF CHANNEL 1
InputFilter1.implementation=Freq_Xlating_Fir_Filter
InputFilter1.dump=false
InputFilter1.input_item_type=float
InputFilter1.output_item_type=gr_complex
InputFilter1.taps_item_type=float
InputFilter1.number_of_taps=5
InputFilter1.number_of_bands=2
InputFilter1.band1_begin=0.0
InputFilter1.band1_end=0.45
InputFilter1.band2_begin=0.55
InputFilter1.band2_end=1.0
InputFilter1.ampl1_begin=1.0
InputFilter1.ampl1_end=1.0
InputFilter1.ampl2_begin=0.0
InputFilter1.ampl2_end=0.0
InputFilter1.band1_error=1.0
InputFilter1.band2_error=1.0
InputFilter1.filter_type=bandpass
InputFilter1.grid_density=16
InputFilter1.sampling_frequency=79500000
InputFilter1.IF=0
InputFilter1.decimation_factor=8
; RF CHANNEL 2
InputFilter2.implementation=Freq_Xlating_Fir_Filter
InputFilter2.dump=false
InputFilter2.input_item_type=float
InputFilter2.output_item_type=gr_complex
InputFilter2.taps_item_type=float
InputFilter2.number_of_taps=5
InputFilter2.number_of_bands=2
InputFilter2.band1_begin=0.0
InputFilter2.band1_end=0.45
InputFilter2.band2_begin=0.55
InputFilter2.band2_end=1.0
InputFilter2.ampl1_begin=1.0
InputFilter2.ampl1_end=1.0
InputFilter2.ampl2_begin=0.0
InputFilter2.ampl2_end=0.0
InputFilter2.band1_error=1.0
InputFilter2.band2_error=1.0
InputFilter2.filter_type=bandpass
InputFilter2.grid_density=16
InputFilter2.sampling_frequency=79500000
InputFilter2.IF=23550000
InputFilter2.decimation_factor=8
; RF CHANNEL 3
InputFilter3.implementation=Freq_Xlating_Fir_Filter
InputFilter3.dump=false
InputFilter3.input_item_type=float
InputFilter3.output_item_type=gr_complex
InputFilter3.taps_item_type=float
InputFilter3.number_of_taps=5
InputFilter3.number_of_bands=2
InputFilter3.band1_begin=0.0
InputFilter3.band1_end=0.45
InputFilter3.band2_begin=0.55
InputFilter3.band2_end=1.0
InputFilter3.ampl1_begin=1.0
InputFilter3.ampl1_end=1.0
InputFilter3.ampl2_begin=0.0
InputFilter3.ampl2_end=0.0
InputFilter3.band1_error=1.0
InputFilter3.band2_error=1.0
InputFilter3.filter_type=bandpass
InputFilter3.grid_density=16
InputFilter3.sampling_frequency=79500000
InputFilter3.IF=27600000
InputFilter3.decimation_factor=8
;######### RESAMPLER CONFIG ############
; RF CHANNEL 0
Resampler0.implementation=Pass_Through
Resampler0.item_type=gr_complex
; RF CHANNEL 1
Resampler1.implementation=Pass_Through
Resampler1.item_type=gr_complex
; RF CHANNEL 2
Resampler2.implementation=Pass_Through
Resampler2.item_type=gr_complex
; RF CHANNEL 3
Resampler3.implementation=Pass_Through
Resampler3.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels.in_acquisition=1
Channels_1C.count=8 ;# GPS L1
Channels_L5.count=8 ;# GPS L5
Channels_2S.count=8 ;# GPS L2C
Channels_1B.count=8 ;# Galileo E1b
Channels_5X.count=8 ;# Galileo E5a
Channels_B1.count=8 ;# Beidou B1I
; RF CHANNEL MAPPING
Channels_1C.RF_channel_ID=0
Channels_L5.RF_channel_ID=2
Channels_2S.RF_channel_ID=3
Channels_1B.RF_channel_ID=0
Channels_5X.RF_channel_ID=2
Channels_B1.RF_channel_ID=0
;######### ACQUISITION CONFIG ############
;# GPS L1
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=2
Acquisition_1C.doppler_max=5000
Acquisition_1C.doppler_step=125
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
;# GPS L5
Acquisition_L5.implementation=GPS_L5i_PCPS_Acquisition
Acquisition_L5.item_type=gr_complex
Acquisition_L5.threshold=2
Acquisition_L5.doppler_max=5000
Acquisition_L5.doppler_step=125
Acquisition_L5.dump=false
;# GPS L2C
Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S.item_type=gr_complex
Acquisition_2S.threshold=2
Acquisition_2S.doppler_max=5000
Acquisition_2S.doppler_step=150
Acquisition_2S.dump=false
;# Galileo E1b
Acquisition_1B.implementation=Galileo_E1_PCPS_Ambiguous_Acquisition
Acquisition_1B.item_type=gr_complex
Acquisition_1B.threshold=2
Acquisition_1B.doppler_max=5000
Acquisition_1B.doppler_step=125
Acquisition_1B.dump=false
;# Galileo E5a
Acquisition_5X.implementation=Galileo_E5a_Pcps_Acquisition
Acquisition_5X.item_type=gr_complex
Acquisition_5X.threshold=2
Acquisition_5X.doppler_max=5000
Acquisition_5X.doppler_step=125
Acquisition_5X.dump=false
; Only takes effect together with GNSS-SDR.assist_dual_frequency_acq above: collapses
; this (secondary-frequency) acquisition's Doppler search to the E1B-projected bin
; instead of the full +-5000 Hz grid.
; Acquisition_5X.enable_doppler_narrowing=true
;# Beidou B1
Acquisition_B1.implementation=BEIDOU_B1I_PCPS_Acquisition
Acquisition_B1.item_type=gr_complex
Acquisition_B1.threshold=2
Acquisition_B1.doppler_max=5000
Acquisition_B1.doppler_step=150
Acquisition_B1.dump=false
;######### TRACKING CONFIG ############
;# GPS L1
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.dump=false
Tracking_1C.dump_mat=false
;# GPS L5
Tracking_L5.implementation=GPS_L5_DLL_PLL_Tracking
Tracking_L5.item_type=gr_complex
Tracking_L5.dump=false
Tracking_L5.dump_mat=false
;# GPS L2C
Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S.item_type=gr_complex
Tracking_2S.dump=false
Tracking_2S.dump_mat=false
;# Galileo E1b
Tracking_1B.implementation=Galileo_E1_DLL_PLL_VEML_Tracking
Tracking_1B.item_type=gr_complex
Tracking_1B.dump=false
Tracking_1B.dump_mat=false
;# Galileo E5a
Tracking_5X.implementation=Galileo_E5a_DLL_PLL_Tracking
Tracking_5X.item_type=gr_complex
Tracking_5X.dump=false
Tracking_5X.dump_mat=false
;# Beidou B1
Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking
Tracking_B1.item_type=gr_complex
Tracking_B1.dump=false
Tracking_B1.dump_mat=false
;######### TELEMETRY DECODER CONFIG ############
;# GPS L1
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.dump_mat=false
;# GPS L5
TelemetryDecoder_L5.implementation=GPS_L5_Telemetry_Decoder
TelemetryDecoder_L5.dump=false
TelemetryDecoder_L5.dump_mat=false
;# GPS L2C
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=false
TelemetryDecoder_2S.dump_mat=false
;# Galileo E1b
TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B.dump_mat=false
;# Galileo E5a
TelemetryDecoder_5X.implementation=Galileo_E5a_Telemetry_Decoder
TelemetryDecoder_5X.dump=false
TelemetryDecoder_5X.dump_mat=false
;# Beidou B1
TelemetryDecoder_B1.implementation=BEIDOU_B1I_Telemetry_Decoder
TelemetryDecoder_B1.dump=false
TelemetryDecoder_B1.dump_mat=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single;PPP_Kinematic;PPP_Static;
PVT.output_rate_ms=500
PVT.display_rate_ms=500
PVT.iono_model=Broadcast;Iono-Free-LC;
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_output_enabled=true
PVT.rinexobs_rate_ms=1000
PVT.enable_monitor=true
PVT.monitor_client_addresses=127.0.0.1
PVT.monitor_udp_port=0101
PVT.flag_nmea_tty_port=true
PVT.nmea_dump_devname=/dev/pts/12
PVT.nmea_output_file_enabled=true
PVT.enable_rx_clock_correction=false
PVT.elevation_mask=5
PVT.dump=true
PVT.dump_mat=false
;######### MONITOR CONFIG ############
Monitor.enable_monitor=false
Monitor.decimator_factor=50
Monitor.client_addresses=127.0.0.1
Monitor.udp_port=0101