Files
galileo/tests/regression/test_complete_receiver.py

43 lines
2.5 KiB
Python

import numpy as np
from galileo_rx.acquisition.acquisition_manager import AcquisitionManager
from galileo_rx.config import AcquisitionConfig, TrackingConfig
from galileo_rx.fixed_point.fixed_correlator import FixedCorrelator
from galileo_rx.fixed_point.formats import FixedFormat
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
from galileo_rx.tracking.tracking_channel import TrackingChannel
def test_complete_float_and_fixed_prompt_regression() -> None:
fs = 4.092e6
profile, provider = galileo_e1_profile(), SyntheticCodeProvider()
generator = SyntheticSignalGenerator(
profile,
provider,
fs,
satellites=[SatelliteSignalConfig(11, "E1B", code_delay_chips=24.0, doppler_hz=-750.0, carrier_phase_rad=0.05, cn0_db_hz=50.0)],
channel=ChannelModelConfig(seed=123),
)
samples, _ = generator.generate(int(0.06 * fs))
acquisition_config = AcquisitionConfig(
doppler_min_hz=-1500, doppler_max_hz=0, doppler_step_hz=250,
noncoherent_accumulations=2, detection_threshold=2.0, zero_padding_mode="none", parabolic_interpolation=False,
)
acquisition, _ = AcquisitionManager(profile, provider, fs, acquisition_config).acquire_one(samples, "E1B", 11)
assert acquisition.detected and acquisition.raw_doppler_hz == -750.0
channel = TrackingChannel(profile, provider, fs, TrackingConfig(pull_in_duration_ms=12.0), acquisition)
measurements = channel.process(samples)
assert len(measurements) == 15 and not measurements[-1].reacquisition_requested
count = channel.integration_samples
phases = (-acquisition.code_phase_chips + np.arange(count) * profile.code_rate_hz / fs)
code = provider.primary_code(profile, "E1B", 11)
replica = code[np.floor(phases).astype(np.int64) % code.size] * np.where(np.mod(phases, 1.0) < 0.5, 1, -1)
# This vector is intentionally unnormalized AWGN, so use an input format
# with integer headroom rather than the post-AGC Q1.7 default.
fixed_prompt = FixedCorrelator(fs, acquisition.carrier_frequency_hz, sample_format=FixedFormat(12, 4)).correlate_prompt(samples[:count], replica)
float_prompt = np.sum(samples[:count] * np.exp(-2j * np.pi * acquisition.carrier_frequency_hz * np.arange(count) / fs) * replica)
assert abs(fixed_prompt.complex_value - float_prompt) / abs(float_prompt) < 0.03