From 8d83418aa18d3430ea72ef1ef55d9030f9b92aab Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Tue, 29 Aug 2023 22:51:31 +1000 Subject: [PATCH 1/3] Tweaks --- rinex/src/bibliography.rs | 2 +- rinex/src/navigation/health/gal.rs | 138 ++++++++++++++-------------- rinex/src/navigation/health/gps.rs | 138 +++++++++++++++++++--------- rinex/src/navigation/health/qzss.rs | 100 ++++++++++++-------- 4 files changed, 227 insertions(+), 151 deletions(-) diff --git a/rinex/src/bibliography.rs b/rinex/src/bibliography.rs index 1b0f3eff9..a6a575a25 100644 --- a/rinex/src/bibliography.rs +++ b/rinex/src/bibliography.rs @@ -39,6 +39,6 @@ pub enum Bibliography { /// [DOI](https://cdn.taoglas.com/wp-content/uploads/pdf/Multipath-Analysis-Using-Code-Minus-Carrier-Technique-in-GNSS-Antennas-_WhitePaper_VP__Final-1.pdf). MpTaoglas, /// QZSS Signal and Constellation interface specifications. - /// [DOI](https://qzss.go.jp/en/technical/download/pdf/ps-is-qzss/is-qzss-pnt-004.pdf) + /// [DOI](https://qzss.go.jp/en/technical/download/pdf/ps-is-qzss/is-qzss-pnt-005.pdf) QzssPnt, } diff --git a/rinex/src/navigation/health/gal.rs b/rinex/src/navigation/health/gal.rs index ddc6aade6..fd43443a8 100644 --- a/rinex/src/navigation/health/gal.rs +++ b/rinex/src/navigation/health/gal.rs @@ -1,88 +1,84 @@ -//! GAL Sv Health specifications -use bitflags::bitflags; +//! GAL SV Health specifications -/// GAL Sv Health indication -#[derive(Debug, Clone, PartialEq, PartialOrd)] +/// GAL INAV & FNAV SV Health indication. +/// See [Bibliography::RINEX3] for more information. +#[derive(Default, Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] -pub enum GALHealth { - /// GAL Legacy Sv Health indication - LNAV(LegacyHealth), - /// GAL INAV Sv Health indication - INAV(Health), - /// GAL FNAV Sv Health indication - FNAV(Health), +pub struct GALHealth { + /// E1-B Data Validity Status + /// `false` = Navigation data valid + /// `true` = Working without guarantee + e1b_dvs: bool, + /// E1-B/C Signal Health Status + /// 0 = Signal OK + /// 1 = Signal out of service + /// 2 = Signal will be out of service + /// 3 = Signal Component currently in Test + e1b_hs: u8, + /// E5a Data Validity Status + /// `false` = Navigation data valid + /// `true` = Working without guarantee + e5a_dvs: bool, + /// E5a Signal Health Status + /// 0 = Signal OK + /// 1 = Signal out of service + /// 2 = Signal will be out of service + /// 3 = Signal Component currently in Test + e5a_hs: u8, + /// E5b Data Validity Status + /// `false` = Navigation data valid + /// `true` = Working without guarantee + e5b_dvs: bool, + /// E5b Signal Health Status + /// 0 = Signal OK + /// 1 = Signal out of service + /// 2 = Signal will be out of service + /// 3 = Signal Component currently in Test + e5b_hs: u8, } -impl Default for GALHealth { - fn default() -> Self { - Self::LNAV(LegacyHealth::default()) +impl std::fmt::UpperExp for GALHealth { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let value: u32 = u32::from(self); + write!(f, "{:e}", value as f32) } } -impl GALHealth { - /// Unwraps self as [`LegacyHealth`] indicator - pub(crate) fn lnav(&self) -> Option<&LegacyHealth> { - match self { - Self::LNAV(h) => Some(h), - _ => None, +impl From for GALHealth { + fn from(value: u32) -> Self { + Self { + e1b_dvs: (value & 0b1) != 0, + e1b_hs: (value & 0b110 >> 1) as u8, + e5a_dvs: (value & 0b1000) != 0, + e5a_hs: (value & 0b110000 >> 4) as u8, + e5b_dvs: (value & 0b1000000) != 0, + e5b_hs: (value & 0b110000000 >> 7) as u8, } } - /// Unwraps self as [`Health`] indicator - pub(crate) fn fnav(&self) -> Option<&Health> { - match self { - Self::FNAV(h) => Some(h), - _ => None, +} + +impl From<&GALHealth> for u32 { + fn from(value: &GALHealth) -> Self { + let mut ret: u32 = 0; + + if value.e1b_dvs { + ret |= 0b1; } - } - /// Unwraps self as [`Health`] indicator - pub(crate) fn inav(&self) -> Option<&Health> { - match self { - Self::INAV(h) => Some(h), - _ => None, + + ret |= (value.e1b_hs as u32) & 0b11 << 1; + + if value.e5a_dvs { + ret |= 0b1000; } - } -} -bitflags! { - /// GAL Legacy Sv Health indication. - /// See [Bibliography::RINEX3] for more information. - #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] - #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct LegacyHealth: u64 { - const E1B_DVS = 0x01; - const E1B_HS0 = 0x02; - const E1B_HS1 = 0x04; - const E5A_DVS = 0x08; - const E5A_HS0 = 0x10; - const E5A_HS1 = 0x20; - const E5B_HS0 = 0x40; - const E5B_HS1 = 0x80; - } -} + ret |= (value.e5a_hs as u32) & 0b11 << 4; -impl std::fmt::UpperExp for LegacyHealth { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{:e}", self.bits() as f32) - } -} + if value.e5b_dvs { + ret |= 0b1000000; + } -bitflags! { - /// GAL FNAV and INAV Health indications. - /// See [Bibliography::RINEX4] for more information. - #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] - #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct Health: u64 { - const L1Healthy = 0x01; - const L2Healthy = 0x02; - const L5Healthy = 0x04; - } -} + ret |= (value.e5b_hs as u32) & 0b11 << 7; -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_gal() { - assert_eq!(GalHealth::default(), GalHealth::empty()); + ret } } diff --git a/rinex/src/navigation/health/gps.rs b/rinex/src/navigation/health/gps.rs index 05c7d05cc..54874146f 100644 --- a/rinex/src/navigation/health/gps.rs +++ b/rinex/src/navigation/health/gps.rs @@ -1,41 +1,41 @@ -//! GPS Sv Health specifications +//! GPS SV Health specifications use bitflags::bitflags; -/// GPS Sv Health indication +/// GPS SV Health indication #[derive(Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] pub enum GPSHealth { - /// GPS Legacy Sv Health indication - LNAV(LegacyHealth), - /// GPS CNAV Sv Health indication - CNAV(CivilianHealth), - /// GPS CNV2 Sv Health indication - CNV2(Civilian2Health), + /// GPS Legacy SV Health indication + LNAV(LNAVHealth), + /// GPS CNAV SV Health indication + CNAV(CNAVHealth), + /// GPS CNV2 SV Health indication + CNV2(CNAVHealth), } impl Default for GPSHealth { fn default() -> Self { - Self::LNAV(LegacyHealth::default()) + Self::LNAV(LNAVHealth::default()) } } impl GPSHealth { - /// Unwraps self as [`LegacyHealth`] indicator - pub(crate) fn lnav(&self) -> Option<&LegacyHealth> { + /// Unwraps self as [`LNAVHealth`] indicator + pub(crate) fn lnav(&self) -> Option<&LNAVHealth> { match self { Self::LNAV(h) => Some(h), _ => None, } } - /// Unwraps self as [`CivilianHealth`] indicator - pub(crate) fn cnav(&self) -> Option<&CivilianHealth> { + /// Unwraps self as [`CNAVHealth`] indicator + pub(crate) fn cnav(&self) -> Option<&CNAVHealth> { match self { Self::CNAV(h) => Some(h), _ => None, } } - /// Unwraps self as [`Civilian2Health`] indicator - pub(crate) fn cnv2(&self) -> Option<&Civilian2Health> { + /// Unwraps self as [`CNAVHealth`] indicator + pub(crate) fn cnv2(&self) -> Option<&CNAVHealth> { match self { Self::CNV2(h) => Some(h), _ => None, @@ -43,44 +43,98 @@ impl GPSHealth { } } -bitflags! { - /// GPS Legacy Sv Health indication. - /// See [Bibliography::RINEX3] for more information. - #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] - #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct LegacyHealth: u64 { - const L1Healthy = 0x01; - const L2Healthy = 0x02; - const L5Healthy = 0x04; - } +/// GPS Legacy SV Health indication. +/// Refer to [Bibliography::RINEX3] and [Bibliography::GpsIcd] 20.3.3.3.1.4 for more information. +#[derive(Default, Debug, Clone, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct LNAVHealth { + /// LNAV data health + /// `false` = all LNAV data are OK + /// `true` = some or all LNAV data are bad + data: bool, + /// Signal component health + /// 0 = All Signals OK + /// 1 = All Signals Weak + /// 2 = All Signals Dead + /// 3 = All Signals Have No Data Modulation + /// 4 = L1 P Signal Weak + /// 5 = L1 P Signal Dead + /// 6 = L1 P Signal Has No Data Modulation + /// 7 = L2 P Signal Weak + /// 8 = L2 P Signal Dead + /// 9 = L2 P Signal Has No Data Modulation + /// 10 = L1C Signal Weak + /// 11 = L1C Signal Dead + /// 12 = L1C Signal Has No Data Modulation + /// 13 = L2C Signal Weak + /// 14 = L2C Signal Dead + /// 15 = L2C Signal Has No Data Modulation + /// 16 = L1 & L2 P Signal Weak + /// 17 = L1 & L2 P Signal Dead + /// 18 = L1 & L2 P Signal Has No Data Modulation + /// 19 = L1 & L2C Signal Weak + /// 20 = L1 & L2C Signal Dead + /// 21 = L1 & L2C Signal Has No Data Modulation + /// 22 = L1 Signal Weak + /// 23 = L1 Signal Dead + /// 24 = L1 Signal Has No Data Modulation + /// 25 = L2 Signal Weak + /// 26 = L2 Signal Dead + /// 27 = L2 Signal Has No Data Modulation + /// 28 = SV Is Temporarily Out + /// 29 = SV Will Be Temporarily Out + /// 30 = One Or More Signals Are Deformed, However The Relevant URA Parameters Are Valid + /// 31 = More Than One Combination Would Be Required To Describe Anomalies + signals: u8, } -impl std::fmt::UpperExp for LegacyHealth { +impl std::fmt::UpperExp for LNAVHealth { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{:e}", self.bits() as f32) + let value = u32::from(self); + write!(f, "{:e}", value as f32) } } -bitflags! { - /// GPS CNAV Sv Health indication. - /// See [Bibliography::RINEX4] for more information. - #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] - #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct CivilianHealth: u64 { - const L1Healthy = 0x01; - const L2Healthy = 0x02; - const L5Healthy = 0x04; +impl From for LNAVHealth { + fn from(value: u32) -> Self { + Self { + data: (value & 0b100000) != 0, + signals: (value & 0b11111) as u8, + } + } +} + +impl From<&LNAVHealth> for u32 { + fn from(value: &LNAVHealth) -> Self { + let mut ret: u32 = 0; + + if value.data { + ret |= 0b100000; + } + + ret |= (value.signals as u32) & 0b11111; + + ret } } bitflags! { - /// GPS CNAV-2 Sv Health indication. - /// See [Bibliography::RINEX4] for more information. + /// GPS CNAV & CNAV-2 SV Health indication. + /// Refer to [Bibliography::RINEX4] and [Bibliography::GpsIcd] 30.3.3.4.4 for more information. #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct Civilian2Health: u64 { - const L1Healthy = 0x01; - const L2Healthy = 0x02; - const L5Healthy = 0x04; + pub struct CNAVHealth: u8 { + /// L1 Signal Health + /// `false` = Some or all codes and data on this carrier are OK + /// `true` = All codes and data on this carrier are bad or unavailable + const L1 = 0x01; + /// L2 Signal Health + /// `false` = Some or all codes and data on this carrier are OK + /// `true` = All codes and data on this carrier are bad or unavailable + const L2 = 0x02; + /// L5 Signal Health + /// `false` = Some or all codes and data on this carrier are OK + /// `true` = All codes and data on this carrier are bad or unavailable + const L5 = 0x04; } } diff --git a/rinex/src/navigation/health/qzss.rs b/rinex/src/navigation/health/qzss.rs index 5050b1704..33c51c25e 100644 --- a/rinex/src/navigation/health/qzss.rs +++ b/rinex/src/navigation/health/qzss.rs @@ -1,44 +1,41 @@ -//! QZSS Sv Health specifications +//! QZSS SV Health specifications use bitflags::bitflags; -/// QZSS Sv Health indication +/// QZSS SV Health indication #[derive(Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] pub enum QZSSHealth { - /// QZSS Legacy Sv Health indication. - /// Refer to [Bibliography::QzssPnt] 5.4.1. - LNAV(LegacyHealth), - /// QZSS CNAV Sv Health indication. - /// Refer to [Bibliography::QzssPnt]. - CNAV(CivilianHealth), - /// QZSS CNV2 Sv Health indication. - /// Refer to [Bibliography::QzssPnt]. - CNV2(Civilian2Health), + /// QZSS Legacy SV Health indication + LNAV(LNAVHealth), + /// QZSS CNAV SV Health indication + CNAV(CNAVHealth), + /// QZSS CNV2 SV Health indication + CNV2(CNAVHealth), } impl Default for QZSSHealth { fn default() -> Self { - Self::LNAV(LegacyHealth::default()) + Self::LNAV(LNAVHealth::default()) } } impl QZSSHealth { - /// Unwraps self as [`LegacyHealth`] indicator - pub(crate) fn lnav(&self) -> Option<&LegacyHealth> { + /// Unwraps self as [`LNAVHealth`] indicator + pub(crate) fn lnav(&self) -> Option<&LNAVHealth> { match self { Self::LNAV(h) => Some(h), _ => None, } } - /// Unwraps self as [`Health`] indicator - pub(crate) fn cnav(&self) -> Option<&CivilianHealth> { + /// Unwraps self as [`CNAVHealth`] indicator + pub(crate) fn cnav(&self) -> Option<&CNAVHealth> { match self { Self::CNAV(h) => Some(h), _ => None, } } - /// Unwraps self as [`Health`] indicator - pub(crate) fn cnv2(&self) -> Option<&Civilian2Health> { + /// Unwraps self as [`CNAVHealth`] indicator + pub(crate) fn cnv2(&self) -> Option<&CNAVHealth> { match self { Self::CNV2(h) => Some(h), _ => None, @@ -47,48 +44,77 @@ impl QZSSHealth { } bitflags! { - /// QZSS Legacy Sv Health indication. + /// QZSS LNAV SV Health indication. /// See [Bibliography::RINEX3] and [Bibliography::QzssPnt] 5.4.1 /// for more information. #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct LegacyHealth: u64 { - const L1CA_B= 0x01 << 22; - const L1C_A = 0x01 << 21; - const L2 = 0x01 << 20; - const L5 = 0x01 << 19; - const L1C = 0x01 << 18; - const L1C_B = 0x01 << 17; - + pub struct LNAVHealth: u64 { + /// L1 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L1 = 0x20; + /// L1 C/A Health + /// `false` = Healthy + /// `true` = Unhealthy + const L1_CA = 0x10; + /// L2 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L2 = 0x08; + /// L5 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L5 = 0x04; + /// L1C Health + /// `false` = Healthy + /// `true` = Unhealthy + const L1C = 0x02; + /// L1 C/B Health + /// `false` = Healthy + /// `true` = Unhealthy + const L1_CB = 0x01; } } -impl std::fmt::UpperExp for LegacyHealth { +impl std::fmt::UpperExp for LNAVHealth { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:e}", self.bits() as f32) } } bitflags! { - /// QZSS CNAV Health indications. - /// See [Bibliography::RINEX4] and [Bibliography::QzssPnt] 5.4.1 + /// QZSS CNAV Health indication. + /// See [Bibliography::RINEX4] and [Bibliography::QzssPnt] 5.4.1 for more information. /// for more information. #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct CivilianHealth: u64 { - const L5 = 0x01 << 54; - const L2 = 0x01 << 53; - const L1 = 0x01 << 52; + pub struct CNAVHealth: u8 { + /// L1 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L1 = 0x01; + /// L2 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L2 = 0x02; + /// L5 Health + /// `false` = Healthy + /// `true` = Unhealthy + const L5 = 0x04; } } bitflags! { - /// QZSS CNV2 Health indications. - /// See [Bibliography::RINEX4] and [Bibliography::QzssPnt] 5.4.1 + /// QZSS CNV2 Health indication. + /// See [Bibliography::RINEX4] and [Bibliography::QzssPnt] 5.4.1 for more information. /// for more information. #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize))] - pub struct Civilian2Health: u64 { + pub struct CNV2Health: u8 { + /// L1C Health + /// `false` = Healthy + /// `true` = Unhealthy const L1C = 0x01; } } From 858d515fd3a6911b8c78d5595017d92bbb7cade3 Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Tue, 29 Aug 2023 23:07:19 +1000 Subject: [PATCH 2/3] Fix typos --- rinex/src/navigation/health/qzss.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rinex/src/navigation/health/qzss.rs b/rinex/src/navigation/health/qzss.rs index 33c51c25e..5453d90f3 100644 --- a/rinex/src/navigation/health/qzss.rs +++ b/rinex/src/navigation/health/qzss.rs @@ -10,7 +10,7 @@ pub enum QZSSHealth { /// QZSS CNAV SV Health indication CNAV(CNAVHealth), /// QZSS CNV2 SV Health indication - CNV2(CNAVHealth), + CNV2(CNV2Health), } impl Default for QZSSHealth { @@ -34,8 +34,8 @@ impl QZSSHealth { _ => None, } } - /// Unwraps self as [`CNAVHealth`] indicator - pub(crate) fn cnv2(&self) -> Option<&CNAVHealth> { + /// Unwraps self as [`CNV2Health`] indicator + pub(crate) fn cnv2(&self) -> Option<&CNV2Health> { match self { Self::CNV2(h) => Some(h), _ => None, @@ -106,7 +106,7 @@ bitflags! { } bitflags! { - /// QZSS CNV2 Health indication. + /// QZSS CNAV-2 Health indication. /// See [Bibliography::RINEX4] and [Bibliography::QzssPnt] 5.4.1 for more information. /// for more information. #[derive(Default, Debug, Clone, PartialEq, PartialOrd)] From 0663a56490203453fef2834cb532d104a1fa5b9e Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Tue, 29 Aug 2023 23:15:38 +1000 Subject: [PATCH 3/3] Tweak refs --- rinex/src/bibliography.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rinex/src/bibliography.rs b/rinex/src/bibliography.rs index a6a575a25..8cf0e8c37 100644 --- a/rinex/src/bibliography.rs +++ b/rinex/src/bibliography.rs @@ -38,7 +38,13 @@ pub enum Bibliography { /// GNSS antennas*. /// [DOI](https://cdn.taoglas.com/wp-content/uploads/pdf/Multipath-Analysis-Using-Code-Minus-Carrier-Technique-in-GNSS-Antennas-_WhitePaper_VP__Final-1.pdf). MpTaoglas, - /// QZSS Signal and Constellation interface specifications. + /// Quasi-Zenith Satellite System Interface Specification Satellite Positioning, Navigation and Timing Service. /// [DOI](https://qzss.go.jp/en/technical/download/pdf/ps-is-qzss/is-qzss-pnt-005.pdf) - QzssPnt, + IsQzssPnt, + /// NAVSTAR GPS Space Segment/Navigation User Segment Interfaces. + /// [DOI](https://www.gps.gov/technical/icwg/IS-GPS-200N.pdf) + IsGps200, + /// European GNSS (Galileo) Open Service Signal-In-Space Interface Control Document. + /// [DOI](https://www.gps.gov/technical/icwg/IS-GPS-200N.pdf) + GalOsSisIcd, }