use crate::units::Radians;
macro_rules! interpolate {
($lhs:ident, $rhs:ident, $factor:ident, $var:ident) => {{
$lhs.$var + $factor * ($rhs.$var - $lhs.$var)
}};
}
macro_rules! interpolate_optional {
($lhs:ident, $rhs:ident, $factor:ident, $var:ident) => {{
if let Some(l) = $lhs.$var {
if let Some(r) = $rhs.$var {
Some(l + $factor * (r - l))
} else {
None
}
} else {
None
}
}};
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[allow(missing_docs)]
pub struct Point {
pub time: f64,
pub longitude: Radians<f64>,
pub latitude: Radians<f64>,
pub altitude: f64,
pub roll: Radians<f64>,
pub pitch: Radians<f64>,
pub yaw: Radians<f64>,
pub distance: Option<f64>,
pub x_velocity: Option<f64>,
pub y_velocity: Option<f64>,
pub z_velocity: Option<f64>,
pub wander_angle: Option<Radians<f64>>,
pub x_acceleration: Option<f64>,
pub y_acceleration: Option<f64>,
pub z_acceleration: Option<f64>,
pub x_angular_rate: Option<Radians<f64>>,
pub y_angular_rate: Option<Radians<f64>>,
pub z_angular_rate: Option<Radians<f64>>,
pub accuracy: Option<Accuracy>,
}
impl Point {
pub fn interpolate(&self, other: &Point, time: f64) -> Point {
let factor = (time - self.time) / (other.time - self.time);
Point {
time: interpolate!(self, other, factor, time),
longitude: interpolate!(self, other, factor, longitude),
latitude: interpolate!(self, other, factor, latitude),
altitude: interpolate!(self, other, factor, altitude),
roll: interpolate!(self, other, factor, roll),
pitch: interpolate!(self, other, factor, pitch),
yaw: interpolate!(self, other, factor, yaw),
distance: interpolate_optional!(self, other, factor, distance),
x_velocity: interpolate_optional!(self, other, factor, x_velocity),
y_velocity: interpolate_optional!(self, other, factor, y_velocity),
z_velocity: interpolate_optional!(self, other, factor, z_velocity),
wander_angle: interpolate_optional!(self, other, factor, wander_angle),
x_acceleration: interpolate_optional!(self, other, factor, x_acceleration),
y_acceleration: interpolate_optional!(self, other, factor, y_acceleration),
z_acceleration: interpolate_optional!(self, other, factor, z_acceleration),
x_angular_rate: interpolate_optional!(self, other, factor, x_angular_rate),
y_angular_rate: interpolate_optional!(self, other, factor, y_angular_rate),
z_angular_rate: interpolate_optional!(self, other, factor, z_angular_rate),
accuracy: if let Some(a1) = self.accuracy {
other.accuracy.map(|a2| a1.interpolate(&a2, time))
} else {
None
},
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[allow(missing_docs)]
pub struct Accuracy {
pub time: f64,
pub x: f64,
pub y: f64,
pub z: f64,
pub roll: Radians<f64>,
pub pitch: Radians<f64>,
pub yaw: Radians<f64>,
pub pdop: f64,
pub satellite_count: Option<SatelliteCount>,
}
impl Accuracy {
pub fn interpolate(&self, other: &Accuracy, time: f64) -> Accuracy {
let factor = (time - self.time) / (other.time - self.time);
Accuracy {
time: interpolate!(self, other, factor, time),
x: interpolate!(self, other, factor, x),
y: interpolate!(self, other, factor, y),
z: interpolate!(self, other, factor, z),
roll: interpolate!(self, other, factor, roll),
pitch: interpolate!(self, other, factor, pitch),
yaw: interpolate!(self, other, factor, yaw),
pdop: interpolate!(self, other, factor, pdop),
satellite_count: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SatelliteCount {
Unspecified(u16),
Specified {
gps: u16,
glonass: u16,
},
}
impl Default for SatelliteCount {
fn default() -> SatelliteCount {
SatelliteCount::Unspecified(0)
}
}