rescode() (rtklib_pntpos.cc) computes each satellite's azimuth/elevation via
satazel() before checking it against PVT.elevation_mask, and pntpos() copies
that azel into ssat[] unconditionally -- only ssat[].vs is gated by the mask
(the same applies to a satellite dropped by RAIM FDE). The used_satellites
loop in rtklib_solver.cc was keying its entire per-satellite entry on vs, so
a tracked satellite excluded from the fix (below the elevation mask, or by
RAIM) disappeared from MonitorPvt entirely -- indistinguishable from a
genuine tracking problem.
Key entries on whether azel was actually computed this epoch instead, and
add a separate `used` flag (default true) reflecting vs. A satellite that
is tracked but excluded from the fix now still reports its real az/el, with
used = false.
An application monitoring gnss-sdr (e.g. for a sky plot or a per-satellite
status view) typically needs to know which satellites and signals actually
contributed to the current PVT solution, and their azimuth/elevation --
none of that is currently exposed on the MonitorPvt UDP interface, only the
scalar solution.
Adds a repeated UsedSatellite field to MonitorPvt (proto field 37), one
entry per satellite/signal used in the fix: PRN, constellation, signal ID,
azimuth, elevation, and whether that satellite's signals were combined
(e.g. Galileo E1+E5a iono-free). Signals are kept as separate entries
rather than merged into one per-satellite record, since a receiver may
track more than one signal of the same satellite independently and a
consumer may care which ones specifically contributed.
Populated in Rtklib_Solver::get_PVT() from RTKLIB's per-satellite azel
solution (pvt_ssat[]) intersected with the observables actually used in
that epoch.
Signed-off-by: joebre <joel.brenner@saphyrion.ch>
Add a Bladerf_Signal_Source that streams RX samples directly from
bladeRF front-ends (bladeRF x40, x115, and bladeRF 2.0 Micro xA4/xA9)
through libbladeRF, instead of going through the generic gr-osmosdr
wrapper. gr-osmosdr's bladerf backend does not expose usable per-stage
gain control on bladeRF2 hardware and has no support for the RX bias
tee used to power an active antenna on the 2.0 Micro.
The new gr::sync_block (bladerf_source) talks to libbladeRF's
synchronous streaming API directly; the adapter (BladerfSignalSource)
follows the existing SignalSourceBase pattern used by the other signal
sources, with valve and dump support wired the same way. Building it
is gated behind -DENABLE_BLADERF=ON, degrades gracefully when
libbladeRF is absent, and requires libbladeRF v2.6.0 or newer,
enforced at configure time.
Verified against a physical bladeRF 2.0 Micro: the receiver opens the
device, streams live samples, and acquires and tracks real GPS
satellites end to end using the new sample configuration file.
Only single-channel (SISO) reception is supported for now; the second
RX channel is not yet exposed.
Signed-off-by: Oleksandr Suvorov <cryosay@gmail.com>
GTEST_SKIP() does not exist before GoogleTest 1.10, which breaks the
build on Ubuntu 16.04 with the distro-provided GoogleTest. Wrap it in
a guarded macro that records a success and returns on older versions,
following the pattern already used in osnma_test_vectors.cc.¡
Compensate the Viterbi traceback delay when timestamping decoded SBAS
messages by carrying per-sample reception timestamps through the sample
and symbol aligners (removes a ~140 ms bias), with a deterministic unit
test covering the FIFO pairing.
Protect decoder state with d_setlock in reset(), set_satellite(),
set_channel() and general_work(), following the convention of the other
telemetry decoders.
Share per-PRN EMS dump files through a per-run dump session: the first
open in a run truncates stale data, later opens append, so channel
reassignments no longer wipe previously decoded messages.
Extend the QZSS L1 C/A LNAV treatment to the L5 CNAV chain: the QZSS-
configured L5 telemetry decoder now publishes dedicated Qzss_CNAV_Iono
and Qzss_CNAV_Utc_Model objects instead of the shared GPS CNAV types,
and PVT keeps them in their own Rtklib_Solver members.
- RINEX 4.02 navigation files get "> STO J CNVX" QZUT records with the
UTC(NICT) identifier and "> ION J CNVX WIDE" Klobuchar records. The
WIDE subtype, compulsory for the QZSS CNVX ION message type, is
correct because CNAV Message Type 30 broadcasts the Wide Area
coefficient set (IS-QZSS-PNT-006; the Japan area set of Message Type
61 is not decoded).
- QZSS CNAV parameters no longer overwrite the GPS CNAV ones in mixed
configurations.
- The QZSS slots of the RTKLIB navigation structure take the LNAV
values with CNAV as fallback, and QZSS-only configurations keep
feeding the broadcast ionospheric model and the leap second count.
- The XML storage output gains qzss_cnav_utc_model.xml and
qzss_cnav_iono.xml.
The Klobuchar coefficients and the UTC(NICT) offset broadcast by QZSS
satellites in LNAV subframe 4 (both the wide-area and Japan-area pages)
were stored in the shared GPS structures, overwriting the GPS-sourced
values in mixed GPS + QZSS configurations and making it impossible to
label them correctly in RINEX output.
New Qzss_Utc_Model and Qzss_Iono storage classes are now published by
the QZSS-configured L1 C/A telemetry decoder and kept in dedicated
Rtklib_Solver members. With this in place:
- RINEX 4.02 navigation files get "> STO J LNAV" QZUT records with the
UTC(NICT) identifier and "> ION J LNAV" Klobuchar records, and the
LEAP SECONDS header is updated from QZSS data in QZSS-only setups.
- QZSS-sourced parameters are no longer mislabeled as GPS corrections
(GPUT / GPS ION or TIME SYSTEM CORR / IONOSPHERIC CORR lines).
- The QZSS slots of the RTKLIB navigation structure (utc_qzs, ion_qzs)
are now populated; QZSS-only configurations keep feeding the broadcast
ionospheric model and the leap second count as before.
- The XML storage output gains qzss_utc_model.xml and qzss_iono.xml.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Activated by setting PVT.rinex_version=4 in the configuration file (or
with the -RINEX_version=4.02 command-line flag). The default behavior
when the parameter is not set remains unchanged (RINEX 3.02).
Observation files are generated in the 4.02 version format. Navigation
files use the data record structure introduced in RINEX 4.00:
- EPH ephemeris records preceded by "> EPH <sat> <msg-type>" header
lines: GPS/QZSS LNAV, GPS/QZSS CNAV (with its own record layout, Table
A10), Galileo INAV/FNAV, GLONASS FDMA (including the new BROADCAST
ORBIT - 4 line with status flags, group delay, URAI and health flags),
and BeiDou D1/D2.
- Ionospheric corrections logged as ION data records (Klobuchar for GPS
and BeiDou, NeQuick-G for Galileo) and time system corrections logged
as STO records (GPUT, GAUT, GAGP, GLUT, GLGP, BDUT) instead of header
lines, written as soon as the corresponding data are received.
- The compulsory LEAP SECONDS header record, written blank if the data
are not available yet and updated in place afterwards.
- Navigation data records use the recommended 'e' exponent indicator
instead of the deprecated FORTRAN 'D' notation.
Also fix update_obs_header() so that the end-of-file position is
preserved after rewriting the header, preventing the destructor from
mistaking an updated observation file for an empty one and deleting it.
- Restore true chip semantics for L1: QZSS_L1_CHIP_RATE is 1.023 Mcps and
QZSS_L1_CODE_LENGTH is 1023 chips again. The replica carries
QZSS_L1_SAMPLES_PER_CHIP = 2 samples per chip (L1 C/A chips duplicated,
L1 C/B sinBOC(1,1) subchips), following the Galileo E1 approach. The
generated waveform is unchanged, but Tracking_1J.early_late_space_chips
is expressed in chips again, consistently with all other signals.
- Normalize the DLL discriminator with the sinBOC(1,1) correlation
function when the tracked PRN broadcasts L1 C/B, selected per PRN in
start_tracking(); warn if the configured correlator spacing falls
outside the BOC(1,1) correlation main peak (> 0.33 chips).
- Attribute L1 C/B observables and ephemerides (PRN 203-206) to the PRN
of the satellite's nominal PNT signals (RINEX 4.00, Table 6), so RINEX,
RTCM and rtklib identify the transmitting satellite correctly and
multi-frequency observations of the same satellite are paired instead
of counted twice.
- Do not search QZSS L5 signals for PRNs above 202, which have no L5
PRN code assigned in IS-QZSS-PNT.
- Remove reserved, non-operational PRNs 198 and 202 from the default
QZSS search list; they remain selectable via the QZSS.prns option.
- Fix a potential std::out_of_range in
GNSSFlowgraph::priorize_satellites() when assisted acquisition
prioritizes satellites of a constellation with only a subset of its
signals configured.
The Monitor block is fed from the Observables output, which only
produced data for channels with a decoded time of week. Galileo E6
channels cannot obtain the TOW from HAS pages alone, so E6-only
configurations never produced any Monitor output. When
Monitor.enable_monitor=true, the Observables block now emits every
epoch, filling channels without valid observables with their latest
tracking data (C/N0, Doppler, carrier phase), flagged as invalid so
that the PVT engine and other consumers keep ignoring them.
Fixes#1018
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.