Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move orbital source to resolve() instead of new() #55

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions examples/spp/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use gnss_rtk::prelude::{
// Orbit source example
struct Orbits {}

impl OrbitSource for Orbits {
impl OrbitSource for &mut Orbits {
// For each requested "t" and "sv",
// if we can, we should resolve the SV [Orbit].
// If interpolation is to be used (depending on your apps), you can
Expand Down Expand Up @@ -66,7 +66,7 @@ impl MyDataSource {

pub fn main() {
// Build the Orbit source
let orbits = Orbits {};
let mut orbits = Orbits {};

// The preset API is useful to quickly deploy depending on your application.
// Static presets target static positioning.
Expand All @@ -79,7 +79,6 @@ pub fn main() {
// We deploy without apriori knowledge.
// The solver will initialize itself.
None, // Tie the Orbit source
orbits,
);

// The solver needs to be mutable, due to the iteration process.
Expand All @@ -89,7 +88,7 @@ pub fn main() {

// Browse your data source (This is an Example)
while let Some((epoch, candidates)) = source.next() {
match solver.resolve(epoch, &candidates) {
match solver.resolve(epoch, &candidates, &mut orbits) {
Ok((_epoch, solution)) => {
// Receiver offset to preset timescale
let (_clock_offset, _timescale) = (solution.dt, solution.timescale);
Expand Down
4 changes: 2 additions & 2 deletions src/cfg/method.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::prelude::Error;

#[cfg(feature = "serde")]
use serde::Deserialize; //, Serialize};
use serde::{Deserialize, Serialize};

/// Solving method
#[derive(Default, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Method {
/// Single Point Positioning (SPP).
/// Code based navigation on a single carrier frequency.
Expand Down
45 changes: 36 additions & 9 deletions src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub enum Error {

/// Geometry strategy
#[derive(Default, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum GeometryStrategy {
/// Algorithm selects best elevation angles
#[default]
Expand All @@ -35,7 +35,7 @@ pub enum GeometryStrategy {
/// selects appropriate settings. Failing to select
/// the apropriate [Profile] will degrade the solutions.
#[derive(Default, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Profile {
/// Receiver held in static.
/// Typically used in Geodetic surveys (GNSS stations Referencing)
Expand All @@ -47,7 +47,7 @@ pub enum Profile {
}

#[derive(Default, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ElevationMappingFunction {
/// a + b * e-elev/c
pub a: f64,
Expand All @@ -64,7 +64,7 @@ impl ElevationMappingFunction {
}

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WeightMatrix {
/// a + b e-elev/c
MappingFunction(ElevationMappingFunction),
Expand Down Expand Up @@ -162,7 +162,7 @@ fn default_tdop_threshold() -> Option<f64> {
}

#[derive(Default, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
/// System Internal Delay as defined by BIPM in
/// "GPS Receivers Accurate Time Comparison" : the (frequency dependent)
/// time delay introduced by the combination of:
Expand All @@ -178,7 +178,7 @@ pub struct InternalDelay {
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SolverOpts {
/// GDOP threshold to invalidate ongoing GDOP
#[cfg_attr(feature = "serde", serde(default = "default_gdop_threshold"))]
Expand Down Expand Up @@ -211,7 +211,7 @@ impl Default for SolverOpts {
}

#[derive(Default, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct FilterOpts {
/// Weight Matrix
#[cfg_attr(feature = "serde", serde(default = "default_weight_matrix"))]
Expand Down Expand Up @@ -302,8 +302,8 @@ impl Default for Modeling {
}
}

#[derive(Default, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Config {
/// Type of solutions to form.
#[cfg_attr(feature = "serde", serde(default))]
Expand Down Expand Up @@ -440,3 +440,30 @@ impl Config {
s
}
}

impl Default for Config {
fn default() -> Self {
Self {
interp_order: 11,
max_tropo_bias: 30.0,
max_iono_bias: 30.0,
min_sv_elev: Some(10.0),
timescale: TimeScale::GPST,
sol_type: Default::default(),
method: Default::default(),
profile: Default::default(),
remote_site: Default::default(),
fixed_altitude: Default::default(),
code_smoothing: Default::default(),
int_delay: Default::default(),
arp_enu: Default::default(),
solver: Default::default(),
externalref_delay: Default::default(),
max_sv_occultation_percent: Default::default(),
min_sv_azim: Default::default(),
max_sv_azim: Default::default(),
min_snr: Default::default(),
modeling: Default::default(),
}
}
}
4 changes: 2 additions & 2 deletions src/navigation/filter.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use nalgebra::{base::dimension::U8, OMatrix, OVector, Vector3};

#[cfg(feature = "serde")]
use serde::Deserialize;
use serde::{Deserialize, Serialize};

use super::{Input, Output};
use crate::prelude::{Epoch, Error};

/// Navigation Filter.
#[derive(Default, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Filter {
/// None: solver filter completely bypassed. Lighter calculations, no iterative behavior.
None,
Expand Down
4 changes: 2 additions & 2 deletions src/navigation/solutions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ pub use validator::InvalidationCause;
pub type InstrumentBias = HashMap<(SV, Carrier), f64>;

#[cfg(feature = "serde")]
use serde::Deserialize;
use serde::{Deserialize, Serialize};

#[derive(Debug, Copy, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PVTSolutionType {
/// Default, complete solution with Position,
/// Velocity and Time components. Requires either
Expand Down
46 changes: 22 additions & 24 deletions src/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,7 @@ pub enum Error {
}

/// [Solver] to resolve [PVTSolution]s.
pub struct Solver<O: OrbitSource> {
/// [OrbitSource]
orbit: O,
pub struct Solver {
/// Solver parametrization
pub cfg: Config,
/// Initial [Orbit] either forwarded by User
Expand Down Expand Up @@ -215,7 +213,7 @@ fn signal_quality_filter(min_snr: f64, pool: &mut Vec<Candidate>) {
})
}

impl<O: OrbitSource> Solver<O> {
impl Solver {
const ALMANAC_LOCAL_STORAGE: &str = ".cache";

fn nyx_anise_de440s_bsp() -> MetaFile {
Expand Down Expand Up @@ -319,10 +317,11 @@ impl<O: OrbitSource> Solver<O> {
pub fn new_almanac_frame(
cfg: &Config,
initial: Option<Orbit>,
orbit: O,
almanac: Almanac,
frame: Frame,
) -> Self {
debug!("Deployed with {:#?}", cfg);

// Print more information
if cfg.method == Method::SPP && cfg.max_sv_occultation_percent.is_some() {
warn!("occultation filter is not meaningful in SPP mode");
Expand All @@ -339,7 +338,6 @@ impl<O: OrbitSource> Solver<O> {
// let almanac = Arc::new(almanac);

Self {
orbit,
almanac,
earth_cef: frame,
initial,
Expand All @@ -362,31 +360,30 @@ impl<O: OrbitSource> Solver<O> {
/// You have to take that into account, especially when operating in Fixed Altitude
/// or Time Only modes.
/// - orbit: [OrbitSource] must be provided for Direct (1D) PPP
pub fn new(cfg: &Config, initial: Option<Orbit>, orbit: O) -> Result<Self, Error> {
pub fn new(cfg: &Config, initial: Option<Orbit>) -> Result<Self, Error> {
let (almanac, earth_cef) = Self::build_almanac_frame_model()?;
Ok(Self::new_almanac_frame(
cfg, initial, orbit, almanac, earth_cef,
))
Ok(Self::new_almanac_frame(cfg, initial, almanac, earth_cef))
}
/// Create new Position [Solver] without knowledge of apriori position (full survey)
pub fn new_survey(cfg: &Config, orbit: O) -> Result<Self, Error> {
Self::new(cfg, None, orbit)
pub fn new_survey(cfg: &Config) -> Result<Self, Error> {
Self::new(cfg, None)
}
/// Create new Position [Solver] without knowledge of apriori position (full survey)
/// and prefered [Almanac] and [Frame] to work with
pub fn new_survey_almanac_frame(
cfg: &Config,
orbit: O,
almanac: Almanac,
frame: Frame,
) -> Self {
Self::new_almanac_frame(cfg, None, orbit, almanac, frame)
pub fn new_survey_almanac_frame(cfg: &Config, almanac: Almanac, frame: Frame) -> Self {
Self::new_almanac_frame(cfg, None, almanac, frame)
}

/// [PVTSolution] resolution attempt.
/// ## Inputs
/// - t: desired [Epoch]
/// - pool: list of [Candidate]
pub fn resolve(&mut self, t: Epoch, pool: &[Candidate]) -> Result<(Epoch, PVTSolution), Error> {
pub fn resolve<O: OrbitSource>(
&mut self,
t: Epoch,
pool: &[Candidate],
ref mut orbit: O,
) -> Result<(Epoch, PVTSolution), Error> {
let min_required = self.min_sv_required();
if pool.len() < min_required {
// no need to proceed further
Expand Down Expand Up @@ -421,10 +418,8 @@ impl<O: OrbitSource> Solver<O> {
.iter()
.filter_map(|cd| match cd.transmission_time(&self.cfg) {
Ok((t_tx, dt_tx)) => {
let orbits = &mut self.orbit;
debug!("{} ({}) : signal propagation {}", cd.t, cd.sv, dt_tx);
if let Some(tx_orbit) =
orbits.next_at(t_tx, cd.sv, self.earth_cef, interp_order)
if let Some(tx_orbit) = orbit.next_at(t_tx, cd.sv, self.earth_cef, interp_order)
{
let orbit = Self::rotate_orbit_dcm3x3(
cd.t,
Expand Down Expand Up @@ -556,7 +551,10 @@ impl<O: OrbitSource> Solver<O> {
if retained {
debug!("{}({}) - tropo delay {:.3E}[m]", cd.t, cd.sv, cd.tropo_bias);
} else {
debug!("{}({}) - rejected (extreme tropo delay)", cd.t, cd.sv);
debug!(
"{}({}) - rejected (extreme tropo delay={:.3e})",
cd.t, cd.sv, cd.tropo_bias
);
}
retained
});
Expand Down
Loading
Loading