Received-event RTK and IMU processing¶
OnlineRtkImuProcessor and gnss_online provide a separate received-event
route. The processor accepts navigation, base observations, body-FLU IMU
samples and rover observations one event at a time. It does not open a data
file, scan later observations, smooth outputs or interpolate a future base.
Existing batch commands retain their existing behavior.
CSV schema v2 appends fresh attitude (wxyz, body FLU to fixed ENU), its source
time and fixed frame rotation, FRD/NED Roll/Pitch/Heading, estimated IMU biases
and antenna ECEF velocities. The first 27 columns are preserved. An available
attitude does not imply observed heading: heading_aligned is the first latch,
while heading_converged is recent innovation health. Uninitialized/stale
quaternions, frame rotations and angles are NaN. See the
PVA workflow for public-log scoring and distribution demos.
Build and input¶
cmake --build <build> --config Release --target gnss_online gnss_online_tests
<build>/apps/Release/gnss_online --help
On a single-configuration generator the executables have no Release directory.
Start the executable with a known reference antenna ECEF position in metres:
gnss_online --base-ecef X Y Z --lever-arm forward left up \
--rtk-out new_rtk.pos --fused-out new_fused.pos
Supply these space-separated event envelopes on stdin. Every week/TOW pair uses normalized GPST; the reception pair must be monotone across all events.
| Event | Remaining fields |
|---|---|
NAV |
reception week/TOW, one complete CRC-valid RTCM3 ephemeris frame in hexadecimal |
BASE |
reception week/TOW, observation week/TOW, all RTCM3 observation frames for that epoch |
ROVER |
reception week/TOW, observation week/TOW, all RTCM3 observation frames for that epoch |
IMU |
reception week/TOW, sample week/TOW, ax ay az gx gy gz |
RESET |
reception week/TOW |
Each event occupies one line. Acceleration uses m/s² and gyro uses rad/s,
both in Forward/Left/Up axes. The lever arm is IMU to antenna in the same
axes. The input adapter must assemble all observation frames for an epoch;
the command checks frame CRC, TOW and duplicate satellite/signal identities.
The full week comes from the envelope. Empty lines and # comments are allowed.
A malformed event stops with its line number and a nonzero exit code.
The decoder receives the event's GPST reception time as the context for
truncated GPS week and GLONASS day fields. Historical replay does not use the
current PC date for those fields. The public RTCMProcessor::setReferenceTime
also exposes this context to adapters; callers that omit it retain the legacy
host-clock decoding behavior. clear() removes the explicit context.
The command flushes one CSV record after every ROVER line, before reading
the next event. Optional POS sinks contain only valid solutions and must be
new files. CSV includes every rover event, including missing solutions.
Time and availability contract¶
An observation/sample timestamp cannot exceed its reception timestamp. A received IMU sample later than a delayed rover epoch remains queued. It is not mechanized until a rover epoch reaches that sample time. Late or duplicate IMU samples are dropped; late base epochs cannot revise emitted outputs.
RTK uses an already-received base epoch at the same observation timestamp. There is no waiting or interpolation. If the exact base is absent, the RTK stream emits an SPP fallback or a missing solution. With 1 Hz base and 5 Hz rover input this means differential processing is available only at the common timestamps. This availability cost must be measured explicitly.
GNSS feedback to the fusion state and tight RTK time updates require an IMU
sample at the rover epoch. An older prediction retains its actual timestamp;
the default maximum fusion age is 0.02 s. Propagation without an accepted
position correction reports PROPAGATED. Fusion requires fresh trailing
IMU alignment and a usable GNSS origin. Tight time updates additionally
require heading convergence and a valid FLOAT posterior anchor. --loose-only
disables that optional feedback path.
An IMU gap greater than 0.1 s, a stale last IMU sample, or a rover gap greater
than 2 s resets the RTK/fusion filters. Reinitialization uses newly received
trailing samples; it cannot reuse the old attitude alignment. Each reset
increments reset_generation. Explicit RESET clears pending observations
and IMU samples while retaining received broadcast navigation. It preserves
the monotone reception watermark.
Pending queues have explicit capacities (10,000 IMU samples and 16 base epochs by default). Overflow rejects the event. Broadcast storage retains at most eight records per satellite and satellite-state caches are scoped to one processing epoch.
Output and provenance¶
CSV records contain input age (reception minus rover timestamp), fusion age (rover minus actual fused timestamp), processing wall time, exact-base availability, IMU consumption, initialization/heading state, supplied tight update, reset generation and fallback/reset reason. Antenna ECEF coordinates are in metres. Reception timestamps describe adapter-provided availability; they must come from actual receipt for a live causality claim. Assigning a timestamp to a preloaded navigation file does not establish when its records were broadcast or received.
An SPP fallback between exact base epochs leaves the RTK differential filter
unchanged and preserves the short IMU interval. The next exact base can then
receive the accumulated time update (for example, with 1 Hz base and 5 Hz
rover). An anchor interval exceeding 2 s discards the tight filter and requires
a fresh LC heading/bootstrap; failed exact-base anchors also discard it. The
public configuration exposes this bound as max_tight_interval_s.
This route is distinct from fixed-lag FGO and existing whole-file fusion. Batch scores do not prove its accuracy or latency. Acceptance requires native queue/reset tests, numerical prefix parity on usable raw PPC outputs, late/missing-base and IMU-gap replays, and measured missing outputs and latency. The processor and executable build; all nine queue/reset tests and four historical RTCM context tests pass. The raw-data verification below passed on Tokyo run1 with 600 epochs and an exactly matching 300-epoch prefix.
Reproducible raw-data verification¶
Build the explicit staging harness and run the verifier against an existing
PPC development run. Keep the historical native test fixtures separate.
The verification targets require BUILD_TESTING=ON and Google Test; the
production gnss_online executable does not depend on Google Test.
cmake --build build --target gnss_online gnss_online_ppc_fixture
python scripts/analysis/verify_online_ppc.py \
--run-dir /datasets/PPC-Dataset/tokyo/run1 \
--fixture-exe build/tests/gnss_online_ppc_fixture \
--online-exe build/apps/gnss_online --epochs 600 \
--output-dir output/online-tokyo1
For Windows multi-config builds add --config Release and use
build/tests/Release/*.exe and build/apps/Release/*.exe. The output directory
must be new. The report records raw-input and executable hashes, the command,
every emitted row, processing time and availability counts.
The typed-API audit uses all constellations admitted by the RINEX reader. The first half of five executions receives identical inputs; subsequent inputs remove base epochs, deliver base epochs after their rover output, or omit IMU samples for four seconds. A fifth execution delivers the rover 0.15 s late, checks its input-age metadata and preserves its chronological numerical output. Late base delivery is explicitly 0.1 s after its rover output. All numerical/metadata prefix fields except wall time must match exactly, with actual RTK/fused positions and supplied tight time updates required. The IMU-gap execution must reinitialize fusion.
The stdin transport audit stages GPS MSM7/1019 frames because the existing ephemeris encoder cannot emit Galileo/BeiDou navigation. This restriction is on the transport fixture, not on the typed processor's constellation support. It waits for each output with stdin still open before sending another rover event, then repeats with a state reset in the suffix. The numerical prefix must match and the suffix must actually change. This also tests CRC framing and historical week interpretation through the production CLI.
PPC does not provide observed reception timestamps. The staging simulation delivers samples/base records at each rover event and admits navigation only after its clock epoch and transmission time. It reads files only to prepare events; the processor sees received records alone. The results establish this declared simulation's prefix causality, missing/late-data behavior and local processing latency. They do not establish live network latency or full-run accuracy against reference truth.
The 2026-10-06 Tokyo run1 verification emitted 600 valid typed RTK positions,
590 fresh fused positions and 103 tight time updates. Exact-base availability
was 120/600; removing or delivering the second half's base epochs late reduced
it to 60/600. The four-second IMU outage caused one filter reset and fresh
reinitialization, with 560 valid fused outputs. Normal processor wall-time P95
was 25.733 ms (maximum 51.5232 ms) on this concurrently busy Windows host.
The GPS-only stdin fixture emitted 108 valid RTK positions, 590 fused positions
(including explicit propagation), and 28 tight updates; its unavailable RTK
outputs remain in CSV. All 600 outputs arrived with stdin still open. Raw
inputs, binaries, CSVs and timing measurements are retained in
output/online-tokyo1-final-20261006/report.json.
The verification record preserves the input and
binary hashes, scenario populations, prefix result and artifact manifest.