Files
galileo/tests/navigation/test_symbol_sync.py
T

36 lines
1.5 KiB
Python

from __future__ import annotations
import numpy as np
from galileo_rx.navigation.e1b_prompt_stream import E1BPromptEpoch
from galileo_rx.navigation.e1b_symbol_sync import E1BSymbolSynchronizer
def _epoch(index: int, sign: int, *, slip: bool = False) -> E1BPromptEpoch:
start = index * 16
prompt = sign * np.exp(1j * 0.37)
return E1BPromptEpoch(
1, start, start + 16, float(prompt.real), float(prompt.imag), 0.0, 1000.0, 0.0,
50.0, True, True, slip, False, True,
)
def test_symbol_sync_preserves_global_polarity_ambiguity() -> None:
truth = np.asarray([1, -1] * 12, dtype=np.int8)
synchronizer = E1BSymbolSynchronizer(minimum_axis_epochs=4, minimum_confidence=0.9)
symbols = synchronizer.process_many([_epoch(i, int(-value)) for i, value in enumerate(truth)])
hard = np.asarray([item.hard_value for item in symbols[4:]], dtype=np.int8)
# Either polarity is valid here; page synchronization resolves it later.
expected_bits = (truth[4:] > 0).astype(np.int8)
assert np.array_equal(hard, expected_bits) or np.array_equal(hard, 1 - expected_bits)
assert all(not item.inverted for item in symbols)
def test_cycle_slip_invalidates_and_restarts_axis_lock() -> None:
sync = E1BSymbolSynchronizer(minimum_axis_epochs=3, minimum_confidence=0.1)
symbols = [sync.process(_epoch(i, 1, slip=i == 5)) for i in range(10)]
assert symbols[5].valid is False
assert symbols[6].valid is False
assert symbols[7].valid is True
assert sync.loss_count == 1