43 lines
2.5 KiB
Python
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
|