87 lines
3.4 KiB
Python
87 lines
3.4 KiB
Python
import numpy as np
|
|
import pytest
|
|
|
|
from galileo_rx.acquisition.acquisition_manager import AcquisitionManager
|
|
from galileo_rx.config import AcquisitionConfig, FrontendConfig, RfConfig
|
|
from galileo_rx.frontend.frontend_chain import FrontendChain
|
|
from galileo_rx.signal_profiles import galileo_e1_profile
|
|
from galileo_rx.signals.code_provider import SyntheticCodeProvider
|
|
from galileo_rx.signals.signal_generator import ChannelModelConfig, SatelliteSignalConfig, SyntheticSignalGenerator
|
|
|
|
|
|
def make_signal(fs: float, delay_chips: float, doppler_hz: float, periods: int = 2, real_if: bool = False):
|
|
profile = galileo_e1_profile()
|
|
provider = SyntheticCodeProvider()
|
|
if_hz = 2.0e6 if real_if else 0.0
|
|
generator = SyntheticSignalGenerator(
|
|
profile,
|
|
provider,
|
|
fs,
|
|
if_hz,
|
|
real_if,
|
|
[SatelliteSignalConfig(prn=5, component="E1C", code_delay_chips=delay_chips, doppler_hz=doppler_hz, cn0_db_hz=48.0)],
|
|
ChannelModelConfig(seed=22),
|
|
)
|
|
samples, _ = generator.generate(int(round(periods * 0.004 * fs)))
|
|
if real_if:
|
|
rf = RfConfig(sample_format="float64", input_is_real_if=True, sampling_frequency_hz=fs, intermediate_frequency_hz=if_hz)
|
|
samples = FrontendChain(rf, FrontendConfig()).process(samples)
|
|
return samples, profile, provider
|
|
|
|
|
|
@pytest.mark.parametrize("doppler_hz", [-1250.0, 1750.0])
|
|
def test_pcps_detects_doppler_and_code(doppler_hz: float) -> None:
|
|
fs = 4.092e6
|
|
delay_chips = 37.0
|
|
samples, profile, provider = make_signal(fs, delay_chips, doppler_hz)
|
|
config = AcquisitionConfig(
|
|
doppler_min_hz=-2500,
|
|
doppler_max_hz=2500,
|
|
doppler_step_hz=250,
|
|
coherent_integration_ms=4,
|
|
noncoherent_accumulations=2,
|
|
detection_threshold=2.0,
|
|
zero_padding_mode="none",
|
|
parabolic_interpolation=False,
|
|
)
|
|
result, _ = AcquisitionManager(profile, provider, fs, config).acquire_one(samples, "E1C", 5)
|
|
assert result.detected
|
|
assert result.raw_doppler_hz == doppler_hz
|
|
assert abs(result.code_phase_chips - delay_chips) <= 0.26
|
|
|
|
|
|
def test_pcps_noninteger_samples_per_chip_and_boundary() -> None:
|
|
fs = 4.5e6
|
|
delay_chips = 4091.2
|
|
samples, profile, provider = make_signal(fs, delay_chips, 500.0)
|
|
config = AcquisitionConfig(
|
|
doppler_min_hz=0,
|
|
doppler_max_hz=1000,
|
|
doppler_step_hz=250,
|
|
coherent_integration_ms=4,
|
|
noncoherent_accumulations=2,
|
|
detection_threshold=1.8,
|
|
zero_padding_mode="none",
|
|
parabolic_interpolation=False,
|
|
)
|
|
result, _ = AcquisitionManager(profile, provider, fs, config).acquire_one(samples, "E1C", 5)
|
|
circular_error = min(abs(result.code_phase_chips - delay_chips), 4092 - abs(result.code_phase_chips - delay_chips))
|
|
assert result.detected and circular_error < 0.6
|
|
|
|
|
|
def test_real_if_acquisition() -> None:
|
|
fs = 8.0e6
|
|
samples, profile, provider = make_signal(fs, 21.0, 750.0, real_if=True)
|
|
config = AcquisitionConfig(
|
|
doppler_min_hz=250,
|
|
doppler_max_hz=1250,
|
|
doppler_step_hz=250,
|
|
coherent_integration_ms=4,
|
|
noncoherent_accumulations=2,
|
|
detection_threshold=1.7,
|
|
zero_padding_mode="none",
|
|
parabolic_interpolation=False,
|
|
)
|
|
result, _ = AcquisitionManager(profile, provider, fs, config).acquire_one(samples, "E1C", 5)
|
|
assert result.detected and result.raw_doppler_hz == 750.0
|