use crate::binrw_util;
use binrw::binrw;
use core::fmt;
use num_enum::{FromPrimitive, IntoPrimitive};
use super::att_euler::AttitudeMode;
use super::pvt_geodetic::{Datum, PvtMode};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GnssMode {
raw: u8,
pub pvt_mode: PvtMode,
pub attitude_mode: AttitudeMode,
}
impl GnssMode {
pub fn from_byte(value: u8) -> Self {
Self {
raw: value,
pvt_mode: PvtMode::from(value),
attitude_mode: AttitudeMode::from((value >> 4) as u16),
}
}
pub fn raw(&self) -> u8 {
self.raw
}
}
impl fmt::Display for GnssMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PVT: {}, Attitude: {}", self.pvt_mode, self.attitude_mode)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoPrimitive)]
#[repr(u8)]
pub enum INSCouplingMode {
LooselyCoupled = 0,
#[num_enum(catch_all)]
Unknown(u8),
}
#[allow(clippy::derivable_impls)]
impl Default for INSCouplingMode {
fn default() -> Self {
INSCouplingMode::LooselyCoupled
}
}
impl From<u16> for INSCouplingMode {
fn from(value: u16) -> Self {
match value & 0x07 {
0 => INSCouplingMode::LooselyCoupled,
x => INSCouplingMode::Unknown(x as u8),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoPrimitive)]
#[repr(u8)]
pub enum INSSolutionLocation {
MainGnssAntenna = 0,
FirstPoi = 1,
#[num_enum(catch_all)]
Unknown(u8),
}
#[allow(clippy::derivable_impls)]
impl Default for INSSolutionLocation {
fn default() -> Self {
INSSolutionLocation::MainGnssAntenna
}
}
impl From<u16> for INSSolutionLocation {
fn from(value: u16) -> Self {
match (value >> 3) & 0x07 {
0 => INSSolutionLocation::MainGnssAntenna,
1 => INSSolutionLocation::FirstPoi,
x => INSSolutionLocation::Unknown(x as u8),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum INSError {
None = 0,
PositionProhibited = 7,
NotRequested = 20,
NotEnoughSensorMeasurements = 21,
StaticAlignmentOngoing = 23,
WaitingForGnssPvt = 24,
InMotionAlignmentOngoing = 28,
WaitingForGnssHeading = 29,
WaitingForImuSync = 30,
StdDevExceedsLimit = 31,
UnsupportedSettings = 32,
IncorrectImuOrientation = 35,
#[num_enum(catch_all)]
Unknown(u8),
}
#[allow(clippy::derivable_impls)]
impl Default for INSError {
fn default() -> Self {
INSError::None
}
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeod {
#[br(map = binrw_util::map_u4)]
#[bw(map = binrw_util::unmap_u4)]
pub tow: Option<u32>,
#[br(map = binrw_util::map_u2)]
#[bw(map = binrw_util::unmap_u2)]
pub wnc: Option<u16>,
gnss_mode_raw: u8,
pub error: u8,
pub info: u16,
#[br(map = binrw_util::map_u2)]
#[bw(map = binrw_util::unmap_u2)]
pub gnss_age: Option<u16>,
#[br(map = binrw_util::map_f8)]
#[bw(map = binrw_util::unmap_f8)]
pub latitude: Option<f64>,
#[br(map = binrw_util::map_f8)]
#[bw(map = binrw_util::unmap_f8)]
pub longitude: Option<f64>,
#[br(map = binrw_util::map_f8)]
#[bw(map = binrw_util::unmap_f8)]
pub height: Option<f64>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub undulation: Option<f32>,
#[br(map = binrw_util::map_u2)]
#[bw(map = binrw_util::unmap_u2)]
pub accuracy: Option<u16>,
#[br(map = binrw_util::map_u2)]
#[bw(map = binrw_util::unmap_u2)]
pub latency: Option<u16>,
#[br(map = binrw_util::map_datum)]
#[bw(map = binrw_util::unmap_datum)]
pub datum: Option<Datum>,
_reserved: u8,
pub sb_list: u16,
#[br(if(sb_list & 1 == 1))]
pub pos_std_dev: Option<INSNavGeodPosStdDev>,
#[br(if((sb_list >> 1) & 1 == 1))]
pub att: Option<INSNavGeodAtt>,
#[br(if((sb_list >> 2) & 1 == 1))]
pub att_std_dev: Option<INSNavGeodAttStdDev>,
#[br(if((sb_list >> 3) & 1 == 1))]
pub vel: Option<INSNavGeodVel>,
#[br(if((sb_list >> 4) & 1 == 1))]
pub vel_std_dev: Option<INSNavGeodVelStdDev>,
#[br(if((sb_list >> 5) & 1 == 1))]
pub pos_cov: Option<INSNavGeodPosCov>,
#[br(if((sb_list >> 6) & 1 == 1))]
pub att_cov: Option<INSNavGeodAttCov>,
#[br(if((sb_list >> 7) & 1 == 1))]
pub vel_cov: Option<INSNavGeodVelCov>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodPosStdDev {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub longitude_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub latitude_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub height_std_dev: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodAtt {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub heading: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub pitch: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub roll: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodAttStdDev {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub heading_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub pitch_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub roll_std_dev: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodVel {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub ve: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub vn: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub vu: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodVelStdDev {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub ve_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub vn_std_dev: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub vu_std_dev: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodPosCov {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub latitude_longitude_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub latitude_height_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub longitude_height_cov: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodVelCov {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub ve_vn_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub ve_vu_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub vn_vu_cov: Option<f32>,
}
#[binrw]
#[derive(Clone, Debug)]
pub struct INSNavGeodAttCov {
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub heading_pitch_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub heading_roll_cov: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub pitch_roll_cov: Option<f32>,
}
impl INSNavGeod {
pub fn gnss_mode(&self) -> GnssMode {
GnssMode::from_byte(self.gnss_mode_raw)
}
pub fn pvt_mode(&self) -> PvtMode {
PvtMode::from(self.gnss_mode_raw & 0x0F)
}
pub fn attitude_mode(&self) -> AttitudeMode {
AttitudeMode::from((self.gnss_mode_raw >> 4) as u16)
}
pub fn ins_error(&self) -> INSError {
INSError::from(self.error)
}
pub fn coupling_mode(&self) -> INSCouplingMode {
INSCouplingMode::from(self.info)
}
pub fn solution_location(&self) -> INSSolutionLocation {
INSSolutionLocation::from(self.info)
}
pub fn heading_ambiguity_fixed(&self) -> bool {
self.info & (1 << 6) != 0
}
pub fn zero_velocity_constraints(&self) -> bool {
self.info & (1 << 7) != 0
}
pub fn imu_orientation_converged(&self) -> bool {
self.info & (1 << 8) != 0
}
}