Rust package to parse and analyze Rinex files
Many RINEX file types exist,
the RinexType
enum (refer to API)
describes the types of RINEX currently supported:
RinexType::NavigationMessage
: Ephemeride (NAV) messagesRinexType::ObservationData
: Observations (OBS) dataRINEX files contain a lot of information,
and this library exposes all data contained by supported
Rinex Types
, that means: a lot.
To learn how to operate this library, refer to: * the examples delivered with the library are detailed and compelling * extracted examples on this page * autotest methods delivered by src/lib.rs
shell
cargo run --example basic
cargo run --example nav-simple
cargo run --example nav-mixed
The ::from_file method lets you parse a local RINEX
file:
rust
use rinex::*;
let path = std::path::PathBuf::from("amel0010.21g");
let rinex = Rinex::from_file(&path).unwrap();
The Rinex Header
contains high level information
```rust use rinex::*;
let rinex = Rinex::fromfile(&PathBuf::from("amel0010.21g")).unwrap(); let header = rinex.getheader(); println!("{:#?}", header);
asserteq!(header.getrinextype(), RinexType::NavigationMessage); asserteq!(header.getconstellation(), constellation::Constellation::Mixed); println!("{:#?}", header.getrinex_version()); println!("Record size: {}", rinex.len()); ```
"Comments" are currently discarded and not exposed by the parser.
length
of a Rinex file returns the record size:
RinexType::ObservationData
RinexType::NavigationMessage
The Record (file content) depends on the file type and constellation.
To learn how to operate the library for the Rinex type you are interested in,
refer to the following section.
Most data is labelized by keys.json refer to that list to determine which fields are available for which Constellation & RINEX revision. Refer to RINEX specifications to interpret each field correctly.
Situation may vary depending on the Rinex File type, this is precisely explained in the following sections.
⚠ ⚠ keys.json is partial
➡ contributions are welcomed, current description might not match your needs (missing keys, etc..)
⚠ ⚠ keys.json might include some mistakes that lead to
➡ corrections are welcomed,
```json keys.json
"NavigationMessage": { <<-- rinex type
"LNVA": <-- a new category should be introduced
to describe V ≥ 4 correctly
"GPS": { <<-- constellation
format is "id": "type",
// this one describes how item1 is identified
"iode": "d19.12", // follow RINEX specifications
"crs": "d19.12", // item2
// [..]
"idot": "d19.12", // item10
"spare": "xxxx", // orbit empty field,
// but continue parsing..
"tgd": "d19.12" // item11
// parsing stops there
}
}
```
Item labelization: follow naming convention & match RINEX specifications closely.
Item types:
Remember:
NAV records expose the following keys to manipulate & search through the records:
* sv
: Satellite Vehicule ID (src/record.rs::Sv)
* svClockBias
: clock bias (s)
* svClockDrift
: clock drift (s.s⁻¹)
* svClockDriftRate
: clock drift (s.s⁻²)
* all keys contained in keys.json for related Rinex revision & constellation
Two main cases for RinexType::NavigationMessage
:
+ Unique constellation (e.g Constellation::GPS
)
+ Constellation::Mixed
(modern use case?)
Sv
)rust
// 'example --nav-simple'
let vehicules: Vec<_> = rinex.get_record().iter()
.map(|s| s["sv"])
.collect();
Sv
tied to Glonass
```rust // 'example --nav-simple' let vehicules: Vec<_> = rinex.get_record().iter() .map(|s| s["sv"]) .collect();
let glo_vehicules: Vec<_> = vehicules.iter()
.filter(|s| s.Sv().unwrap()
.get_constellation() == Constellation::Glonass)
.collecr();
```
svClockBias
(s) and svClockDrift
(s.s⁻¹) for R03
``rust
// 'example --nav-simple'
let sv = Sv::new(Constellation::Glonass, 0x03); //
R03`
let svtomatch = RecordItem::Sv(sv); // filter item
let r03data: Vec<_> = rinex.getrecord().iter()
.map(|s| s["sv"] == svtomatch)
.collect();
let (clk_bias, clk_drift) = (r03_data["svClockBias"], r03_data["svClockDrift"]);
```
WorkInProgress
svHealth
exists for GPS for instance (keys.json) and is a binary word:
rust
// 'example --nav-mixed'
WorkInProgress
WorkInProgress
OBS records expose mainly: * raw carrier phase measurements * pseudo ranges estimates * doppler measurements
WorkInProgress
First thing to do is to determine which data a given file actually contains
rust
// 'example --obs-simple'
let obs_types = header.get_obs_types();
WorkInProgress
Extract pseudo range for a unique vehicule
`̀
rust
// 'example --obs-simple'
let sv = Sv::new(Constellation::GPS, 0x01); // "G01"
let tomatch = RecordItem::Sv(sv); // filter item
let matching: Vec<_> = rinex.getrecord().iter()
.filter(|s| s["sv"] == tomatch)
.collect();
let (pseudorange, raw_phase) = matching["C1C"];
```
Sometimes data is scaled:
TODO
rust
// 'example --obs-mixed'
SigStrength
conditionWorkInProgress
Extract phase + pseudo range
LeapSecond
informationWorkInProgress
rust
// 'example --nav-mixed'
WorkInProgress
rust
// 'example --nav-mixed'
WorkInProgress
rust
// 'example --'