303 while (line.find(
"RINEX VERSION / TYPE") == std::string::npos && !
eof())
309 if ((line.substr(20, 15) ==
"N: GPS NAV DATA" || line.substr(20, 15) ==
"NAVIGATION DATA")
310 && (line.substr(40, 3) ==
"GPS" ||
str::trim_copy(line.substr(40, 3)).empty()))
316 else if (line.substr(20, 16) ==
"GLONASS NAV DATA")
326 auto headerLabel = extHeaderLabel(line);
327 if (headerLabel ==
"PGM / RUN BY / DATE")
336 else if (headerLabel ==
"COMMENT")
340 else if (headerLabel ==
"IONOSPHERIC CORR")
343 std::array<double, 4> values{};
353 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
356 fmt::join(values.begin(), values.end(),
", "));
358 else if (headerLabel ==
"ION ALPHA" || headerLabel ==
"ION BETA")
360 auto correctionType = headerLabel.substr(4, 1);
362 std::array<double, 4> values{};
363 for (
size_t i = 0; i < valuesStr.size(); i++)
365 values.at(i) = std::stod(valuesStr.at(i));
369 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
372 fmt::join(values.begin(), values.end(),
", "));
374 else if (headerLabel ==
"TIME SYSTEM CORR"
375 || headerLabel ==
"CORR TO SYSTEM TIME")
384 else if (headerLabel ==
"DELTA-UTC: A0,A1,T,W")
391 if (a0 != 0 || a1 != 0)
396 else if (headerLabel ==
"LEAP SECONDS")
398 LOG_DATA(
"{}: Leap seconds: {}",
nameId(), std::stoi(line.substr(0, 6)));
400 else if (headerLabel ==
"END OF HEADER")
411 while (line.find(
"RINEX VERSION / TYPE") == std::string::npos && !
eof())
422 auto headerLabel = extHeaderLabel(line);
423 if (headerLabel ==
"PGM / RUN BY / DATE")
432 else if (headerLabel ==
"COMMENT")
436 else if (headerLabel ==
"IONOSPHERIC CORR")
439 std::array<double, 4> values{};
449 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
452 fmt::join(values.begin(), values.end(),
", "));
454 else if (headerLabel ==
"ION ALPHA" || headerLabel ==
"ION BETA")
456 auto correctionType = headerLabel.substr(4, 1);
458 std::array<double, 4> values{};
459 for (
size_t i = 0; i < valuesStr.size(); i++)
461 values.at(i) = std::stod(valuesStr.at(i));
465 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
468 fmt::join(values.begin(), values.end(),
", "));
470 else if (headerLabel ==
"TIME SYSTEM CORR"
471 || headerLabel ==
"CORR TO SYSTEM TIME")
474 LOG_DATA(
"{}: Time System Correction: {}",
nameId(), correctionType);
476 std::array<size_t, 2> x{ 5, 22 };
477 std::array<size_t, 2> n{ 17, 16 };
479 if (correctionType ==
"SBUT")
484 else if (correctionType ==
"GLUT")
495 if (!std::isnan(a0) && !std::isnan(a1))
497 std::pair<TimeSystem, TimeSystem> timeSystems;
498 if (correctionType ==
"GPUT") { timeSystems = {
GPST,
UTC }; }
499 else if (correctionType ==
"GLUT") { timeSystems = {
GLNT,
UTC }; }
500 else if (correctionType ==
"GAUT") { timeSystems = {
GST,
UTC }; }
501 else if (correctionType ==
"BDUT") { timeSystems = {
BDT,
UTC }; }
502 else if (correctionType ==
"QZUT") { timeSystems = {
QZSST,
UTC }; }
503 else if (correctionType ==
"IRUT") { timeSystems = {
IRNSST,
UTC }; }
505 else if (correctionType ==
"GLGP") { timeSystems = {
GLNT,
GPST }; }
506 else if (correctionType ==
"GAGP") { timeSystems = {
GST,
GPST }; }
507 else if (correctionType ==
"GPGA") { timeSystems = {
GST,
GPST }; }
508 else if (correctionType ==
"QZGP") { timeSystems = {
QZSST,
GPST }; }
509 else if (correctionType ==
"IRGP") { timeSystems = {
IRNSST,
GPST }; }
512 LOG_TRACE(
"{}: Time System Correction '{}' not implemented yet",
nameId(), correctionType);
515 _gnssNavInfo.timeSysCorr[timeSystems] = { .a0 = a0, .a1 = a1 };
518 else if (headerLabel ==
"DELTA-UTC: A0,A1,T,W")
525 if (a0 != 0 || a1 != 0)
530 else if (headerLabel ==
"LEAP SECONDS")
532 LOG_DATA(
"{}: Leap seconds: {}",
nameId(), std::stoi(line.substr(0, 6)));
534 else if (headerLabel ==
"END OF HEADER")
621 if (line.size() > 82)
643 auto satNumStr = line.substr(0, 2);
644 if (satNumStr ==
" ") {
continue; }
646 auto satNum =
static_cast<uint8_t
>(
str::stoi(satNumStr, 0));
647 if (satNum == 0) {
continue; }
653 int year = std::stoi(timeSplit.at(0));
656 year += (year >= 80 ? 1900 : 2000);
658 InsTime epoch{
static_cast<uint16_t
>(year),
659 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
660 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
661 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
662 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
663 std::stold(timeSplit.at(5)),
666 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.
toYMDHMS(), std::string(timeSystem));
668 if (satSys ==
GPS || satSys ==
GAL || satSys ==
QZSS || satSys ==
BDS)
671 std::array<double, 3> a{};
679 LOG_DATA(
"{}: clkBias {}, clkDrift {}, clkDriftRate {}",
nameId(), a[0], a[1], a[2]);
683 if (line.size() > 82)
702 LOG_DATA(
"{}: IODE_IODnav_AODE_IODEC {}, Crs {}, Delta_n {}, M0 {}",
nameId(), IODE_IODnav_AODE_IODEC, Crs, delta_n, M_0);
706 if (line.size() > 82)
721 LOG_DATA(
"{}: Cuc {}, e {}, Cus {}, sqrt_A {}",
nameId(), Cuc, e, Cus, sqrt_A);
725 if (line.size() > 82)
740 LOG_DATA(
"{}: toe {}, Cic {}, Omega_0 {}, Cis {}",
nameId(), toeSec, Cic, Omega_0, Cis);
744 if (line.size() > 82)
759 LOG_DATA(
"{}: i_0 {}, Crc {}, omega {}, Omega_dot {}",
nameId(), i_0, Crc, omega, Omega_dot);
763 if (line.size() > 82)
797 LOG_DATA(
"{}: i_dot {}, codesOnL2Channel/dataSources {} ({}), gpsWeek {}, L2PdataFlag {}",
nameId(),
798 i_dot, codesOnL2Channel_dataSources, std::bitset<10>(codesOnL2Channel_dataSources).
to_string(), gpsWeek, L2PdataFlag);
802 if (line.size() > 82)
839 LOG_DATA(
"{}: svAccuracy {}, svHealth {}, TGD {}, IODC {}",
nameId(), signalAccuracy, svHealth, tgd_bgd5a_TGD1, IODC_bgd5b_TGD2);
843 if (line.size() > 82)
860 LOG_DATA(
"{}: transmissionTime {}, fitInterval/AODC {}",
nameId(), transmissionTime, fitInterval_AODC);
864 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GPSEphemeris>(epoch, toe,
865 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
866 sqrt_A, e, i_0, Omega_0, omega, M_0,
867 delta_n, Omega_dot, i_dot, Cus, Cuc,
869 signalAccuracy, svHealth,
870 codesOnL2Channel_dataSources, L2PdataFlag,
871 tgd_bgd5a_TGD1, fitInterval_AODC));
873 else if (satSys ==
GAL)
878 if (
_gnssNavInfo.satellites().contains({ satSys, satNum })
879 && !std::bitset<10>(codesOnL2Channel_dataSources)[0])
881 const auto& navData =
_gnssNavInfo.satellites().at({ satSys, satNum }).getNavigationData();
882 auto existingEph = std::ranges::find_if(navData, [&](
const std::shared_ptr<SatNavData>& satNavData) {
884 && std::dynamic_pointer_cast<GalileoEphemeris>(satNavData)->dataSource[0];
886 if (existingEph != navData.end())
888 LOG_DATA(
"{}: Skipping ephemeris data because of dataSource priority",
nameId());
899 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GalileoEphemeris>(epoch, toe, IODE_IODnav_AODE_IODEC, a,
900 sqrt_A, e, i_0, Omega_0, omega, M_0,
901 delta_n, Omega_dot, i_dot, Cus, Cuc,
903 codesOnL2Channel_dataSources, signalAccuracy, health,
904 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
906 else if (satSys ==
BDS)
908 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<BDSEphemeris>(satNum, epoch, toe,
909 IODE_IODnav_AODE_IODEC, fitInterval_AODC, a,
910 sqrt_A, e, i_0, Omega_0, omega, M_0,
911 delta_n, Omega_dot, i_dot, Cus, Cuc,
913 signalAccuracy, svHealth,
914 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
916 else if (satSys ==
QZSS)
918 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<QZSSEphemeris>(epoch, toe,
919 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
920 sqrt_A, e, i_0, Omega_0, omega, M_0,
921 delta_n, Omega_dot, i_dot, Cus, Cuc,
923 signalAccuracy, svHealth,
924 codesOnL2Channel_dataSources, L2PdataFlag,
925 tgd_bgd5a_TGD1, fitInterval_AODC));
928 else if (satSys ==
GLO || satSys ==
SBAS)
934 Eigen::Vector3d accelLuniSolar;
938 if (
_gnssNavInfo.timeSysCorr.contains({ satSys.getTimeSystem(), UTC }))
952 LOG_DATA(
"{}: clkBias {}, relFreqBias {}, msgFrameTime {}",
nameId(), m_tau_n, gamma_n, msgFrameTime);
956 if (line.size() > 82)
972 LOG_DATA(
"{}: satPosX {}, velX {}, accelX {}, health {}",
nameId(), pos.x(), vel.x(), accelLuniSolar.x(), health);
976 if (line.size() > 82)
992 LOG_DATA(
"{}: satPosY {}, velY {}, accelY {}, freqNum/accuracyCode {}",
nameId(), pos.y(), vel.y(), accelLuniSolar.y(), frequencyNumber_accuracyCode);
996 if (line.size() > 82)
1012 LOG_DATA(
"{}: satPosZ {}, velZ {}, accelZ {}, ageOfOperation/IODN {}",
nameId(), pos.z(), vel.z(), accelLuniSolar.z(), ageOfOperation_IODN);
1016 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GLONASSEphemeris>(epoch, tau_c,
1017 -m_tau_n, gamma_n,
static_cast<bool>(health),
1018 pos, vel, accelLuniSolar,
1019 frequencyNumber_accuracyCode));
1023 LOG_WARN(
"SBAS is not yet supported. Therefore the Navigation file data will be skipped.");
1029 catch (
const std::exception& e)
1089 if (line.size() > 82)
1095 if (line.at(0) ==
'>')
1112 auto satNumStr = line.substr(7, 2);
1113 if (satNumStr ==
" ") {
continue; }
1115 auto satNum =
static_cast<uint8_t
>(
str::stoi(satNumStr, 0));
1116 if (satNum == 0) {
continue; }
1118 std::string msgType = line.substr(2, 3);
1129 if (line.size() > 82)
1147 if (line.size() > 82)
1158 int year = std::stoi(timeSplit.at(0));
1160 InsTime epoch{
static_cast<uint16_t
>(year),
1161 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1162 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1163 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1164 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1165 std::stold(timeSplit.at(5)),
1168 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.
toYMDHMS(), std::string(timeSystem));
1170 LOG_DATA(
"{}: Time System Correction: {}",
nameId(), correctionType);
1173 if (line.size() > 82)
1188 if (!std::isnan(a0) && !std::isnan(a1))
1190 std::pair<TimeSystem, TimeSystem> timeSystems;
1191 if (correctionType ==
"GPUT")
1195 else if (correctionType ==
"GLUT")
1199 else if (correctionType ==
"GAUT")
1201 timeSystems = {
GST,
UTC };
1203 else if (correctionType ==
"BDUT")
1205 timeSystems = {
BDT,
UTC };
1207 else if (correctionType ==
"QZUT")
1211 else if (correctionType ==
"IRUT")
1216 else if (correctionType ==
"GLGP")
1220 else if (correctionType ==
"GAGP")
1224 else if (correctionType ==
"GPGA")
1228 else if (correctionType ==
"QZGP")
1232 else if (correctionType ==
"IRGP")
1238 LOG_TRACE(
"{}: Time System Correction '{}' not implemented yet",
nameId(), correctionType);
1241 _gnssNavInfo.timeSysCorr[timeSystems] = { .a0 = a0, .a1 = a1 };
1253 if (line.size() > 82)
1264 int year = std::stoi(timeSplit.at(0));
1266 InsTime t_tm{
static_cast<uint16_t
>(year),
1267 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1268 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1269 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1270 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1271 std::stold(timeSplit.at(5)),
1274 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, t_tm.
toYMDHMS(), std::string(timeSystem));
1278 if (satSys ==
GPS || satSys ==
QZSS || satSys ==
IRNSS || satSys ==
BDS)
1280 std::array<double, 4> alpha{};
1281 std::array<double, 4> beta{};
1286 if (line.size() > 82)
1296 if (line.size() > 82)
1305 std::string(satSys), fmt::join(alpha.begin(), alpha.end(),
", "));
1307 std::string(satSys), fmt::join(beta.begin(), beta.end(),
", "));
1310 else if (satSys ==
GAL)
1312 std::array<double, 4> alpha{};
1317 if (line.size() > 82)
1327 std::string(satSys), fmt::join(alpha.begin(), alpha.end(),
", "));
1346 catch (
const std::exception& e)
1359 int year = std::stoi(timeSplit.at(0));
1361 InsTime epoch{
static_cast<uint16_t
>(year),
1362 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1363 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1364 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1365 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1366 std::stold(timeSplit.at(5)),
1369 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.
toYMDHMS(), std::string(timeSystem));
1371 if (satSys ==
GPS || satSys ==
GAL || satSys ==
QZSS || satSys ==
BDS)
1374 std::array<double, 3> a{};
1382 LOG_DATA(
"{}: clkBias {}, clkDrift {}, clkDriftRate {}",
nameId(), a[0], a[1], a[2]);
1386 if (line.size() > 82)
1405 LOG_DATA(
"{}: IODE_IODnav_AODE_IODEC {}, Crs {}, Delta_n {}, M0 {}",
nameId(), IODE_IODnav_AODE_IODEC, Crs, delta_n, M_0);
1409 if (line.size() > 82)
1424 LOG_DATA(
"{}: Cuc {}, e {}, Cus {}, sqrt_A {}",
nameId(), Cuc, e, Cus, sqrt_A);
1428 if (line.size() > 82)
1443 LOG_DATA(
"{}: toe {}, Cic {}, Omega_0 {}, Cis {}",
nameId(), toeSec, Cic, Omega_0, Cis);
1447 if (line.size() > 82)
1462 LOG_DATA(
"{}: i_0 {}, Crc {}, omega {}, Omega_dot {}",
nameId(), i_0, Crc, omega, Omega_dot);
1466 if (line.size() > 82)
1500 LOG_DATA(
"{}: i_dot {}, codesOnL2Channel/dataSources {} ({}), gpsWeek {}, L2PdataFlag {}",
nameId(),
1501 i_dot, codesOnL2Channel_dataSources, std::bitset<10>(codesOnL2Channel_dataSources).
to_string(), gpsWeek, L2PdataFlag);
1505 if (line.size() > 82)
1542 LOG_DATA(
"{}: svAccuracy {}, svHealth {}, TGD {}, IODC {}",
nameId(), signalAccuracy, svHealth, tgd_bgd5a_TGD1, IODC_bgd5b_TGD2);
1546 if (line.size() > 82)
1563 LOG_DATA(
"{}: transmissionTime {}, fitInterval/AODC {}",
nameId(), transmissionTime, fitInterval_AODC);
1567 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GPSEphemeris>(epoch, toe,
1568 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
1569 sqrt_A, e, i_0, Omega_0, omega, M_0,
1570 delta_n, Omega_dot, i_dot, Cus, Cuc,
1572 signalAccuracy, svHealth,
1573 codesOnL2Channel_dataSources, L2PdataFlag,
1574 tgd_bgd5a_TGD1, fitInterval_AODC));
1576 else if (satSys ==
GAL)
1581 if (
_gnssNavInfo.satellites().contains({ satSys, satNum })
1582 && !std::bitset<10>(codesOnL2Channel_dataSources)[0])
1584 const auto& navData =
_gnssNavInfo.satellites().at({ satSys, satNum }).getNavigationData();
1585 auto existingEph = std::ranges::find_if(navData, [&](
const std::shared_ptr<SatNavData>& satNavData) {
1587 && std::dynamic_pointer_cast<GalileoEphemeris>(satNavData)->dataSource[0];
1589 if (existingEph != navData.end())
1591 LOG_DATA(
"{}: Skipping ephemeris data because of dataSource priority",
nameId());
1602 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GalileoEphemeris>(epoch, toe, IODE_IODnav_AODE_IODEC, a,
1603 sqrt_A, e, i_0, Omega_0, omega, M_0,
1604 delta_n, Omega_dot, i_dot, Cus, Cuc,
1606 codesOnL2Channel_dataSources, signalAccuracy, health,
1607 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
1609 else if (satSys ==
BDS)
1611 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<BDSEphemeris>(satNum, epoch, toe,
1612 IODE_IODnav_AODE_IODEC, fitInterval_AODC, a,
1613 sqrt_A, e, i_0, Omega_0, omega, M_0,
1614 delta_n, Omega_dot, i_dot, Cus, Cuc,
1616 signalAccuracy, svHealth,
1617 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
1619 else if (satSys ==
QZSS)
1621 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<QZSSEphemeris>(epoch, toe,
1622 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
1623 sqrt_A, e, i_0, Omega_0, omega, M_0,
1624 delta_n, Omega_dot, i_dot, Cus, Cuc,
1626 signalAccuracy, svHealth,
1627 codesOnL2Channel_dataSources, L2PdataFlag,
1628 tgd_bgd5a_TGD1, fitInterval_AODC));
1631 else if (satSys ==
GLO || satSys ==
SBAS)
1635 Eigen::Vector3d pos;
1636 Eigen::Vector3d vel;
1637 Eigen::Vector3d accelLuniSolar;
1641 if (
_gnssNavInfo.timeSysCorr.contains({ satSys.getTimeSystem(), UTC }))
1655 LOG_DATA(
"{}: clkBias {}, relFreqBias {}, msgFrameTime {}",
nameId(), m_tau_n, gamma_n, msgFrameTime);
1659 if (line.size() > 82)
1675 LOG_DATA(
"{}: satPosX {}, velX {}, accelX {}, health {}",
nameId(), pos.x(), vel.x(), accelLuniSolar.x(), health);
1679 if (line.size() > 82)
1695 LOG_DATA(
"{}: satPosY {}, velY {}, accelY {}, freqNum/accuracyCode {}",
nameId(), pos.y(), vel.y(), accelLuniSolar.y(), frequencyNumber_accuracyCode);
1699 if (line.size() > 82)
1715 LOG_DATA(
"{}: satPosZ {}, velZ {}, accelZ {}, ageOfOperation/IODN {}",
nameId(), pos.z(), vel.z(), accelLuniSolar.z(), ageOfOperation_IODN);
1722 if (line.size() > 82)
1746 LOG_DATA(
"{}: statusFlags {}, L1L2groupDelayDifference {}, URAI {}, healthFlags {}",
nameId(), statusFlags, L1L2groupDelayDifference, URAI, healthFlags);
1751 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GLONASSEphemeris>(epoch, tau_c,
1752 -m_tau_n, gamma_n,
static_cast<bool>(health),
1753 pos, vel, accelLuniSolar,
1754 frequencyNumber_accuracyCode));
1758 LOG_WARN(
"SBAS is not yet supported. Therefore the Navigation file data will be skipped.");