and reloading it from the XML assistance files, which could replace a
fresher, live-decoded almanac with a stale snapshot from disk, and the
handler now uses the visible-satellite list it computed instead of
prioritizing an empty one.
Visibility-aware acquisition search (GNSS-SDR.enable_visibility_aware_search):
- Classify GLONASS and QZSS satellites too. GLONASS positions come from the
GNAV almanac (new Glonass_Gnav_Almanac::satellite_position with the
standard perturbation model), so the search order benefits before any
GLONASS ephemeris is decoded.
- PVT publishes a lock-free navigation snapshot (ephemeris, almanac, UTC
models per system) that the classifier reads instead of locking the PVT
maps on every recompute.
- Recompute on new navigation data, on position changes larger than
visibility_recompute_position_threshold_m, every
visibility_recompute_interval_s, and when the almanac ages out; fix the
periodic and position-triggered recomputes that never fired, and the
off-by-one that excluded satellites in [mask, mask+1) degrees.
- Enter the start-up standby only when the feature is enabled, so the
default search order is untouched.
Secondary-frequency acquisition assistance:
- Do not start an acquisition on the PRN 0 placeholder left on assisted
channels at connect time; it threw inside the control thread and left the
flowgraph running headless with the secondary band never acquired.
- Match GLONASS assistance by FDMA frequency channel: the search pool keeps
one slot per channel while tracked L1 channels report the decoded slot, so
L2 was never picked.
- Assist from locked channels before their telemetry is decoded: the
observables status now reports tracking-only channels and the flowgraph
keeps a separate tracking map for the assisted search.
WARMSTART used to clear ephemeris and almanac and then reload both
from local XML assistance files, which can silently regress the
receiver's live-accumulated almanac (new satellites/pages demodulated
since last start) back to whatever stale snapshot happens to be on
disk. It also never wrote anything back to disk first, so this was a
one-way loss with no merge.
Add PvtInterface::clear_ephemeris_keep_almanac(), which clears only
the ephemeris maps and leaves almanac untouched, and use it in
WARMSTART instead of clear_ephemeris() + read_assistance_from_XML().
This matches the classic cold/warm/hot start table (warm: almanac
current, ephemeris unknown/stale) using whatever almanac the receiver
already has, rather than a file that can't be any more current than
that.
Also fixes get_visible_sats()'s return value never being assigned to
visible_satellites in the WARMSTART handler, so priorize_satellites()
was always reordering the queue with an empty list.
- 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>
When acquiring a secondary frequency (e.g. Galileo E5a) of a satellite
whose primary frequency (e.g. E1) is already tracked, the primary's
Doppler can be projected onto the secondary and passed in as an
already-known estimate (GNSS-SDR.assist_dual_frequency_acq). Even so,
the acquisition still searched the full configured Doppler grid around
that estimate rather than trusting it.
Adds Acquisition_<Sig>.enable_doppler_narrowing (default false): when
the projected Doppler is passed in as exact (doppler_uncertanty == 0),
collapses the search to just that bin plus one reference bin (used as
the existing noise-power estimate, at the same separation the full
grid search already uses for its own "opposite" bin), instead of
running the full multi-bin grid. Falls back to the full grid whenever
the Doppler isn't known this precisely (single-frequency acquisition,
or dual-frequency assist disabled/unavailable).
set_doppler_uncertanty() threads through
AcquisitionInterface -> PcpsAcquisitionAdapter -> pcps_acquisition,
and Channel::assist_acquisition_doppler() gains a doppler_uncertanty
parameter (default 1, i.e. "not known precisely") so existing callers
are unaffected unless they opt in.
Also fixes max_to_input_power_statistic()'s "opposite bin" index to
wrap using its own num_doppler_bins parameter instead of the
always-full-grid d_num_doppler_bins member, which was already
inconsistent with step-two's narrower bin count and would have been
wrong for the narrowed 2-bin case introduced here.
Signed-off-by: joebre <joel.brenner@saphyrion.ch>
also adds a base implementation that most signal sources should inherit from.
The gen_signal_source is inexplicably different (probably as a test fixture,
commonality was not valued).
Only the file_signal_source has been tested; all the sources are modified in the same
way, but we all know the only proof of correctness is testing.
The block factory was simplified a bit. Handling for legacy config files was pulled out
of the flowgraph; now when the "0" instance of a component (Foo0) is created, if there is
no config for it, then the legacy version (Foo) will be tried. This is different from
passing -1 for the item number (which is still supported). Theoretically, all existing
config files should still work.
Added acquisition and tracking monitors to view intermediate outputs of
GNSS-SDR from monitoring clients. Each monitor (acquisition, tracking,
original monitor, and pvt) pushes its data to a different UDP port.
This commit enforces naming style for Classes and global constants:
Camel_Snake_Case for Classes
UPPER_CASE for global constants
CamelCase for abstract classes