GeoVeil-MP: GNSS Multipath Analysis Library
A high-performance Rust library for GNSS multipath analysis with Python bindings. Part of the GeoVeil suite for GNSS signal quality analysis.
Features
- 🛰️ RINEX Support: Full support for RINEX v2.xx, v3.xx, and v4.xx observation files
- 🌍 Multi-GNSS: GPS, GLONASS, Galileo, BeiDou, QZSS, NavIC/IRNSS, SBAS
- 📡 Navigation Data:
- Broadcast ephemerides (Keplerian elements)
- GLONASS state vector propagation (4th-order Runge-Kutta)
- SP3 precise orbit interpolation (Neville's algorithm)
- 📊 Multipath Analysis: Code multipath estimation using linear combinations
- ⚡ Cycle Slip Detection: Ionospheric residuals and code-phase combinations
- 📍 Position Estimation: Least squares SPP with DOP calculation
- 🎨 Visualization: R plotting integration for publication-quality figures
- 🚀 High Performance: Parallel processing with Rayon, memory-mapped I/O
- 🐍 Python Bindings: Full Python API via PyO3
Installation
Python (PyPI)
Rust (Cargo)
[]
= "0.1"
Or with all features:
[]
= { = "0.1", = ["full"] }
From Source
# Clone the repository
# Build Rust library
# Build Python wheel
Quick Start
Python Usage
# Read RINEX observation file
=
# Read SP3 precise ephemeris (optional, for accurate elevations)
=
# Create analyzer with elevation cutoff
=
# Run multipath analysis
=
# Compute satellite elevations from SP3
, =
# Access results
# Print statistics by signal
# Export to CSV
=
=
Rust Usage
use ;
CLI Usage
# Analyze RINEX file with SP3 orbits
# Get file information
# Estimate position from pseudoranges
Multipath Estimation
The code multipath is estimated using the linear combination:
$$MP_1 = R_1 - \left(1+\frac{2}{\alpha - 1}\right)\Phi_1 + \left(\frac{2}{\alpha - 1}\right)\Phi_2$$
where:
- $R_1$ is the code observation on frequency 1
- $\Phi_1, \Phi_2$ are phase observations on frequencies 1 and 2
- $\alpha = f_12/f_22$ is the frequency ratio squared
This combination eliminates ionospheric delay and geometry, leaving only code multipath, code noise, and ambiguity-related biases.
Supported GNSS Systems
| System | Code | Frequencies | Navigation |
|---|---|---|---|
| GPS | G | L1, L2, L5 | Keplerian |
| GLONASS | R | G1, G2, G3 | State Vector (RK4) |
| Galileo | E | E1, E5a, E5b, E6 | Keplerian |
| BeiDou | C | B1I, B1C, B2a, B2b, B3I | Keplerian |
| QZSS | J | L1, L2, L5, L6 | Keplerian |
| NavIC | I | L5, S, L1 | Keplerian |
| SBAS | S | L1, L5 | - |
Data Sources
SP3 Precise Orbits (No Authentication Required)
ESA: http://navigation-office.esa.int/products/gnss-products/{week}/
GFZ: https://igs.bkg.bund.de/root_ftp/IGS/products/mgex/{week}/
CODE: https://igs.bkg.bund.de/root_ftp/IGS/products/mgex/{week}/
Broadcast Navigation
BKG: https://igs.bkg.bund.de/root_ftp/IGS/BRDC/{year}/{doy}/
IGN: https://igs.ign.fr/pub/igs/data/{year}/{doy}/
Python API Reference
Classes
| Class | Description |
|---|---|
GnssSystem |
GNSS constellation identifier (G, R, E, C, J, I, S) |
Satellite |
Satellite PRN identifier (e.g., "G01", "E11") |
Epoch |
Time representation with GPS/Julian conversions |
Ecef |
Earth-Centered Earth-Fixed coordinates |
Geodetic |
Latitude/Longitude/Height coordinates |
RinexObsData |
RINEX observation data container |
Sp3Data |
SP3 precise orbit data container |
MultipathAnalyzer |
Main multipath analysis engine |
AnalysisResults |
Analysis results container |
Functions
| Function | Description |
|---|---|
read_rinex_obs(path) |
Read RINEX observation file |
read_rinex_obs_bytes(data, filename) |
Read RINEX from bytes |
read_sp3(path) |
Read SP3 precise orbit file |
get_frequency(system, band, fcn) |
Get signal frequency (Hz) |
get_wavelength(system, band, fcn) |
Get signal wavelength (m) |
calculate_azel(receiver, satellite) |
Compute azimuth/elevation |
compute_elevation(sp3, receiver, sat, epoch) |
Compute elevation from SP3 |
version() |
Get library version |
Constants
| Constant | Value | Description |
|---|---|---|
SPEED_OF_LIGHT |
299792458.0 | Speed of light (m/s) |
GM_WGS84 |
3.986005e14 | Earth gravitational parameter (m³/s²) |
EARTH_RADIUS |
6378137.0 | WGS84 Earth radius (m) |
Architecture
geoveil_mp/
├── src/
│ ├── lib.rs # Library entry point
│ ├── python.rs # Python bindings (PyO3)
│ ├── rinex/ # RINEX parsing
│ │ ├── types.rs # Data structures
│ │ └── obs_reader.rs # Observation file reader
│ ├── navigation/ # Ephemeris handling
│ │ ├── types.rs # Ephemeris types
│ │ ├── kepler2ecef.rs # Keplerian to ECEF
│ │ ├── glonass.rs # GLONASS Runge-Kutta
│ │ └── sp3.rs # SP3 Neville interpolation
│ ├── analysis/ # Analysis algorithms
│ │ ├── multipath.rs # Multipath estimation
│ │ ├── cycle_slip.rs # Cycle slip detection
│ │ └── position.rs # Position estimation
│ ├── plotting/ # R integration
│ └── utils/ # Utilities
│ ├── constants.rs # Physical constants
│ ├── coordinates.rs # Coordinate transforms
│ ├── time.rs # Time handling
│ └── error.rs # Error types
├── examples/
├── tests/
└── r_scripts/ # R plotting scripts
Performance
Benchmarks on a typical 24-hour multi-GNSS RINEX file (~100MB):
| Operation | Time | Notes |
|---|---|---|
| Read RINEX 3.05 | ~500ms | Memory-mapped I/O |
| Read SP3 | ~50ms | Neville interpolation ready |
| Multipath analysis | ~200ms | Parallel processing |
| Position estimation | ~2s | All epochs |
Related Projects
- geoveil-cn0: CN0 (carrier-to-noise ratio) analysis and interference detection
- GNSS_Multipath_Analysis_Software: Original Python implementation (inspiration)
References
- RINEX 4.02 Specification (IGS/RTCM)
- GPS Interface Control Document (IS-GPS-200)
- GLONASS Interface Control Document (ICD-GLONASS)
- Galileo OS-SDD (Open Service Signal-in-Space ICD)
- IGS Multi-GNSS Experiment (MGEX)
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Changelog
See CHANGELOG.md for version history.