Skip to content

Commit

Permalink
clk interpolation will always be required..
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume W. Bres <[email protected]>
  • Loading branch information
gwbres committed Mar 6, 2024
1 parent b2a47bd commit 0532aa6
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 133 deletions.
12 changes: 0 additions & 12 deletions rinex-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ pub struct Context {
/// 1. manually defined by CLI
/// 2. determined from dataset
pub rx_ecef: Option<(f64, f64, f64)>,
/// True if (high precision) CLK product needs to be interpolated.
/// False if both CLK and OBS products are not present.
/// False if both are present but this is a high quality/state of the art context.
pub needs_clock_interpolation: bool,
}

impl Context {
Expand Down Expand Up @@ -153,16 +149,8 @@ impl Context {
let data_stem = Self::context_stem(&data);
let data_position = data.ground_position();

let needs_clock_interpolation = data.needs_clock_interpolation();
if !needs_clock_interpolation {
info!("coherent precise products detected: interpolation is not required");
} else {
warn!("incoherent CLK/OBS products: interpolation will be needed");
}

Ok(Self {
data,
needs_clock_interpolation,
quiet: cli.matches.get_flag("quiet"),
workspace: {
let path = match std::env::var("RINEX_WORKSPACE") {
Expand Down
49 changes: 11 additions & 38 deletions rinex-cli/src/positioning/ppp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,45 +68,18 @@ where
* 3. Radio last option: always feasible
*/
let clock_state = if let Some(clk) = clk_data {
if ctx.needs_clock_interpolation {
if let Some((_, profile)) = clk.precise_sv_clock_interpolate(*t, *sv) {
(
profile.bias,
profile.drift.unwrap_or(0.0),
profile.drift_change.unwrap_or(0.0),
)
} else {
/*
* interpolation failure.
* Do not interpolate other products: SV will not be presented.
*/
continue;
}
if let Some((_, profile)) = clk.precise_sv_clock_interpolate(*t, *sv) {
(
profile.bias,
profile.drift.unwrap_or(0.0),
profile.drift_change.unwrap_or(0.0),
)
} else {
if let Some(profile) = clk
.precise_sv_clock()
.filter_map(|(clk_t, clk_sv, _, profile)| {
if clk_t == *t && clk_sv == *sv {
Some(profile)
} else {
None
}
})
.reduce(|k, _| k)
{
(
profile.bias,
profile.drift.unwrap_or(0.0),
profile.drift_change.unwrap_or(0.0),
)
} else {
/*
* When using high precision products it's better not to attempt
* this in other products, which would mix high and low precision products
* in the solution. We simply abort.
*/
continue;
}
/*
* interpolation failure.
* Do not interpolate other products: SV will not be presented.
*/
continue;
}
} else if sp3_has_clock {
panic!("sp3 (clock) not ready yet: prefer broadcast or clk product");
Expand Down
83 changes: 0 additions & 83 deletions rinex/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ use horrorshow::{box_html, helper::doctype, html, RenderBox};
#[cfg(feature = "qc")]
use rinex_qc_traits::HtmlReport;

use hifitime::TimeScale;

#[derive(Debug, Error)]
pub enum Error {
#[error("can only form a RINEX context from a directory, not a single file")]
Expand Down Expand Up @@ -490,47 +488,6 @@ impl RnxContext {
false
}
}
/// Returns true if High precision Clock product(s) will have to to be interpolated.
/// Clock products do not have to be interpolated if they strictly match signals observations.
/// That is true if you're using overlapping and state of the art Clock and OBS RINEX files.
pub fn needs_clock_interpolation(&self) -> bool {
if let Some(obs) = &self.obs {
let obs = obs.data();
if let Some(clk) = &self.clk {
let clk = clk.data();
let (first_obs_epoch, last_obs_epoch) =
(obs.first_epoch(), obs.last_epoch().unwrap_or_default());
let (first_clk_epoch, last_clk_epoch) =
(clk.first_epoch(), clk.last_epoch().unwrap_or_default());

let (obs_sampling, clk_sampling) = (
obs.dominant_sample_rate().unwrap_or_default(),
clk.dominant_sample_rate().unwrap_or_default(),
);

let last_delta = (last_clk_epoch.to_duration()
- last_obs_epoch.to_duration_in_time_scale(TimeScale::UTC))
.to_seconds();

!(
// [a] CLK should start prior or at the same time as observations.
first_obs_epoch < first_clk_epoch
// [b] tolerate one symbol difference at the end of each file, no more.
&& last_delta <= 2.0 * obs_sampling.to_seconds()
// [c] sampling should be steady: no gaps
&& obs.steady_sampling()
// [c] sampling should be steady: no gaps
&& clk.steady_sampling()
// [d] sampling should be identical: c+d <=> strict equaliy
&& obs.dominant_sample_rate() == clk.dominant_sample_rate()
)
} else {
false
}
} else {
false
}
}
// /// Removes "incomplete" Epochs from OBS Data
// pub fn complete_epoch_filter(&mut self, min_snr: Option<Snr>) {
// let total = self.primary_data().epoch().count();
Expand Down Expand Up @@ -726,43 +683,3 @@ impl HtmlReport for RnxContext {
}
}
}

#[cfg(test)]
mod test {
use super::*;
use std::path::Path;
#[test]
#[cfg(feature = "flate2")]
fn test_clk_needs_interp() {
let obs_path = env!("CARGO_MANIFEST_DIR").to_owned()
+ "/../test_resources/CRNX/V3/ESBC00DNK_R_20201770000_01D_30S_MO.crx.gz";

for (clk_path, needs_interp) in [
("V2/COD20352.CLK", true),
("V3/GRG0MGXFIN_20201770000_01D_30S_CLK.CLK.gz", false),
] {
let obs_path = Path::new(&obs_path).to_path_buf();
let mut ctx = RnxContext::new(&obs_path).unwrap();
assert!(
ctx.has_observation_data(),
"OBS product not correctly latched"
);

let clk_path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("test_resources")
.join("CLK")
.join(clk_path)
.to_path_buf();
ctx.load(&clk_path).unwrap();
assert!(ctx.has_clock_data(), "CLK product not correctly latched");

assert_eq!(
ctx.needs_clock_interpolation(),
needs_interp,
"test failed for CLK \"{}\"",
clk_path.display()
);
}
}
}

0 comments on commit 0532aa6

Please sign in to comment.