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