Skip to content

Commit

Permalink
SBAS + Qc (georust#259)
Browse files Browse the repository at this point in the history
SBAS and BRDC Navigation
Improved QC capabilities and reporting features
Integrated plot
Breaking changes in the command line opts
Breaking changes: Graph mode is removed and integrated into analysis mode

---------

Signed-off-by: Guillaume W. Bres <[email protected]>
  • Loading branch information
gwbres authored Jul 28, 2024
1 parent 0fae4d8 commit 783c2aa
Show file tree
Hide file tree
Showing 212 changed files with 11,314 additions and 7,858 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

Thank you for using our toolbox and trying to make it better 🛰️ 🌍

If you are reporting an error related to one of the applications, [follow these guidelines](#applications-error-reporting).
Otherwise, [use those](#core-library-error-reporting) to report core library issues
When reporting applications issues, please follow the first paragraph.
When reporting errors in the core libraries, refer to the second paragraph.

## Applications error reporting

Expand Down
56 changes: 27 additions & 29 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,6 @@ env:
CARGO_TERM_COLOR: always

jobs:

lint:
name: Linter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
name: Install Rust
with:
toolchain: stable
override: true
components: rustfmt, clippy
- uses: actions-rs/cargo@v1
name: Linter
with:
command: fmt
args: --all -- --check
- name: Audit
continue-on-error: true
run: |
cargo install cargo-audit
cargo audit
build:
name: Build
runs-on: ubuntu-latest
Expand All @@ -51,6 +28,23 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y libudev-dev
- uses: actions-rs/cargo@v1
name: Cargo update
with:
command: update

- uses: actions-rs/cargo@v1
name: Linter
with:
command: fmt
args: --all -- --check

- uses: actions-rs/cargo@v1
name: Build (all features)
with:
command: build
args: --all-features --release

- uses: actions-rs/cargo@v1
name: Test
Expand All @@ -64,12 +58,6 @@ jobs:
command: test
args: --verbose --all-features

- uses: actions-rs/cargo@v1
name: Build (all features)
with:
command: build
args: --all-features --release

- uses: actions-rs/toolchain@v1
name: Install nightly
with:
Expand All @@ -90,6 +78,11 @@ jobs:
toolchain: stable
override: true

- uses: actions-rs/cargo@v1
name: Cargo update
with:
command: update

- uses: actions-rs/cargo@v1
name: Build (default)
with:
Expand All @@ -112,6 +105,11 @@ jobs:
toolchain: stable
override: true

- uses: actions-rs/cargo@v1
name: Cargo update
with:
command: update

- uses: actions-rs/cargo@v1
name: Build (default)
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Cargo.lock
*.swp
*.swo
*.patch
*.txt
**/*.rs.bk
.DS_Store

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ It is growing as some sort of Anubis/Teqc/Glab combination. No GUI currently ava
It integrates a PVT and CGGTTS solutions solver.
The application is auto-generated for a few architectures, you can directly
[download it from Github.com](https://github.com/georust/rinex/releases)

* [`tutorials`](tutorials/) is a superset of scripts (Linux/MacOS compatible)
to get started quickly. The examples span pretty much everything our applications allow.
* [`sp3`](sp3/) High Precision Orbits (by IGS)
* [`rnx2crx`](rnx2crx/) is a RINEX compressor (RINEX to Compact RINEX)
* [`crx2rnx`](crx2rnx/) is a CRINEX decompresor (Compact RINEX to RINEX)
Expand All @@ -67,6 +68,8 @@ The application is auto-generated for a few architectures, you can directly
* [`sinex`](sinex/) SNX dedicated core library
* [`ublox-rnx`](ublox-rnx/) is an application to generate RINEX files from Ublox receivers.
This application is currently work in progress
* [`tools`](tools/) are utility scripts and development tools
* [`logs`](logs/) is dedicated to store session logs, if you work within this workspace directly.

## Relevant Ecosystem

Expand Down
Empty file added logs/.gitkeep
Empty file.
11 changes: 10 additions & 1 deletion qc-traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@ edition = "2021"
[features]
default = [] # no features by default

# Unlock processing features
# - Filter designer: design and apply filter ops to GNSS datasets
processing = [
"dep:gnss-rs",
"dep:hifitime",
]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docrs", "--generate-link-to-definition"]

[dependencies]
horrorshow = "0.8"
thiserror = "1"
hifitime = { version = "4.0.0-alpha", optional = true }
gnss-rs = { version = "2.2", features = ["serde", "domes", "cospar"], optional = true }
15 changes: 15 additions & 0 deletions qc-traits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# RINEX/GNSS QC and processing

This crate is a small library to share and implement in other libraries
to form a coherent ecosystem to process and analyze GNSS data.

As an example, this crate is implemented in the RINEX and SP3 libraries, the RINEX-QC
library and the RINEX-Cli application and allows the synthesis of analysis reports
and the processing on GNSS down to navigation.

## Existing Modules

- html: HTML report rendition
- merge: describes how we stack data into an already existing context
- processing: available on crate feature only,
describes a filter designer and processing ops
11 changes: 0 additions & 11 deletions qc-traits/src/html.rs

This file was deleted.

12 changes: 9 additions & 3 deletions qc-traits/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
//! Specific traits to generate RINEX quality reports.
#![doc(html_logo_url = "https://raw.githubusercontent.com/georust/meta/master/logo/logo.png")]
#![doc = include_str!("../README.md")]
#![cfg_attr(docrs, feature(doc_cfg))]

mod html;
pub use html::HtmlReport;
pub mod merge;
pub use merge::{Error as MergeError, Merge};

#[cfg(feature = "processing")]
#[cfg_attr(docrs, doc(cfg(feature = "processing")))]
pub mod processing;
35 changes: 35 additions & 0 deletions qc-traits/src/merge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! Merge traits to extend data contexts
use thiserror::Error;

/// [Merge] specific Errors.
#[derive(Error, Debug)]
pub enum Error {
/// When merging B into A, both types should match
/// otherwise operation in invalid.
#[error("file type mismatch")]
FileTypeMismatch,
/// Some file formats, to remain valid, require that
/// B and A be expressed in the same Timescale to remain valid
#[error("timescale mismatch")]
TimescaleMismatch,
/// Some file formats, to remain valid, require that coordinates
/// from B and A be expressed in the same Reference Frame to remain valid
#[error("reference frame mismatch")]
ReferenceFrameMismatch,
/// Some file formats, to remain valid, require that they are
/// published by the same publisher/agency to be merged to into one another
#[error("data provider (agency) mismatch")]
DataProviderAgencyMismatch,
}

/// Merge Trait is impleted to extend Data Contexts.
pub trait Merge {
/// Merge "rhs" dataset into self, to form extend dataset.
/// We use this for example to extend 24h RINEX to 1week RINEX.
/// When merging File A and B types must match otherwise operation is invalid.
fn merge(&self, rhs: &Self) -> Result<Self, Error>
where
Self: Sized;
/// [Self::merge] mutable implementation.
fn merge_mut(&mut self, rhs: &Self) -> Result<(), Error>;
}
43 changes: 43 additions & 0 deletions qc-traits/src/processing/averaging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use hifitime::{Duration, Epoch};

fn moving_average<T: std::default::Default>(
data: Vec<(Epoch, T)>,
window: Duration,
) -> Vec<(Epoch, T)> {
let mut acc = T::default();
let mut prev_epoch: Option<Epoch> = None;
let mut ret: Vec<(Epoch, T)> = Vec::new();
for (epoch, value) in data {}
ret
}

#[derive(Debug, Clone, Copy)]
pub enum Averager {
MovingAverage(Duration),
}

impl Default for Averager {
fn default() -> Self {
Self::MovingAverage(Duration::from_seconds(600.0_f64))
}
}

impl Averager {
pub fn mov(window: Duration) -> Self {
Self::MovingAverage(window)
}
pub fn eval<T: std::default::Default>(&self, input: Vec<(Epoch, T)>) -> Vec<(Epoch, T)> {
match self {
Self::MovingAverage(dt) => moving_average(input, *dt),
}
}
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_moving_average() {
let mov = Averager::mov(Duration::from_seconds(10.0_f64));
}
}
96 changes: 96 additions & 0 deletions qc-traits/src/processing/decim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use crate::processing::{FilterItem, ItemError};
use hifitime::Duration;
use thiserror::Error;

/// Decimation filter parsing error
#[derive(Error, Debug)]
pub enum Error {
#[error("invalid decimated item")]
InvalidDecimItem(#[from] ItemError),
#[error("failed to parse decimation attribute \"{0}\"")]
AttributeParsingError(String),
}

/// Type of decimation filter
#[derive(Clone, Debug, PartialEq)]
pub enum DecimationFilterType {
/// Simple modulo decimation
Modulo(u32),
/// Duration decimation
Duration(Duration),
}

#[derive(Clone, Debug, PartialEq)]
pub struct DecimationFilter {
/// Type of decimation filter
pub filter: DecimationFilterType,
/// Optional decimated item.
/// When item is None, all data is to be decimated.
/// When item is specified, only that subset is to be decimated.
pub item: Option<FilterItem>,
}

impl DecimationFilter {
/// Builds a new Duration decimation filter
pub fn duration(dt: Duration) -> Self {
Self {
item: None,
filter: DecimationFilterType::Duration(dt),
}
}
/// Builds new Modulo decimation filter
pub fn modulo(modulo: u32) -> Self {
Self {
item: None,
filter: DecimationFilterType::Modulo(modulo),
}
}
/// Adds targetted item to be decimated
pub fn with_item(&self, item: FilterItem) -> Self {
let mut s = self.clone();
s.item = Some(item.clone());
s
}
}

/// The [Decimate] trait is implemented to reduce data rate prior analysis.
pub trait Decimate {
/// Immutable decimation
fn decimate(&self, f: &DecimationFilter) -> Self;
/// Mutable decimation
fn decimate_mut(&mut self, f: &DecimationFilter);
}

impl std::str::FromStr for DecimationFilter {
type Err = Error;
fn from_str(content: &str) -> Result<Self, Self::Err> {
let items: Vec<&str> = content.trim().split(':').collect();
if let Ok(dt) = Duration::from_str(items[0].trim()) {
Ok(Self {
item: {
if items.len() > 1 {
let item = FilterItem::from_str(items[1].trim())?;
Some(item)
} else {
None // no subset description
}
},
filter: DecimationFilterType::Duration(dt),
})
} else if let Ok(r) = items[0].trim().parse::<u32>() {
Ok(Self {
item: {
if items.len() > 1 {
let item = FilterItem::from_str(items[1].trim())?;
Some(item)
} else {
None
}
},
filter: DecimationFilterType::Modulo(r),
})
} else {
Err(Error::AttributeParsingError(items[0].to_string()))
}
}
}
Loading

0 comments on commit 783c2aa

Please sign in to comment.