- Rust 68.8%
- RenderScript 24%
- Python 5.5%
- Kotlin 1.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The rounded corners turned "A" into a lowercase-like loop: the 148° apex was cut off by the arc and the crossbar sat low without reaching both legs. Now A is left leg up -> sharp apex -> right leg down to the crossbar at 40% height -> crossbar left and back -> down the right leg. The apex and the crossbar junction are sharp: the receiver brakes to zero at the vertex and accelerates along the new course (6.25 m/s^2, velocity stays continuous). For that, the course field now applies to ConstAcc too (CTrajectory::append_trajectory_course replaces append_const_course): the incoming horizontal velocity is rotated to the course and the segment parameters are recomputed, so ConstAcc from rest accelerates in that course. The stops cost ~12 s, so the word is 80 x 47 m (was 85 x 50 m) to still fit two passes in 300 s at 12.5 m/s. GNSS-SDR (rx_new/rx.conf): fix from 30 s, median deviation 0.9 m, p95 2.7 m, Galileo in 1161 of 2696 epochs (was 723); with Galileo PLL 35 Hz 2538 epochs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
| .cargo | ||
| android | ||
| benchmarks | ||
| docs | ||
| EphData | ||
| presets | ||
| Rinex_Data | ||
| src | ||
| tests | ||
| .gitignore | ||
| ble_gnss_logger.py | ||
| build.rs | ||
| CACHE_OPTIMIZATION_REPORT.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| compare_rust_cpp.py | ||
| config.json | ||
| decode_gal_compare.py | ||
| FILE_STATUS.md | ||
| gal_demod.py | ||
| HARDWARE_TESTS.md | ||
| phase_continuity_check.py | ||
| README.md | ||
| README.ru.md | ||
| rinex304.pdf | ||
| TODO_FULL_VERIFICATION.md | ||
| TODO_PERFORMANCE_FIXES.md | ||
| verify_signal.py | ||
| verify_signal_enhanced.py | ||
gnss-signal-simulator-rs
🌐 English · Русский
Multi-constellation GNSS IF signal simulator written in Rust
Генерация IQ для GPS, Galileo, BeiDou и GLONASS из RINEX 3.04. Основной путь использует CPU, Rayon и SIMD через wide; CUDA kernels пока не подключены к потоковому синтезу.
Актуальный статус: трекер, контракт генерации, матрица приёмников. Исторические z-score ниже подтверждают acquisition в конкретном тесте; они не доказывают корректность nav/CRC/PVT всех перечисленных сигналов. Выбор эфемерид выполняется отдельно для спутника/семейства сообщения, видимость обновляется раз в секунду. IQ сопровождается TXT и SHA-256 manifest.
Supported Signals
| System | Signal | Frequency | Modulation | Code Length | Verified z-score |
|---|---|---|---|---|---|
| GPS | L1CA | 1575.42 MHz | BPSK(1) | 1023 | 58–88 |
| GPS | L5 | 1176.45 MHz | BPSK(10) | 10230 | 44–59 |
| GPS | L2C | 1227.60 MHz | BPSK(1) | 10230 | Verified |
| GPS | L1C | 1575.42 MHz | TMBOC / BOC(1,1) | 10230 | Verified |
| Galileo | E1 | 1575.42 MHz | CBOC(6,1,1/11) | 4092 | 63–103 |
| Galileo | E5a | 1176.45 MHz | BPSK(10) | 10230 | 48–64 |
| Galileo | E5b | 1207.14 MHz | BPSK(10) | 10230 | 449–514 |
| Galileo | E6 | 1278.75 MHz | BPSK(5) | 5115 | 270–299 |
| BeiDou | B1C | 1575.42 MHz | BOC(1,1)+QMBOC(6,1,4/33) | 10230 | 132–247 |
| BeiDou | B1I | 1561.098 MHz | BPSK(2) | 2046 | 65–96 |
| BeiDou | B2a | 1176.45 MHz | BPSK(10) | 10230 | 48–72 |
| GLONASS | G1 | 1602+k×0.5625 MHz | BPSK(0.5) FDMA | 511 | 54–56 |
z-score = (correlation peak − mean) / std, threshold ≥ 30. Values above 50 indicate reliable detection.
Key Features
- RINEX 3.04 ephemeris parsing — GPS (7-line), BeiDou (7-line with BDT correction), Galileo (7-line), GLONASS (3-line with km→m)
- Keplerian orbit propagation — GPS ICD-200 algorithm; GLONASS RK4 in PZ-90
- Multithreading — Rayon-based parallel satellite processing
- IQ8 output — signed 8-bit I/Q interleaved samples, compatible with SDR receivers (GNURadio, SDR#)
- Python verification tool — 3-page PDF report with PSD, acquisition, correlation analysis
- Minimal dependencies — only
rand,rayon,wide,serde_json,sha2(+ optionalcudarc)
Quick Start
Requirements
- Stable Rust (edition 2021) and
cargo - Рекомендуется x86_64;
.cargo/config.tomlиспользует target-cpu=native, такой бинарь непереносим на более старые CPU. - Экспериментальная GPU-фича: CUDA 12.5; основной генератор остаётся CPU.
Build and Run
# Build optimized release
cargo build --release
# Generate GPS L1CA signal (simplest example)
cargo run --release -- presets/gps_l1ca.json
# Generate triple-system GPS + BeiDou + Galileo
cargo run --release -- presets/gps_bds_gal_l1.json
# Generate quad-system GPS + BeiDou + Galileo + GLONASS (46.5 MHz)
cargo run --release -- presets/quad_l1g1.json
# Verbose output
cargo run --release -- -v presets/gps_l1ca.json
Output: binary IQ file (e.g. generated_files/gps_l1ca.C8).
Build with GPU (optional)
cargo build --release --features gpu
cargo run --release --features gpu -- presets/gps_l1ca.json
Экспериментальная сборка требует CUDA 12.5/NVRTC. Она не включает GPU в основной потоковый синтез; runtime CUDA здесь не проверен.
Presets
Ready-to-use JSON configurations in presets/:
| Preset | Systems | Sample Rate |
|---|---|---|
gps_l1ca.json |
GPS L1CA | 5 MHz |
gps_l5.json |
GPS L5 | 21 MHz |
bds_b1c.json |
BeiDou B1C | 5 MHz |
gal_e1.json |
Galileo E1 | 5 MHz |
gal_e5a.json |
Galileo E5a | 21 MHz |
gal_e5b.json |
Galileo E5b | 21 MHz |
gal_e6.json |
Galileo E6 | 11 MHz |
glo_g1.json |
GLONASS G1 | 10 MHz |
gps_bds_gal_l1.json |
GPS+BDS+GAL L1 | 5 MHz |
gps_bds_gal_l1_300s.json |
GPS+BDS+GAL L1 (over-air, 52 dBHz) | 8 MHz |
quad_l1g1.json |
GPS+BDS+GAL+GLO L1/G1 | 46.5 MHz |
The repository ships 46 presets. Most use the Montana location, 10s duration, elevation mask 5°, full RINEX; the moscow_* and usa_* presets are longer real-receiver scenarios (60–300s) at their respective locations.
Custom presets: copy any JSON, edit receiver position (LLA), sample rate, RINEX path, duration, and signal selection.
Over-the-Air Replay (HackRF / PortaPack → real receiver)
When replaying a generated file over the air into a real receiver (phone, u-blox), the defaults tuned for the software verifier are too weak. For a phone to acquire and sustain tracking (decode ephemeris → get a fix):
initPower≥ 52 dBHz in the preset. The AGC normalizes the file to a fixed output RMS regardless ofinitPower, so this sets the in-file CN0 (signal-to-noise margin), not the loudness. The default 45 dBHz acquires in the verifier but a phone cannot hold tracking.- Sample rate ≥ 8 MHz. HackRF One does 2–20 Msps but
<8 MHzis out of DAC spec; PortaPack replay is SD-throughput-limited, so ~8–10 Msps is the practical sweet spot. - E1/B1C use pure BOC(1,1) below 12.276 MHz automatically. The true CBOC/QMBOC BOC(6,1) subcarrier (6.138 MHz) aliases into the data channel at low sample rates and blocks nav-message decode on real receivers; the generator falls back to clean BOC(1,1) (which a phone's narrow L1 front-end uses anyway) and switches to true CBOC only at
Fs ≥ 12.276 MHz. - BeiDou on phones is B1I (1561.098 MHz), not B1C (1575.42 MHz). B1I is outside an L1-centered file, so use a dedicated B1I preset for BeiDou on a phone.
presets/gps_bds_gal_l1_300s.json is preconfigured for this (8 MHz, 52 dBHz, 300 s).
Signal Verification
The included Python tool verify_signal_enhanced.py generates a 3-page PDF diagnostic report.
Usage
# Install dependencies
pip install numpy matplotlib
# Verify with auto-configuration from preset
python verify_signal_enhanced.py generated_files/gps_bds_gal_l1.C8 \
--preset presets/gps_bds_gal_l1.json
# Fast mode (search only RINEX-visible satellites)
python verify_signal_enhanced.py generated_files/gps_l1ca.C8 \
--preset presets/gps_l1ca.json --fast
# Custom parameters
python verify_signal_enhanced.py generated_files/output.C8 \
--sample-rate 5.0 --threshold 30 --output report.pdf
PDF Report Contents
- Page 1 — Signal Overview: Welch PSD, I/Q histogram with Gaussian fit, constellation diagram, RMS stability
- Page 2 — Acquisition Results: z-score bar chart (color-coded by system), polar skyplot (expected vs detected), CN0 estimation, Doppler accuracy
- Page 3 — Correlation Analysis: Zoomed correlation peaks per system, 2D Doppler×Code heatmaps
Verification Results
Triple-system (GPS + BeiDou + Galileo, 5 MHz, 10s, Chicago):
| System | RINEX Visible | Detected | z-score Range |
|---|---|---|---|
| GPS L1CA | 11 | 11 | 58–88 |
| BeiDou B1C | 8 | 6 | 574–955 |
| Galileo E1 | 10 | 6 | 364–425 |
| Total | 29 | 23 | 100% of generated |
Galileo multi-band (Montana, 10s each):
| Signal | Sample Rate | Detected | z-score Range |
|---|---|---|---|
| E5a | 21 MHz | 7/7 | 434–502 |
| E5b | 21 MHz | 7/7 | 449–514 |
| E6 | 11 MHz | 7/7 | 270–299 |
Single-system results after the June 2026 passes (true CBOC/QMBOC waveforms + NH-robust verifier):
| Signal | Sample Rate | RINEX Visible | Detected | z-score Range |
|---|---|---|---|---|
| Galileo E1 (CBOC) | 5 MHz | 10 | 10/10 | 63–103 |
| BeiDou B1C (QMBOC, pilot acquisition) | 5 MHz | 12 | 12/12 | 132–247 |
| BeiDou B1I | 5 MHz | 12 | 12/12 | 65–96 |
| GPS L5 | 21 MHz | 10 | 10/10 | 44–59 |
| Galileo E5a | 21 MHz | 10 | 10/10 | 48–64 |
| BeiDou B2a | 21 MHz | 12 | 12/12 | 48–72 |
PRN codes cross-verified bit-exact against independent references: B1I vs gnss-sdr (63/63 PRN); B1C data/pilot/secondary, E5a I/Q, B2a data/pilot and all NH/secondary codes vs PocketSDR. GPS L5 XA/XB is ICD-literal (free-running XB; the references' mod-10230 roll diverges in the last
advchips per PRN, <0.12 dB effect).The verifier uses double-window linear correlation (immune to NH/secondary chip flips at code epochs) with code-Doppler drift compensation — the earlier 0/10 GPS L5 result was a verifier artifact, confirmed by a clean-room dump showing ideal per-period correlation and bit-exact NH wiring.
GLONASS G1 (10 MHz, Montana, 10s):
| Generated | Detected | z-score Range |
|---|---|---|
| 7 SVs | 5 | 54–56 |
Architecture
src/
├── main.rs # Entry point — reads JSON preset, runs generation
├── lib.rs # Public module exports
├── ifdatagen.rs # Core IF data generation (AGC, satellite signals, noise)
├── sat_if_signal.rs # Per-satellite IF sample generation (PRN codes, BOC)
├── coordinate.rs # Keplerian propagator, ECEF/LLA/ENU conversions
├── json_interpreter.rs # RINEX 3.04 parser, JSON preset parser
├── gnsstime.rs # GPS/BDT/GST/GLONASS time system conversions
├── types.rs # Core types: GpsEphemeris, BeiDouEphemeris, KinematicInfo
├── constants.rs # WGS84, PZ-90, CGCS2000 constants
├── prngenerate.rs # PRN code generation (Gold, Weil/Legendre, memory codes)
├── memory_code_e1.rs # Galileo E1 memory codes (4092 chips)
├── memory_code_e6.rs # Galileo E6 memory codes (5115 chips)
├── fastmath.rs # Optimized sin/cos/atan2 approximations
├── complex_number.rs # Lightweight complex arithmetic
├── satellite_param.rs # Satellite parameters and signal configuration
├── satellite_signal.rs # Signal-level satellite processing
├── almanac.rs # Almanac parsing and type detection
├── trajectory.rs # Receiver trajectory generation
├── *navbit.rs # Navigation message generators (GPS LNAV, Galileo I/NAV,
│ # F/NAV, BeiDou BCNav1/2/3, GLONASS G-NAV, etc.)
├── nav_decode.rs # Reverse decoders + ICD parity/CRC verifiers for nav messages
├── gps_pilot/mod.rs # Clean minimal phase-continuous GPS L1CA generator
└── bin/
├── spectrum_analyzer.rs # IF spectrum analysis (PSD, peaks, CSV export)
├── nav_diagnostics.rs # Nav message encode→decode→compare vs RINEX (ICD verify)
├── decode_iq.rs # GPS L1CA IQ8 decoder — acquisition, tracking, LNAV decode
├── gnss_pilot.rs # Clean GPS L1CA + Galileo E1 + BeiDou B1C L1-band generator
├── gps_pilot.rs # Clean minimal GPS L1CA generator
├── nav_test.rs # Navigation bit unit tests
├── bench.rs # CPU/AVX-512/GPU benchmarks
└── extreme_bench.rs # Stress benchmarks
RINEX Data
Rinex_Data/rinex_v3_20251560000.rnx— 2025-06-05, GPS/BDS/GALRinex_Data/BRDC00IGS_R_20251560000_01D_MN.rnx— 2025-06-05, full merged GPS/BDS/GAL/GLO
Output Format
IQ8: signed 8-bit interleaved I/Q samples (.C8 extension)
[I₀, Q₀, I₁, Q₁, I₂, Q₂, ...] — each sample is int8 (-128..+127)
- AGC target RMS: 0.25 (quantized: ~31.75 in int8 units)
- Compatible with GNURadio (
file_source→char_to_float), SDR#, and custom SDR receivers - File size:
2 × sample_rate × durationbytes (e.g. 5 MHz × 10s = 100 MB)
Spectrum Analyzer
Built-in IF spectrum analysis tool:
cargo run --release --bin spectrum_analyzer -- generated_files/gps_l1ca.C8 iq8 5000000 0 --csv
Outputs PSD to terminal and optionally to spectrum.csv.
Development
cargo check # Fast syntax/type check
cargo test # Run unit tests
cargo fmt --all # Format code
cargo clippy # Lint
Detailed verification status is tracked in docs/verification_report.md and
docs/gnss_icd_conformance_report.md.
Troubleshooting
| Problem | Solution |
|---|---|
| "Configuration file not found" | Use presets from presets/ or edit generated config.json |
| "RINEX file not found" | Check relative paths in preset, ensure files exist in Rinex_Data/ |
| CUDA not found | Install CUDA 12.5, verify NVRTC in PATH/LD_LIBRARY_PATH |
| Slow generation | Use --release, use --features gpu |
| 0 visible satellites | Check RINEX date matches preset time, verify receiver coordinates |
License
See source files for license information.
Описание (Русский)
Мультисистемный симулятор GNSS-сигналов на Rust
Генерация реалистичных IQ-отсчётов промежуточной частоты для GPS, Galileo, BeiDou и GLONASS из навигационных данных RINEX 3.04.
Поддерживаемые сигналы
- GPS: L1CA, L5, L2C, L1C
- Galileo: E1 (CBOC), E5a, E5b, E6
- BeiDou: B1C (BOC+QMBOC), B1I, B2a
- GLONASS: G1 (FDMA)
Быстрый старт
# Сборка
cargo build --release
# Генерация GPS L1CA
cargo run --release -- presets/gps_l1ca.json
# Тройная система GPS + BeiDou + Galileo
cargo run --release -- presets/gps_bds_gal_l1.json
# Верификация сигнала (Python)
python verify_signal_enhanced.py generated_files/gps_l1ca.C8 \
--preset presets/gps_l1ca.json
Основные возможности
- 4 навигационные системы, 10 сигналов, одновременная генерация
- Парсинг эфемерид RINEX 3.04 (GPS/BDS/GAL/GLO)
- Кеплеровская пропагация орбит + ГЛОНАСС RK4 в ПЗ-90
- Физически корректная модель АРУ (AGC)
- Ускорение AVX-512 + многопоточность (Rayon)
- Экспериментальные CUDA kernels (не основной путь генерации)
- Выход IQ8 (8-бит I/Q), совместимый с SDR-приёмниками
- Инструмент верификации с 3-страничным PDF-отчётом
- ~55 000 строк Rust, минимум зависимостей