Implement Galileo E1B I/NAV navigation decoding

This commit is contained in:
2026-07-31 00:15:34 +03:00
parent 2a6ccfc23d
commit 814a788b36
104 changed files with 6351 additions and 10 deletions
@@ -0,0 +1,22 @@
from __future__ import annotations
import json
from pathlib import Path
import pytest
@pytest.mark.signalsim
def test_four_satellites_are_navigation_ready_without_truth_inputs() -> None:
path = Path("reports/navigation_run/inav_collection_report.json")
if not path.is_file():
pytest.skip("SignalSim multi-satellite navigation collection report is unavailable")
report = json.loads(path.read_text(encoding="utf-8"))
assert report["decoder_truth_inputs"] == []
ready = [
item for item in report["satellites"].values()
if item["complete_ephemeris"] and item["clock_parameters"] and item["health_valid"] and item["data_valid"]
]
assert len(ready) >= 4
assert report["galileo_time"]["valid"] is True
assert report["navigation_ready"] is True
@@ -0,0 +1,20 @@
from __future__ import annotations
import json
from pathlib import Path
import pytest
@pytest.mark.signalsim
def test_signalsim_decoded_ephemerides_match_rinex_truth_within_quantization() -> None:
path = Path("reports/inav_truth_comparison.json")
if not path.is_file():
pytest.skip("post-decode SignalSim truth-comparison report is unavailable")
report = json.loads(path.read_text(encoding="utf-8"))
assert report["truth_injected_into_decoder"] is False
assert report["overall_pass"] is True
assert len(report["satellites"]) >= 4
assert all(item["pass"] for item in report["satellites"].values())
assert report["galileo_time"]["pass"] is True
assert report["galileo_time"]["time_of_week_absolute_error_s"] <= 1
@@ -0,0 +1,19 @@
from __future__ import annotations
from pathlib import Path
import pytest
from galileo_rx.navigation.decoder_diagnostics import load_prompt_epochs
from galileo_rx.navigation.inav_pipeline import InavNavigationPipeline
@pytest.mark.signalsim
def test_signalsim_prompts_produce_crc_valid_inav_pages() -> None:
path = Path("verification/navigation/signalsim_navigation_multisat/prn_01/prompt_epochs.npz")
if not path.is_file():
pytest.skip("SignalSim navigation prompt artifact is unavailable; run collect-navigation first")
decoded = InavNavigationPipeline(1).process(load_prompt_epochs(path, 1))
assert len(decoded.pages) == 15
assert all(page.sync_valid and page.fec_valid and page.crc_valid for page in decoded.pages)
assert {word.word_type for word in decoded.words} == {1, 2, 3, 4, 5, 6}
@@ -0,0 +1,23 @@
from __future__ import annotations
from pathlib import Path
import numpy as np
import pytest
from galileo_rx.navigation.decoder_diagnostics import load_prompt_epochs
from galileo_rx.navigation.e1b_symbol_sync import E1BSymbolSynchronizer
@pytest.mark.signalsim
def test_signalsim_prompt_artifact_recovers_soft_and_hard_symbols() -> None:
path = Path("verification/navigation/signalsim_navigation_multisat/prn_01/prompt_epochs.npz")
if not path.is_file():
pytest.skip("SignalSim navigation prompt artifact is unavailable; run collect-navigation first")
prompts = load_prompt_epochs(path, 1)
symbols = E1BSymbolSynchronizer(8, 0.1).process_many(prompts)
soft = np.asarray([item.soft_value for item in symbols], dtype=np.float64)
assert soft.dtype == np.float64
assert len(symbols) == 8044
assert np.count_nonzero([item.valid for item in symbols]) > 7500
assert {item.hard_value for item in symbols} == {0, 1}