Files
galileo/tests/integration/test_signalsim_e1c_pilot_aided_tracking.py

79 lines
3.1 KiB
Python

from __future__ import annotations
from pathlib import Path
import numpy as np
import pytest
import yaml
from galileo_rx.acquisition.acquisition_manager import AcquisitionManager
from galileo_rx.config import AcquisitionConfig, TrackingConfig
from galileo_rx.io.signalsim_reader import SignalSimReader, SignalSimSampleSpec
from galileo_rx.signal_profiles import galileo_e1_profile
from galileo_rx.signals.signalsim_codes import SignalSimCodeProvider
from galileo_rx.tracking.pilot_aided_e1 import (
E1CPilotAidedE1TrackingChannel,
synchronize_e1c_for_tracking,
)
@pytest.mark.signalsim
def test_e1c_secondary_sync_and_pilot_aided_e1b_branch() -> None:
cfg = yaml.safe_load(Path("configs/navigation_collection.yaml").read_text(encoding="utf-8"))
source = Path(cfg["signalsim"]["path"])
vector = Path(cfg["signalsim"]["samples"])
if not source.is_dir() or not vector.is_file():
pytest.skip("SignalSim checkout or 32.2-second navigation IQ8 vector is unavailable")
fs = float(cfg["rf"]["sampling_frequency_hz"])
samples = SignalSimReader(
vector, SignalSimSampleSpec(cfg["signalsim"]["sample_format"]), memory_map=True
).read()
profile = galileo_e1_profile()
provider = SignalSimCodeProvider(source)
acquisition_config = AcquisitionConfig(
**cfg["acquisition"], parallelism="doppler_vectorized"
)
manager = AcquisitionManager(profile, provider, fs, acquisition_config)
observation_samples = (
manager.engine.coherent_samples * acquisition_config.noncoherent_accumulations
)
acquisition, _ = manager.acquire_one(
samples[:observation_samples], "E1C", 1, float(cfg["rf"]["intermediate_frequency_hz"])
)
assert acquisition.detected
synchronized = synchronize_e1c_for_tracking(
samples, profile, provider, fs, acquisition, observation_samples
)
assert synchronized.sync.normalized_correlation > 0.98
assert synchronized.sync.sign_errors == 0
channel = E1CPilotAidedE1TrackingChannel(
profile,
provider,
fs,
TrackingConfig(
integration_ms=2.0,
pull_in_duration_ms=300.0,
pll_noise_bandwidth_hz=10.0,
fll_noise_bandwidth_hz=20.0,
dll_noise_bandwidth_hz=1.0,
secondary_code_mode="wipeoff",
loss_of_lock_epochs=40,
),
synchronized.acquisition,
synchronized.tracking_start_sample,
synchronized.sync.phase,
)
count = int(round(fs * 1.0))
epochs = channel.process_pilot_aided(
samples[synchronized.tracking_start_sample : synchronized.tracking_start_sample + count]
)
pilot = [item.pilot for item in epochs]
assert len(pilot) == 500
assert sum(item.code_lock and item.carrier_lock for item in pilot[30:]) > 460
assert not any(item.cycle_slip or item.sample_discontinuity for item in pilot)
assert sum(pilot[index - 1].code_lock and not pilot[index].code_lock for index in range(1, len(pilot))) == 0
assert np.median(
np.asarray([abs(item.e1b_correlators.prompt) for item in epochs[150:]], dtype=np.float64)
) > 1.0e4