305 while (line.find(
"RINEX VERSION / TYPE") == std::string::npos && !
eof())
311 if ((line.substr(20, 15) ==
"N: GPS NAV DATA" || line.substr(20, 15) ==
"NAVIGATION DATA")
312 && (line.substr(40, 3) ==
"GPS" ||
str::trim_copy(line.substr(40, 3)).empty()))
318 else if (line.substr(20, 16) ==
"GLONASS NAV DATA")
328 auto headerLabel = extHeaderLabel(line);
329 if (headerLabel ==
"PGM / RUN BY / DATE")
338 else if (headerLabel ==
"COMMENT")
342 else if (headerLabel ==
"IONOSPHERIC CORR")
345 std::array<double, 4> values{};
355 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
358 fmt::join(values.begin(), values.end(),
", "));
360 else if (headerLabel ==
"ION ALPHA" || headerLabel ==
"ION BETA")
362 auto correctionType = headerLabel.substr(4, 1);
364 std::array<double, 4> values{};
365 for (
size_t i = 0; i < valuesStr.size(); i++)
367 values.at(i) = std::stod(valuesStr.at(i));
371 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
374 fmt::join(values.begin(), values.end(),
", "));
376 else if (headerLabel ==
"TIME SYSTEM CORR"
377 || headerLabel ==
"CORR TO SYSTEM TIME")
386 else if (headerLabel ==
"DELTA-UTC: A0,A1,T,W")
393 if (a0 != 0 || a1 != 0)
398 else if (headerLabel ==
"LEAP SECONDS")
400 LOG_DATA(
"{}: Leap seconds: {}",
nameId(), std::stoi(line.substr(0, 6)));
402 else if (headerLabel ==
"END OF HEADER")
413 while (line.find(
"RINEX VERSION / TYPE") == std::string::npos && !
eof())
424 auto headerLabel = extHeaderLabel(line);
425 if (headerLabel ==
"PGM / RUN BY / DATE")
434 else if (headerLabel ==
"COMMENT")
438 else if (headerLabel ==
"IONOSPHERIC CORR")
441 std::array<double, 4> values{};
451 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
454 fmt::join(values.begin(), values.end(),
", "));
456 else if (headerLabel ==
"ION ALPHA" || headerLabel ==
"ION BETA")
458 auto correctionType = headerLabel.substr(4, 1);
460 std::array<double, 4> values{};
461 for (
size_t i = 0; i < valuesStr.size(); i++)
463 values.at(i) = std::stod(valuesStr.at(i));
467 _gnssNavInfo.ionosphericCorrections.insert(satSys, alphaBeta, values);
470 fmt::join(values.begin(), values.end(),
", "));
472 else if (headerLabel ==
"TIME SYSTEM CORR"
473 || headerLabel ==
"CORR TO SYSTEM TIME")
476 LOG_DATA(
"{}: Time System Correction: {}",
nameId(), correctionType);
478 std::array<size_t, 2> x{ 5, 22 };
479 std::array<size_t, 2> n{ 17, 16 };
481 if (correctionType ==
"SBUT")
486 else if (correctionType ==
"GLUT")
497 if (!std::isnan(a0) && !std::isnan(a1))
499 std::pair<TimeSystem, TimeSystem> timeSystems;
500 if (correctionType ==
"GPUT") { timeSystems = {
GPST,
UTC }; }
501 else if (correctionType ==
"GLUT") { timeSystems = {
GLNT,
UTC }; }
502 else if (correctionType ==
"GAUT") { timeSystems = {
GST,
UTC }; }
503 else if (correctionType ==
"BDUT") { timeSystems = {
BDT,
UTC }; }
504 else if (correctionType ==
"QZUT") { timeSystems = {
QZSST,
UTC }; }
505 else if (correctionType ==
"IRUT") { timeSystems = {
IRNSST,
UTC }; }
507 else if (correctionType ==
"GLGP") { timeSystems = {
GLNT,
GPST }; }
508 else if (correctionType ==
"GAGP") { timeSystems = {
GST,
GPST }; }
509 else if (correctionType ==
"GPGA") { timeSystems = {
GST,
GPST }; }
510 else if (correctionType ==
"QZGP") { timeSystems = {
QZSST,
GPST }; }
511 else if (correctionType ==
"IRGP") { timeSystems = {
IRNSST,
GPST }; }
514 LOG_TRACE(
"{}: Time System Correction '{}' not implemented yet",
nameId(), correctionType);
517 _gnssNavInfo.timeSysCorr[timeSystems] = { .a0 = a0, .a1 = a1 };
520 else if (headerLabel ==
"DELTA-UTC: A0,A1,T,W")
527 if (a0 != 0 || a1 != 0)
532 else if (headerLabel ==
"LEAP SECONDS")
534 LOG_DATA(
"{}: Leap seconds: {}",
nameId(), std::stoi(line.substr(0, 6)));
536 else if (headerLabel ==
"END OF HEADER")
623 if (line.size() > 82)
645 auto satNumStr = line.substr(0, 2);
646 if (satNumStr ==
" ") {
continue; }
648 auto satNum =
static_cast<uint8_t
>(
str::stoi(satNumStr, 0));
649 if (satNum == 0) {
continue; }
655 int year = std::stoi(timeSplit.at(0));
658 year += (year >= 80 ? 1900 : 2000);
660 InsTime epoch{
static_cast<uint16_t
>(year),
661 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
662 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
663 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
664 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
665 std::stold(timeSplit.at(5)),
668 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.toYMDHMS(), std::string(timeSystem));
670 if (satSys ==
GPS || satSys ==
GAL || satSys ==
QZSS || satSys ==
BDS)
673 std::array<double, 3> a{};
681 LOG_DATA(
"{}: clkBias {}, clkDrift {}, clkDriftRate {}",
nameId(), a[0], a[1], a[2]);
685 if (line.size() > 82)
704 LOG_DATA(
"{}: IODE_IODnav_AODE_IODEC {}, Crs {}, Delta_n {}, M0 {}",
nameId(), IODE_IODnav_AODE_IODEC, Crs, delta_n, M_0);
708 if (line.size() > 82)
723 LOG_DATA(
"{}: Cuc {}, e {}, Cus {}, sqrt_A {}",
nameId(), Cuc, e, Cus, sqrt_A);
727 if (line.size() > 82)
742 LOG_DATA(
"{}: toe {}, Cic {}, Omega_0 {}, Cis {}",
nameId(), toeSec, Cic, Omega_0, Cis);
746 if (line.size() > 82)
761 LOG_DATA(
"{}: i_0 {}, Crc {}, omega {}, Omega_dot {}",
nameId(), i_0, Crc, omega, Omega_dot);
765 if (line.size() > 82)
799 LOG_DATA(
"{}: i_dot {}, codesOnL2Channel/dataSources {} ({}), gpsWeek {}, L2PdataFlag {}",
nameId(),
800 i_dot, codesOnL2Channel_dataSources, std::bitset<10>(codesOnL2Channel_dataSources).
to_string(), gpsWeek, L2PdataFlag);
804 if (line.size() > 82)
841 LOG_DATA(
"{}: svAccuracy {}, svHealth {}, TGD {}, IODC {}",
nameId(), signalAccuracy, svHealth, tgd_bgd5a_TGD1, IODC_bgd5b_TGD2);
845 if (line.size() > 82)
862 LOG_DATA(
"{}: transmissionTime {}, fitInterval/AODC {}",
nameId(), transmissionTime, fitInterval_AODC);
866 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GPSEphemeris>(epoch, toe,
867 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
868 sqrt_A, e, i_0, Omega_0, omega, M_0,
869 delta_n, Omega_dot, i_dot, Cus, Cuc,
871 signalAccuracy, svHealth,
872 codesOnL2Channel_dataSources, L2PdataFlag,
873 tgd_bgd5a_TGD1, fitInterval_AODC));
875 else if (satSys ==
GAL)
880 if (
_gnssNavInfo.satellites().contains({ satSys, satNum })
881 && !std::bitset<10>(codesOnL2Channel_dataSources)[0])
883 const auto& navData =
_gnssNavInfo.satellites().at({ satSys, satNum }).getNavigationData();
884 auto existingEph = std::ranges::find_if(navData, [&](
const std::shared_ptr<SatNavData>& satNavData) {
886 && std::dynamic_pointer_cast<GalileoEphemeris>(satNavData)->dataSource[0];
888 if (existingEph != navData.end())
890 LOG_DATA(
"{}: Skipping ephemeris data because of dataSource priority",
nameId());
901 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GalileoEphemeris>(epoch, toe, IODE_IODnav_AODE_IODEC, a,
902 sqrt_A, e, i_0, Omega_0, omega, M_0,
903 delta_n, Omega_dot, i_dot, Cus, Cuc,
905 codesOnL2Channel_dataSources, signalAccuracy, health,
906 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
908 else if (satSys ==
BDS)
910 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<BDSEphemeris>(satNum, epoch, toe,
911 IODE_IODnav_AODE_IODEC, fitInterval_AODC, a,
912 sqrt_A, e, i_0, Omega_0, omega, M_0,
913 delta_n, Omega_dot, i_dot, Cus, Cuc,
915 signalAccuracy, svHealth,
916 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
918 else if (satSys ==
QZSS)
920 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<QZSSEphemeris>(epoch, toe,
921 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
922 sqrt_A, e, i_0, Omega_0, omega, M_0,
923 delta_n, Omega_dot, i_dot, Cus, Cuc,
925 signalAccuracy, svHealth,
926 codesOnL2Channel_dataSources, L2PdataFlag,
927 tgd_bgd5a_TGD1, fitInterval_AODC));
930 else if (satSys ==
GLO || satSys ==
SBAS)
936 Eigen::Vector3d accelLuniSolar;
940 if (
_gnssNavInfo.timeSysCorr.contains({ satSys.getTimeSystem(), UTC }))
954 LOG_DATA(
"{}: clkBias {}, relFreqBias {}, msgFrameTime {}",
nameId(), m_tau_n, gamma_n, msgFrameTime);
958 if (line.size() > 82)
974 LOG_DATA(
"{}: satPosX {}, velX {}, accelX {}, health {}",
nameId(), pos.x(), vel.x(), accelLuniSolar.x(), health);
978 if (line.size() > 82)
994 LOG_DATA(
"{}: satPosY {}, velY {}, accelY {}, freqNum/accuracyCode {}",
nameId(), pos.y(), vel.y(), accelLuniSolar.y(), frequencyNumber_accuracyCode);
998 if (line.size() > 82)
1014 LOG_DATA(
"{}: satPosZ {}, velZ {}, accelZ {}, ageOfOperation/IODN {}",
nameId(), pos.z(), vel.z(), accelLuniSolar.z(), ageOfOperation_IODN);
1018 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GLONASSEphemeris>(epoch, tau_c,
1019 -m_tau_n, gamma_n,
static_cast<bool>(health),
1020 pos, vel, accelLuniSolar,
1021 frequencyNumber_accuracyCode));
1025 LOG_WARN(
"SBAS is not yet supported. Therefore the Navigation file data will be skipped.");
1031 catch (
const std::exception& e)
1091 if (line.size() > 82)
1097 if (line.at(0) ==
'>')
1114 auto satNumStr = line.substr(7, 2);
1115 if (satNumStr ==
" ") {
continue; }
1117 auto satNum =
static_cast<uint8_t
>(
str::stoi(satNumStr, 0));
1118 if (satNum == 0) {
continue; }
1120 std::string msgType = line.substr(2, 3);
1131 if (line.size() > 82)
1149 if (line.size() > 82)
1160 int year = std::stoi(timeSplit.at(0));
1162 InsTime epoch{
static_cast<uint16_t
>(year),
1163 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1164 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1165 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1166 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1167 std::stold(timeSplit.at(5)),
1170 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.toYMDHMS(), std::string(timeSystem));
1172 LOG_DATA(
"{}: Time System Correction: {}",
nameId(), correctionType);
1175 if (line.size() > 82)
1190 if (!std::isnan(a0) && !std::isnan(a1))
1192 std::pair<TimeSystem, TimeSystem> timeSystems;
1193 if (correctionType ==
"GPUT")
1197 else if (correctionType ==
"GLUT")
1201 else if (correctionType ==
"GAUT")
1203 timeSystems = {
GST,
UTC };
1205 else if (correctionType ==
"BDUT")
1207 timeSystems = {
BDT,
UTC };
1209 else if (correctionType ==
"QZUT")
1213 else if (correctionType ==
"IRUT")
1218 else if (correctionType ==
"GLGP")
1222 else if (correctionType ==
"GAGP")
1226 else if (correctionType ==
"GPGA")
1230 else if (correctionType ==
"QZGP")
1234 else if (correctionType ==
"IRGP")
1240 LOG_TRACE(
"{}: Time System Correction '{}' not implemented yet",
nameId(), correctionType);
1243 _gnssNavInfo.timeSysCorr[timeSystems] = { .a0 = a0, .a1 = a1 };
1255 if (line.size() > 82)
1266 int year = std::stoi(timeSplit.at(0));
1268 InsTime t_tm{
static_cast<uint16_t
>(year),
1269 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1270 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1271 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1272 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1273 std::stold(timeSplit.at(5)),
1276 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, t_tm.toYMDHMS(), std::string(timeSystem));
1280 if (satSys ==
GPS || satSys ==
QZSS || satSys ==
IRNSS || satSys ==
BDS)
1282 std::array<double, 4> alpha{};
1283 std::array<double, 4> beta{};
1288 if (line.size() > 82)
1298 if (line.size() > 82)
1307 std::string(satSys), fmt::join(alpha.begin(), alpha.end(),
", "));
1309 std::string(satSys), fmt::join(beta.begin(), beta.end(),
", "));
1312 else if (satSys ==
GAL)
1314 std::array<double, 4> alpha{};
1319 if (line.size() > 82)
1329 std::string(satSys), fmt::join(alpha.begin(), alpha.end(),
", "));
1348 catch (
const std::exception& e)
1361 int year = std::stoi(timeSplit.at(0));
1363 InsTime epoch{
static_cast<uint16_t
>(year),
1364 static_cast<uint16_t
>(std::stoi(timeSplit.at(1))),
1365 static_cast<uint16_t
>(std::stoi(timeSplit.at(2))),
1366 static_cast<uint16_t
>(std::stoi(timeSplit.at(3))),
1367 static_cast<uint16_t
>(std::stoi(timeSplit.at(4))),
1368 std::stold(timeSplit.at(5)),
1371 LOG_DATA(
"{}: {}-{} {} (read as {} time)",
nameId(), satSys, satNum, epoch.toYMDHMS(), std::string(timeSystem));
1373 if (satSys ==
GPS || satSys ==
GAL || satSys ==
QZSS || satSys ==
BDS)
1376 std::array<double, 3> a{};
1384 LOG_DATA(
"{}: clkBias {}, clkDrift {}, clkDriftRate {}",
nameId(), a[0], a[1], a[2]);
1388 if (line.size() > 82)
1407 LOG_DATA(
"{}: IODE_IODnav_AODE_IODEC {}, Crs {}, Delta_n {}, M0 {}",
nameId(), IODE_IODnav_AODE_IODEC, Crs, delta_n, M_0);
1411 if (line.size() > 82)
1426 LOG_DATA(
"{}: Cuc {}, e {}, Cus {}, sqrt_A {}",
nameId(), Cuc, e, Cus, sqrt_A);
1430 if (line.size() > 82)
1445 LOG_DATA(
"{}: toe {}, Cic {}, Omega_0 {}, Cis {}",
nameId(), toeSec, Cic, Omega_0, Cis);
1449 if (line.size() > 82)
1464 LOG_DATA(
"{}: i_0 {}, Crc {}, omega {}, Omega_dot {}",
nameId(), i_0, Crc, omega, Omega_dot);
1468 if (line.size() > 82)
1502 LOG_DATA(
"{}: i_dot {}, codesOnL2Channel/dataSources {} ({}), gpsWeek {}, L2PdataFlag {}",
nameId(),
1503 i_dot, codesOnL2Channel_dataSources, std::bitset<10>(codesOnL2Channel_dataSources).
to_string(), gpsWeek, L2PdataFlag);
1507 if (line.size() > 82)
1544 LOG_DATA(
"{}: svAccuracy {}, svHealth {}, TGD {}, IODC {}",
nameId(), signalAccuracy, svHealth, tgd_bgd5a_TGD1, IODC_bgd5b_TGD2);
1548 if (line.size() > 82)
1565 LOG_DATA(
"{}: transmissionTime {}, fitInterval/AODC {}",
nameId(), transmissionTime, fitInterval_AODC);
1569 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GPSEphemeris>(epoch, toe,
1570 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
1571 sqrt_A, e, i_0, Omega_0, omega, M_0,
1572 delta_n, Omega_dot, i_dot, Cus, Cuc,
1574 signalAccuracy, svHealth,
1575 codesOnL2Channel_dataSources, L2PdataFlag,
1576 tgd_bgd5a_TGD1, fitInterval_AODC));
1578 else if (satSys ==
GAL)
1583 if (
_gnssNavInfo.satellites().contains({ satSys, satNum })
1584 && !std::bitset<10>(codesOnL2Channel_dataSources)[0])
1586 const auto& navData =
_gnssNavInfo.satellites().at({ satSys, satNum }).getNavigationData();
1587 auto existingEph = std::ranges::find_if(navData, [&](
const std::shared_ptr<SatNavData>& satNavData) {
1589 && std::dynamic_pointer_cast<GalileoEphemeris>(satNavData)->dataSource[0];
1591 if (existingEph != navData.end())
1593 LOG_DATA(
"{}: Skipping ephemeris data because of dataSource priority",
nameId());
1604 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GalileoEphemeris>(epoch, toe, IODE_IODnav_AODE_IODEC, a,
1605 sqrt_A, e, i_0, Omega_0, omega, M_0,
1606 delta_n, Omega_dot, i_dot, Cus, Cuc,
1608 codesOnL2Channel_dataSources, signalAccuracy, health,
1609 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
1611 else if (satSys ==
BDS)
1613 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<BDSEphemeris>(satNum, epoch, toe,
1614 IODE_IODnav_AODE_IODEC, fitInterval_AODC, a,
1615 sqrt_A, e, i_0, Omega_0, omega, M_0,
1616 delta_n, Omega_dot, i_dot, Cus, Cuc,
1618 signalAccuracy, svHealth,
1619 tgd_bgd5a_TGD1, IODC_bgd5b_TGD2));
1621 else if (satSys ==
QZSS)
1623 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<QZSSEphemeris>(epoch, toe,
1624 IODE_IODnav_AODE_IODEC, IODC_bgd5b_TGD2, a,
1625 sqrt_A, e, i_0, Omega_0, omega, M_0,
1626 delta_n, Omega_dot, i_dot, Cus, Cuc,
1628 signalAccuracy, svHealth,
1629 codesOnL2Channel_dataSources, L2PdataFlag,
1630 tgd_bgd5a_TGD1, fitInterval_AODC));
1633 else if (satSys ==
GLO || satSys ==
SBAS)
1637 Eigen::Vector3d pos;
1638 Eigen::Vector3d vel;
1639 Eigen::Vector3d accelLuniSolar;
1643 if (
_gnssNavInfo.timeSysCorr.contains({ satSys.getTimeSystem(), UTC }))
1657 LOG_DATA(
"{}: clkBias {}, relFreqBias {}, msgFrameTime {}",
nameId(), m_tau_n, gamma_n, msgFrameTime);
1661 if (line.size() > 82)
1677 LOG_DATA(
"{}: satPosX {}, velX {}, accelX {}, health {}",
nameId(), pos.x(), vel.x(), accelLuniSolar.x(), health);
1681 if (line.size() > 82)
1697 LOG_DATA(
"{}: satPosY {}, velY {}, accelY {}, freqNum/accuracyCode {}",
nameId(), pos.y(), vel.y(), accelLuniSolar.y(), frequencyNumber_accuracyCode);
1701 if (line.size() > 82)
1717 LOG_DATA(
"{}: satPosZ {}, velZ {}, accelZ {}, ageOfOperation/IODN {}",
nameId(), pos.z(), vel.z(), accelLuniSolar.z(), ageOfOperation_IODN);
1724 if (line.size() > 82)
1748 LOG_DATA(
"{}: statusFlags {}, L1L2groupDelayDifference {}, URAI {}, healthFlags {}",
nameId(), statusFlags, L1L2groupDelayDifference, URAI, healthFlags);
1753 _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GLONASSEphemeris>(epoch, tau_c,
1754 -m_tau_n, gamma_n,
static_cast<bool>(health),
1755 pos, vel, accelLuniSolar,
1756 frequencyNumber_accuracyCode));
1760 LOG_WARN(
"SBAS is not yet supported. Therefore the Navigation file data will be skipped.");