diff --git a/rinex-cli/src/cli/mod.rs b/rinex-cli/src/cli/mod.rs index ae21d3358..9a2495a54 100644 --- a/rinex-cli/src/cli/mod.rs +++ b/rinex-cli/src/cli/mod.rs @@ -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 { @@ -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") { diff --git a/rinex-cli/src/positioning/ppp/mod.rs b/rinex-cli/src/positioning/ppp/mod.rs index ebb5f338a..9071c4d92 100644 --- a/rinex-cli/src/positioning/ppp/mod.rs +++ b/rinex-cli/src/positioning/ppp/mod.rs @@ -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"); diff --git a/rinex/src/context/mod.rs b/rinex/src/context/mod.rs index 2447e4380..f105eadca 100644 --- a/rinex/src/context/mod.rs +++ b/rinex/src/context/mod.rs @@ -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")] @@ -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) { // let total = self.primary_data().epoch().count(); @@ -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() - ); - } - } -}