use crate::{
navigation::{sv::SVContribution, DilutionOfPrecision, State},
prelude::{Epoch, TimeScale},
};
#[cfg(feature = "serde")]
use serde::Serialize;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum PVTSolutionType {
PPP = 0,
RTK = 1,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct PVTSolution {
pub solution_type: PVTSolutionType,
pub epoch: Epoch,
pub pos_m: (f64, f64, f64),
pub vel_m_s: (f64, f64, f64),
pub lat_long_alt_deg_deg_m: (f64, f64, f64),
pub timescale: TimeScale,
pub clock_offset_s: f64,
pub sv: Vec<SVContribution>,
pub gdop: f64,
pub vdop: f64,
pub hdop: f64,
pub tdop: f64,
}
impl PVTSolution {
pub(crate) fn new(
epoch: Epoch,
uses_rtk: bool,
state: &State,
dop: &DilutionOfPrecision,
contributions: &[SVContribution],
) -> Self {
let pos_vel_ecef_m = state.to_position_velocity_ecef_m();
let (clock_offset_s, _) = state.clock_profile_s();
Self {
epoch,
solution_type: if uses_rtk {
PVTSolutionType::RTK
} else {
PVTSolutionType::PPP
},
gdop: dop.gdop,
tdop: dop.tdop,
vdop: dop.vdop,
hdop: dop.hdop,
clock_offset_s,
lat_long_alt_deg_deg_m: (
state.lat_long_alt_deg_deg_km.0,
state.lat_long_alt_deg_deg_km.1,
state.lat_long_alt_deg_deg_km.2 * 1.0E3,
),
sv: contributions.to_vec(),
timescale: state.epoch.time_scale,
pos_m: (pos_vel_ecef_m[0], pos_vel_ecef_m[1], pos_vel_ecef_m[2]),
vel_m_s: (pos_vel_ecef_m[3], pos_vel_ecef_m[4], pos_vel_ecef_m[5]),
}
}
}