use crate::{
navigation::{NavFrameType, NavMessageType},
prelude::{Constellation, Epoch, Rinex, TimeScale, SV},
tests::toolkit::{generic_navigation_test, TimeFrame},
};
use hifitime::Unit;
use std::{path::PathBuf, str::FromStr};
#[test]
fn v2_amel0010_21g() {
let test_resource = env!("CARGO_MANIFEST_DIR").to_owned() + "/data/NAV/V2/amel0010.21g";
let dut = Rinex::from_file(&test_resource).unwrap();
generic_navigation_test(
&dut,
"2.11",
"Glonass",
Some(TimeFrame::from_erratic_csv(
"2020-12-31T23:45:00 UTC,
2021-01-01T11:15:00 UTC,
2021-01-01T11:45:00 UTC,
2021-01-01T16:15:00 UTC,
2021-01-01T16:15:00 UTC,
2021-01-01T16:15:00 UTC",
)),
"R01, R02, R03, R04, R05, R07",
6,
);
let mut num_tests = 0;
for (k, eph) in dut.nav_ephemeris_frames_iter() {
assert_eq!(k.frmtype, NavFrameType::Ephemeris);
assert_eq!(k.msgtype, NavMessageType::LNAV);
assert_eq!(k.sv.constellation, Constellation::Glonass);
match k.sv.prn {
1 => {
assert_eq!(eph.sv_clock(), (7.282570004460E-5, 0.0, 7.380000000000E+04));
assert!(eph.get_orbit_f64("ageOp").is_none());
assert_eq!(eph.glonass_freq_channel(), Some(1));
num_tests += 1;
},
2 => {
assert_eq!(eph.clock_bias, 4.610531032090E-04);
assert_eq!(eph.clock_drift, 1.818989403550E-12);
assert_eq!(eph.clock_drift_rate, 4.245000000000E+04);
assert!(eph.get_orbit_f64("ageOp").is_none());
num_tests += 1;
},
3 => {
assert_eq!(eph.clock_bias, 2.838205546140E-05);
assert_eq!(eph.clock_drift, 0.0);
assert_eq!(eph.clock_drift_rate, 4.680000000000E+04);
num_tests += 1;
},
4 => {
assert_eq!(eph.clock_bias, 6.817653775220E-05);
assert_eq!(eph.clock_drift, 1.818989403550E-12);
assert_eq!(eph.clock_drift_rate, 4.680000000000E+04);
num_tests += 1;
},
5 => {
assert_eq!(eph.clock_bias, 6.396882236000E-05);
assert_eq!(eph.clock_drift, 9.094947017730E-13);
assert_eq!(eph.clock_drift_rate, 8.007000000000E+04);
num_tests += 1;
},
7 => {
assert_eq!(eph.clock_bias, -4.201009869580E-05);
assert_eq!(eph.clock_drift, 0.0);
assert_eq!(eph.clock_drift_rate, 2.88E4);
assert!(eph.get_orbit_f64("ageOp").is_none());
num_tests += 1;
},
prn => panic!("invalid SV: R{}", prn),
}
}
assert_eq!(num_tests, 6);
}
#[test]
#[cfg(feature = "flate2")]
fn v2_cbw10010_21n() {
let data = env!("CARGO_MANIFEST_DIR").to_owned() + "/data/NAV/V2/cbw10010.21n.gz";
let dut = Rinex::from_gzip_file(&data).unwrap();
generic_navigation_test(
&dut,
"2.11",
"GPS",
None,
"G01, G07, G08, G04, G19, G10, G15, G20, G18, G31, G03, G06, G27, G09, G11, G13, G30, G12, G14, G17, G23, G24, G19, G21, G22, G28, G32, G25, G02, G03, G06, G12, G17, G22, G26, G05, G16, G29, G14",
187,
);
let t0 = Epoch::from_str("2020-12-31T23:59:44 GPST").unwrap();
let t1 = Epoch::from_str("2021-01-02T00:00:00 GPST").unwrap();
let mut tests_passed = 0;
for (k, eph) in dut.nav_ephemeris_frames_iter() {
assert_eq!(k.msgtype, NavMessageType::LNAV, "Legacy NAV file");
assert_eq!(k.sv.constellation, Constellation::GPS, "GPS NAV file");
if k.epoch == t0 {
if k.sv.prn == 7 {
assert_eq!(eph.clock_bias, 4.204921424390E-6);
assert_eq!(eph.clock_drift, 1.477928890380E-11);
assert_eq!(eph.clock_drift_rate, 0.0);
for (field, value) in [
("crs", Some(-1.509375000000E1)),
("deltaN", Some(5.043781392540E-9)),
("m0", Some(-1.673144695710)),
("cuc", Some(-8.475035429000E-7)),
("e", Some(1.431132073050E-2)),
("cus", Some(5.507841706280E-6)),
("sqrta", Some(5.153606595990E3)),
("toe", Some(4.319840000000E5)),
("cic", Some(2.216547727580E-7)),
("omega0", Some(2.333424778860)),
("cis", Some(-8.009374141690E-8)),
("i0", Some(9.519533967710E-1)),
("crc", Some(2.626562500000E2)),
("omega", Some(-2.356931900380)),
("omegaDot", Some(-8.034263032640E-9)),
("idot", Some(-1.592923432050E-10)),
("l2Codes", Some(1.000000000000)),
("tgd", Some(-1.117587089540E-8)),
("t_tm", Some(4.283760000000E5)),
] {
let orbit_value = eph.get_orbit_f64(field);
assert_eq!(
orbit_value, value,
"parsed wrong \"{}\" value for G07 T0",
field
);
}
assert_eq!(eph.get_week(), Some(2138));
assert!(
eph.get_orbit_f64("fitInt").is_none(),
"parsed fitInt unexpectedly"
);
tests_passed += 1;
}
} else if k.epoch == t1 {
if k.sv.prn == 30 {
assert_eq!(eph.clock_bias, -3.621461801230E-04);
assert_eq!(eph.clock_drift, -6.139089236970E-12);
assert_eq!(eph.clock_drift_rate, 0.000000000000);
for (field, value) in vec![
("iode", Some(8.500000000000E1)),
("crs", Some(-7.500000000000)),
("deltaN", Some(5.476656696160E-9)),
("m0", Some(-1.649762378650)),
("cuc", Some(-6.072223186490E-7)),
("e", Some(4.747916595080E-3)),
("cus", Some(5.392357707020E-6)),
("sqrta", Some(5.153756387710E+3)),
("toe", Some(5.184000000000E+5)),
("cic", Some(7.636845111850E-8)),
("omega0", Some(2.352085289360E+00)),
("cis", Some(-2.421438694000E-8)),
("i0", Some(9.371909002540E-1)),
("crc", Some(2.614687500000E+2)),
("omega", Some(-2.846234079630)),
("omegaDot", Some(-8.435351366240E-9)),
("idot", Some(-7.000291590240E-11)),
("l2Codes", Some(1.000000000000)),
("tgd", Some(3.725290298460E-9)),
("iodc", Some(8.500000000000E1)),
("t_tm", Some(5.146680000000E5)),
] {
let orbit = eph.get_orbit_f64(field);
assert_eq!(orbit, value, "parsed wrong \"{}\" value for G30 T1", field);
}
assert_eq!(eph.get_week(), Some(2138));
assert!(
eph.get_orbit_f64("fitInt").is_none(),
"parsed fitInt unexpectedly"
);
tests_passed += 1;
}
}
}
assert_eq!(tests_passed, 2);
}
#[test]
fn v3_amel00nld_r_2021() {
let test_resource =
env!("CARGO_MANIFEST_DIR").to_owned() + "/data/NAV/V3/AMEL00NLD_R_20210010000_01D_MN.rnx";
let rinex = Rinex::from_file(&test_resource).unwrap();
assert!(rinex.is_navigation_rinex());
assert!(rinex.header.obs.is_none());
assert!(rinex.header.meteo.is_none());
let c05 = SV::from_str("C05").unwrap();
let c21 = SV::from_str("C21").unwrap();
let e01 = SV::from_str("E01").unwrap();
let r07 = SV::from_str("R07").unwrap();
let r19 = SV::from_str("R19").unwrap();
let mut num_tests = 0;
for (k, eph) in rinex.nav_ephemeris_frames_iter() {
assert_eq!(k.msgtype, NavMessageType::LNAV);
if k.sv == c05 {
assert_eq!(eph.clock_bias, -0.426337239332e-03);
assert_eq!(eph.clock_drift, -0.752518047875e-10);
assert_eq!(eph.clock_drift_rate, 0.0);
assert_eq!(eph.get_orbit_f64("aode"), Some(0.100000000000e+01));
assert_eq!(eph.get_orbit_f64("crs"), Some(0.118906250000e+02));
} else if k.sv == c21 {
assert_eq!(eph.clock_bias, -0.775156309828e-03);
assert_eq!(eph.clock_drift, -0.144968481663e-10);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+0);
} else if k.sv == r19 {
assert_eq!(eph.clock_bias, -0.126023776829e-03);
assert_eq!(eph.clock_drift, -0.909494701773e-12);
assert_eq!(eph.clock_drift_rate, 0.0);
} else if k.sv == r07 {
assert_eq!(eph.clock_bias, -0.420100986958E-04);
assert_eq!(eph.clock_drift, 0.0);
assert_eq!(eph.clock_drift_rate, 0.342000000000e+05);
} else if k.sv == e01 {
assert_eq!(eph.clock_bias, -0.101553811692e-02);
assert_eq!(eph.clock_drift, -0.804334376880e-11);
assert_eq!(eph.clock_drift_rate, 0.0);
} else if k.sv == e01 {
assert_eq!(eph.clock_bias, -0.382520200219e-03);
assert_eq!(eph.clock_drift, -0.422062385041e-11);
assert_eq!(eph.clock_drift_rate, 0.0);
}
num_tests += 1;
}
assert_eq!(num_tests, 6);
}
#[test]
#[cfg(feature = "flate2")]
fn v3_brdc00gop_r_2021_gz() {
let test_resource = env!("CARGO_MANIFEST_DIR").to_owned()
+ "/data/NAV/V3/BRDC00GOP_R_20210010000_01D_MN.rnx.gz";
let dut = Rinex::from_gzip_file(&test_resource).unwrap();
generic_navigation_test(
&dut,
"3.04",
"MIX",
Some(TimeFrame::from_erratic_csv(
"
2021-01-01T00:00:00 BDT,
2021-01-01T01:28:00 GPST,
2021-01-01T07:15:00 UTC,
2021-01-01T08:20:00 GST",
)),
"C01, E03, R10, S36",
4,
);
}
#[test]
#[cfg(feature = "flate2")]
fn v3_esbc00dnk_r2020() {
let test_resource = env!("CARGO_MANIFEST_DIR").to_owned()
+ "/data/NAV/V3/ESBC00DNK_R_20201770000_01D_MN.rnx.gz";
let dut = Rinex::from_gzip_file(&test_resource).unwrap();
generic_navigation_test(
&dut,
"3.05",
"MIX",
None,
"
C05, C06, C07, C08, C09, C10, C11, C12, C13, C14,
C16, C19, C20, C21, C22, C23, C24, C25, C26, C27,
C28, C29, C30, C32, C33, C34, C35, C36, C37,
E01, E02, E03, E04, E05, E07, E08, E09, E11, E12,
E13, E14, E15, E18, E19, E21, E24, E25, E26, E27,
E30, E31, E33, E36,
G01, G02, G03, G04, G05, G06, G07, G08, G09, G10, G11,
G12, G13, G14, G15, G16, G17, G18, G19, G20, G21, G22,
G24, G25, G26, G27, G28, G29, G30, G31, G32,
J01, J02, J03,
R01, R02, R03, R04, R05, R06, R07, R08, R09, R10,
R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R23, R24,
S23, S25, S26, S36, S44",
4092,
);
let mut tests_passed = 0;
let t0 = Epoch::from_str("2020-06-24T22:00:00 GPST").unwrap();
let g30 = SV::from_str("G30").unwrap();
for (k, eph) in dut.nav_ephemeris_frames_iter() {
if k.epoch == t0 && k.sv == g30 {
assert_eq!(
eph.sv_clock(),
(-2.486067824066e-04, -7.844391802792e-12, 0.000000000000e+00)
);
tests_passed += 1;
}
}
assert_eq!(tests_passed, 1);
}
#[test]
#[cfg(feature = "flate2")]
fn nav_v4_kms300dnk_r2022() {
let test_resource = env!("CARGO_MANIFEST_DIR").to_owned()
+ "/data/NAV/V4/KMS300DNK_R_20221591000_01H_MN.rnx.gz";
let dut = Rinex::from_gzip_file(&test_resource).unwrap();
generic_navigation_test(
&dut,
"4.00",
"MIX",
None,
"G02, G04, G05, G07, G08, G09,
G10, G11, G12, G13,
G15, G16, G18, G20, G22, G23,
G25, G26, G27, G29, G31,
E01, E03, E05, E07, E08, E09, E10,
E11, E12, E13, E14, E15, E21, E24,
E25, E26, E31, E33,
R03, R04, R05, R10, R11, R12, R13,
R20, R21, R23,
C05, C08, C10, C13, C14, C20, C21, C24, C26, C27,
C28, C29, C30, C32, C33, C35, C36, C38, C41, C42, C45, C46, C60,
J04,
S48, S36, S26, S44, S23, S25, S27, S26, S28",
357,
);
let t0 = Epoch::from_str("2022-06-10T19:56:48 GPST").unwrap();
let t1 = Epoch::from_str("2022-06-08T00:00:00 GST").unwrap();
let t2 = Epoch::from_str("2022-06-08T09:50:00 GST").unwrap();
let t_11_00_00_gpst = Epoch::from_str("2022-06-08T11:00:00 GPST").unwrap();
let t_last = Epoch::from_str("2022-06-10T19:56:48 GPST").unwrap();
let g26 = SV::from_str("G26").unwrap();
let e01 = SV::from_str("E01").unwrap();
let e14 = SV::from_str("E14").unwrap();
let j04 = SV::from_str("J04").unwrap();
let mut tests_passed = 0;
for (k, v) in dut.nav_ephemeris_frames_iter() {
assert_eq!(k.frmtype, NavFrameType::Ephemeris);
if k.epoch == t0 {
} else if k.epoch == t_11_00_00_gpst {
assert_eq!(k.sv, j04);
assert_eq!(k.msgtype, NavMessageType::LNAV);
assert_eq!(v.clock_bias, 1.080981455743E-04);
assert_eq!(v.clock_drift, 3.751665644813E-12);
assert_eq!(v.clock_drift_rate, 0.0);
tests_passed += 1;
} else if k.epoch == t2 {
if k.sv == e14 {
if k.msgtype == NavMessageType::INAV {
assert_eq!(v.clock_bias, -1.813994604163E-03);
assert_eq!(v.clock_drift, 1.104183411371E-11);
assert_eq!(v.clock_drift_rate, 0.000000000000E+00);
tests_passed += 1;
} else if k.msgtype == NavMessageType::FNAV {
assert_eq!(v.clock_bias, -1.813993556425E-03);
assert_eq!(v.clock_drift, 1.104183411371E-11);
assert_eq!(v.clock_drift_rate, 0.000000000000E+00);
tests_passed += 1;
}
}
} else if k.epoch == t_last {
}
}
assert_eq!(tests_passed, 3);
let mut tests_passed = 0;
for (k, v) in dut.nav_system_time_frames_iter() {
if k.epoch == t0 {
if k.sv == g26 {
assert_eq!(k.msgtype, NavMessageType::LNAV);
assert_eq!(k.frmtype, NavFrameType::SystemTimeOffset);
assert_eq!(v.lhs, TimeScale::GPST);
assert_eq!(v.rhs, TimeScale::UTC);
let (seconds, drift) = (v.polynomial.0, v.polynomial.1);
assert_eq!(v.polynomial.2, 0.0);
tests_passed += 1;
}
} else if k.epoch == t1 {
if k.sv == e01 {
assert_eq!(k.msgtype, NavMessageType::IFNV);
assert_eq!(k.frmtype, NavFrameType::SystemTimeOffset);
assert_eq!(v.lhs, TimeScale::GST);
assert_eq!(v.rhs, TimeScale::GPST);
let (seconds, drift) = (v.polynomial.0, v.polynomial.1);
assert!((seconds - 3.201421350241E-09).abs() < 1E-12);
assert!((drift - -4.440892098501E-15).abs() < 1E-12);
assert_eq!(v.polynomial.2, 0.0);
tests_passed += 1;
}
}
}
assert_eq!(tests_passed, 2);
let mut tests = 0;
for (_, _) in dut.nav_earth_orientation_frames_iter() {
tests += 1;
}
assert_eq!(tests, 0);
}
#[test]
#[cfg(feature = "nav")]
#[cfg(feature = "flate2")]
fn v4_brd400dlr_s2023() {
let path = PathBuf::new()
.join(env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("NAV")
.join("V4")
.join("BRD400DLR_S_20230710000_01D_MN.rnx.gz");
let path = path.to_string_lossy().to_string();
let rinex = Rinex::from_gzip_file(&path).unwrap();
let t_03_12_00_00_00_gpst = Epoch::from_str("2023-03-12T00:00:00 GPST").unwrap();
let t_03_12_00_00_00_bdt = Epoch::from_str("2023-03-12T00:00:00 BDT").unwrap();
let t_03_12_01_30_00_gpst = Epoch::from_str("2023-03-12T01:30:00 GPST").unwrap();
let t_03_12_02_00_00_gpst = Epoch::from_str("2023-03-12T02:00:00 GPST").unwrap();
let g01 = SV::from_str("G01").unwrap();
let c19 = SV::from_str("C19").unwrap();
let j04 = SV::from_str("J04").unwrap();
let mut tests_passed = 0;
for (k, eph) in rinex.nav_ephemeris_frames_iter() {
if k.sv == g01 {
assert!(
(k.msgtype == NavMessageType::LNAV) || (k.msgtype == NavMessageType::CNAV),
"bad ephemeris message {} for G01 {}",
k.msgtype,
k.epoch
);
if k.epoch == t_03_12_00_00_00_gpst {
assert_eq!(k.msgtype, NavMessageType::LNAV);
assert_eq!(eph.clock_bias, 2.037500962615e-04);
assert_eq!(eph.clock_drift, -3.865352482535e-12);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
} else if k.epoch == t_03_12_02_00_00_gpst {
assert_eq!(k.msgtype, NavMessageType::LNAV);
assert_eq!(eph.clock_bias, 2.037221565843e-04);
assert_eq!(eph.clock_drift, -3.865352482535e-12);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
} else if k.epoch == t_03_12_01_30_00_gpst {
assert_eq!(k.msgtype, NavMessageType::CNAV);
assert_eq!(eph.clock_bias, 2.037292579189e-04);
assert_eq!(eph.clock_drift, -3.829825345747e-12);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
}
} else if k.sv == c19 {
assert!(
(k.msgtype == NavMessageType::D1)
|| (k.msgtype == NavMessageType::CNV1)
|| (k.msgtype == NavMessageType::CNV2),
"bad ephemeris message {} for C19 {}",
k.msgtype,
k.epoch
);
if k.epoch == t_03_12_00_00_00_bdt {
if k.msgtype == NavMessageType::D1 {
assert_eq!(eph.clock_bias, -8.956108940765e-04);
assert_eq!(eph.clock_drift, -9.041656312547e-13);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
} else if k.msgtype == NavMessageType::CNV2 {
assert_eq!(eph.clock_bias, -8.956108940765e-04);
assert_eq!(eph.clock_drift, -9.041656312547e-13);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
}
}
} else if k.sv == j04 {
assert!(
(k.msgtype == NavMessageType::LNAV)
|| (k.msgtype == NavMessageType::CNAV)
|| (k.msgtype == NavMessageType::CNV2),
"bad ephemeris message {} for J04 {}",
k.msgtype,
k.epoch
);
if k.epoch == t_03_12_00_00_00_gpst {
if k.msgtype == NavMessageType::LNAV {
assert_eq!(eph.clock_bias, 9.417533874512e-05);
assert_eq!(eph.clock_drift, 0.000000000000e+00);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
} else if k.msgtype == NavMessageType::CNAV {
assert_eq!(eph.clock_bias, 9.417530964129e-05);
assert_eq!(eph.clock_drift, -4.263256414561e-14);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
} else if k.msgtype == NavMessageType::CNV2 {
assert_eq!(eph.clock_bias, 9.417530964129e-05);
assert_eq!(eph.clock_drift, -4.263256414561e-14);
assert_eq!(eph.clock_drift_rate, 0.000000000000e+00);
tests_passed += 1;
}
}
}
}
assert_eq!(tests_passed, 8);
}
fn toe_helper(week: f64, week_s: f64, ts: TimeScale) -> Epoch {
if ts == TimeScale::GST {
Epoch::from_duration((week - 1024.0) * Unit::Week + week_s * Unit::Second, ts)
} else {
Epoch::from_duration(week * Unit::Week + week_s * Unit::Second, ts)
}
}
#[test]
fn nav_toe_gal_bds() {
let mut tests_passed = 0;
let path = format!(
"{}/data/NAV/V3/AMEL00NLD_R_20210010000_01D_MN.rnx",
env!("CARGO_MANIFEST_DIR")
);
let dut = Rinex::from_file(path).unwrap();
let t0 = Epoch::from_str("2021-01-01T00:00:00 BDT").unwrap();
let t1 = Epoch::from_str("2021-01-01T05:00:00 BDT").unwrap();
let t2 = Epoch::from_str("2021-01-01T10:10:00 GST").unwrap();
let t3 = Epoch::from_str("2021-01-01T15:40:00 GST").unwrap();
for (k, eph) in dut.nav_ephemeris_frames_iter() {
let ts = k.sv.timescale().expect("only known timescales here!");
if let Some(toe) = eph.toe(k.sv) {
if k.epoch == t0 {
assert_eq!(toe, toe_helper(0.782E3, 0.432E6, TimeScale::BDT));
tests_passed += 1;
} else if k.epoch == t1 {
assert_eq!(toe, toe_helper(0.782E3, 0.450E6, TimeScale::BDT));
tests_passed += 1;
} else if k.epoch == t2 {
assert_eq!(toe, toe_helper(0.2138E4, 0.4686E6, TimeScale::GST));
tests_passed += 1;
} else if k.epoch == t3 {
assert_eq!(toe, toe_helper(0.2138E4, 0.4884E6, TimeScale::GST));
tests_passed += 1;
}
}
}
assert_eq!(tests_passed, 4);
}
#[test]
#[cfg(feature = "nav")]
fn nav_v3_ionospheric_corr() {
let path = PathBuf::new()
.join(env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("NAV")
.join("V3")
.join("CBW100NLD_R_20210010000_01D_MN.rnx");
let path = path.to_string_lossy().to_string();
let _rinex = Rinex::from_file(&path).unwrap();
}
#[test]
#[cfg(feature = "flate2")]
fn nav_v4_messages() {
for fp in [
"KMS300DNK_R_20221591000_01H_MN.rnx.gz",
"BRD400DLR_S_20230710000_01D_MN.rnx.gz",
] {
let fullpath = format!("{}/data/NAV/V4/{}", env!("CARGO_MANIFEST_DIR"), fp);
let rinex = Rinex::from_gzip_file(&fullpath).unwrap();
for (k, model) in rinex.nav_ionosphere_models_iter() {
match k.sv.constellation {
Constellation::GPS => {
assert!(
model.as_klobuchar().is_some(),
"GPS vehicles only publish Kb model",
);
},
Constellation::QZSS => {
assert!(
model.as_klobuchar().is_some(),
"QZSS vehicles only publish Kb model",
);
},
Constellation::BeiDou => match k.msgtype {
NavMessageType::D1D2 => {
assert!(
model.as_klobuchar().is_some(),
"BeiDou (D1D2) should be be a Kb model",
);
},
NavMessageType::CNVX => {
assert!(
model.as_bdgim().is_some(),
"BeiDou (CNVX) should be a Bd model"
);
},
_ => {
panic!(
"invalid message type \"{}\" for BeiDou ION frame",
k.msgtype
);
},
},
Constellation::IRNSS => {
assert!(
model.as_klobuchar().is_some(),
"NavIC/IRNSS vehicles only publish Kb model",
);
},
Constellation::Galileo => {
assert!(
model.as_nequick_g().is_some(),
"GAL vehicles only publish Ng model",
);
},
_ => {
panic!("finvalid constellation: {}", k.sv.constellation,);
},
}
}
for (k, _) in rinex.nav_earth_orientation_frames_iter() {
match k.sv.constellation {
Constellation::GPS
| Constellation::QZSS
| Constellation::IRNSS
| Constellation::BeiDou => {},
_ => panic!("found invalid constellation: {}", k.sv.constellation),
}
match k.msgtype {
NavMessageType::CNVX | NavMessageType::LNAV => {},
_ => panic!("bad msg identified for GPS vehicle: {}", k.msgtype),
}
}
for (k, _) in rinex.nav_system_time_frames_iter() {
match k.msgtype {
NavMessageType::LNAV
| NavMessageType::FDMA
| NavMessageType::IFNV
| NavMessageType::D1D2
| NavMessageType::SBAS
| NavMessageType::CNVX => {},
_ => panic!("bad \"{}\" message for STO frame", k.msgtype),
}
}
}
}
#[test]
#[cfg(feature = "flate2")]
fn nav_v2_iono_alphabeta_and_toe() {
let path = PathBuf::new()
.join(env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("NAV")
.join("V2")
.join("cbw10010.21n.gz");
let path = path.to_string_lossy().to_string();
let rinex = Rinex::from_gzip_file(&path).unwrap();
let mut num_tests = 0;
let t_01_01_000000 = Epoch::from_str("2021-01-01T00:00:00 GPST").unwrap();
let t_01_01_015944 = Epoch::from_str("2021-01-01T01:59:44 GPST").unwrap();
let t_01_01_020000 = Epoch::from_str("2021-01-01T02:00:00 GPST").unwrap();
let t_01_01_080000 = Epoch::from_str("2021-01-01T08:00:00 GPST").unwrap();
let t_01_02_000000 = Epoch::from_str("2021-01-02T00:00:00 GPST").unwrap();
for (k, eph) in rinex.nav_ephemeris_frames_iter() {
let sv_ts = k.sv.timescale().expect("unknown timescale");
assert_eq!(sv_ts, TimeScale::GPST, "GPS NAV");
let toe = eph
.toe(k.sv)
.expect(&format!("toe() failed for {} ({})", k.epoch, k.sv));
assert_eq!(
toe.time_scale,
TimeScale::GPST,
"TOE returned wrong timescale for GPS NAV"
);
let prn = k.sv.prn;
if k.epoch == t_01_01_000000 {
assert_eq!(prn, 8, "invalid SV");
let expected = toe_helper(2.138E3, 4.32E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else if k.epoch == t_01_01_020000 {
assert_eq!(prn, 1, "invalid SV");
let expected = toe_helper(2.138E3, 4.392E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else if k.epoch == t_01_01_080000 {
if prn == 1 {
num_tests += 1;
} else if prn == 2 {
num_tests += 1;
} else if prn == 3 {
num_tests += 1;
} else if prn == 4 {
num_tests += 1;
} else if prn == 5 {
num_tests += 1;
} else if prn == 6 {
num_tests += 1;
} else if prn == 7 {
let expected = toe_helper(2.138E3, 4.608E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else if prn == 9 {
num_tests += 1;
} else if prn == 12 {
num_tests += 1;
} else if prn == 17 {
num_tests += 1;
} else if prn == 19 {
num_tests += 1;
} else if prn == 21 {
num_tests += 1;
} else if prn == 22 {
num_tests += 1;
} else if prn == 25 {
num_tests += 1;
} else if prn == 26 {
num_tests += 1;
} else if k.sv.prn == 29 {
num_tests += 1;
} else if k.sv.prn == 30 {
num_tests += 1;
} else if k.sv.prn == 31 {
num_tests += 1;
} else {
panic!("invalid SV=G{:02} @ {}", prn, k.epoch);
}
} else if k.epoch == t_01_02_000000 {
if prn == 5 {
let expected = toe_helper(2.138E3, 5.184E5, TimeScale::GPST);
assert_eq!(expected, toe);
num_tests += 1;
} else if prn == 7 {
num_tests += 1;
} else if prn == 8 {
let expected = toe_helper(2.138E3, 5.184E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else if k.sv.prn == 10 {
num_tests += 1;
} else if k.sv.prn == 11 {
num_tests += 1;
} else if k.sv.prn == 13 {
num_tests += 1;
} else if k.sv.prn == 15 {
num_tests += 1;
} else if k.sv.prn == 16 {
num_tests += 1;
} else if k.sv.prn == 18 {
num_tests += 1;
} else if k.sv.prn == 20 {
num_tests += 1;
} else if k.sv.prn == 21 {
num_tests += 1;
} else if k.sv.prn == 23 {
num_tests += 1;
} else if k.sv.prn == 26 {
num_tests += 1;
} else if k.sv.prn == 27 {
num_tests += 1;
} else if k.sv.prn == 29 {
num_tests += 1;
} else if k.sv.prn == 30 {
let expected = toe_helper(2.138000000000E3, 5.184000000000E5, TimeScale::GPST);
assert_eq!(expected, toe);
num_tests += 1;
} else {
panic!("invalid SV=G{:02} @ {}", prn, k.epoch);
}
} else if k.epoch == t_01_01_015944 {
if prn == 7 {
let expected = toe_helper(2.138000000000E3, 4.391840000000E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else if prn == 8 {
let expected = toe_helper(2.138000000000E3, 4.391840000000E5, TimeScale::GPST);
assert_eq!(toe, expected);
num_tests += 1;
} else {
panic!("invalid SV=G{:02} @ {}", prn, k.epoch);
}
}
}
assert_eq!(num_tests, 38);
}