| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
| 2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
| 3 | // the University of Stuttgart, Germany. | ||
| 4 | // | ||
| 5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
| 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| 7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| 8 | |||
| 9 | #include "UbloxGnssOrbitCollector.hpp" | ||
| 10 | |||
| 11 | #include <algorithm> | ||
| 12 | #include <chrono> | ||
| 13 | #include <cstddef> | ||
| 14 | #include <imgui.h> | ||
| 15 | #include <imgui_internal.h> | ||
| 16 | |||
| 17 | #include "util/Logger.hpp" | ||
| 18 | #include "util/Container/STL.hpp" | ||
| 19 | |||
| 20 | #include <fmt/format.h> | ||
| 21 | #include "internal/FlowManager.hpp" | ||
| 22 | |||
| 23 | #include "Navigation/GNSS/Satellite/Ephemeris/GPSEphemeris.hpp" | ||
| 24 | #include "Navigation/GNSS/Satellite/Ephemeris/GalileoEphemeris.hpp" | ||
| 25 | #include "Navigation/GNSS/Satellite/Ephemeris/GLONASSEphemeris.hpp" | ||
| 26 | #include "Navigation/GNSS/Satellite/Ephemeris/BDSEphemeris.hpp" | ||
| 27 | #include "Navigation/GNSS/Functions.hpp" | ||
| 28 | #include "Navigation/Transformations/Units.hpp" | ||
| 29 | |||
| 30 | 115 | NAV::UbloxGnssOrbitCollector::UbloxGnssOrbitCollector() | |
| 31 |
2/4✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 115 times.
✗ Branch 5 not taken.
|
115 | : Node(typeStatic()) |
| 32 | { | ||
| 33 | LOG_TRACE("{}: called", name); | ||
| 34 | 115 | _hasConfig = true; | |
| 35 | |||
| 36 |
4/8✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 115 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 115 times.
✓ Branch 9 taken 115 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
345 | CreateInputPin("UbloxObs", Pin::Type::Flow, { NAV::UbloxObs::type() }, &UbloxGnssOrbitCollector::receiveObs); |
| 37 | |||
| 38 |
5/10✓ Branch 2 taken 115 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 115 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 115 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 115 times.
✓ Branch 15 taken 115 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
460 | CreateOutputPin(GnssNavInfo::type().c_str(), Pin::Type::Object, { GnssNavInfo::type() }, &_gnssNavInfo); |
| 39 | 345 | } | |
| 40 | |||
| 41 | 232 | NAV::UbloxGnssOrbitCollector::~UbloxGnssOrbitCollector() | |
| 42 | { | ||
| 43 | LOG_TRACE("{}: called", nameId()); | ||
| 44 | 232 | } | |
| 45 | |||
| 46 | 229 | std::string NAV::UbloxGnssOrbitCollector::typeStatic() | |
| 47 | { | ||
| 48 |
1/2✓ Branch 1 taken 229 times.
✗ Branch 2 not taken.
|
458 | return "UbloxGnssOrbitCollector"; |
| 49 | } | ||
| 50 | |||
| 51 | ✗ | std::string NAV::UbloxGnssOrbitCollector::type() const | |
| 52 | { | ||
| 53 | ✗ | return typeStatic(); | |
| 54 | } | ||
| 55 | |||
| 56 | 114 | std::string NAV::UbloxGnssOrbitCollector::category() | |
| 57 | { | ||
| 58 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
228 | return "Converter"; |
| 59 | } | ||
| 60 | |||
| 61 | ✗ | void NAV::UbloxGnssOrbitCollector::guiConfig() | |
| 62 | { | ||
| 63 | ✗ | bool isDisabled = ImGui::GetCurrentContext()->CurrentItemFlags & ImGuiItemFlags_Disabled; | |
| 64 | |||
| 65 | ✗ | if (isDisabled) { ImGui::EndDisabled(); } | |
| 66 | ✗ | if (ImGui::BeginTable(fmt::format("{} UbloxGnssOrbitCollector", size_t(id)).c_str(), 4, | |
| 67 | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX)) | ||
| 68 | { | ||
| 69 | ✗ | ImGui::TableSetupColumn(""); | |
| 70 | ✗ | ImGui::TableSetupColumn("Received"); | |
| 71 | ✗ | ImGui::TableSetupColumn("Iono"); | |
| 72 | ✗ | ImGui::TableSetupColumn("Building"); | |
| 73 | ✗ | ImGui::TableHeadersRow(); | |
| 74 | |||
| 75 | ✗ | for (uint64_t sys = 0xFF; sys < static_cast<uint64_t>(0xFF) << (7 * 8); sys = sys << 8UL) | |
| 76 | { | ||
| 77 | ✗ | ImGui::TableNextRow(); | |
| 78 | ✗ | ImGui::TableNextColumn(); | |
| 79 | |||
| 80 | ✗ | ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImGuiCol_TableHeaderBg)); | |
| 81 | ✗ | SatelliteSystem satSys{ SatelliteSystem_(sys) }; | |
| 82 | ✗ | ImGui::TextUnformatted(fmt::format("{}", satSys).c_str()); | |
| 83 | |||
| 84 | ✗ | ImGui::TableNextColumn(); | |
| 85 | ✗ | size_t i = 0; | |
| 86 | ✗ | constexpr size_t ITEMS_PER_ROW = 4; | |
| 87 | ✗ | for (const auto& [satId, sat] : _gnssNavInfo.satellites()) | |
| 88 | { | ||
| 89 | ✗ | if (satId.satSys != satSys) { continue; } | |
| 90 | ✗ | if (i % ITEMS_PER_ROW != 0) | |
| 91 | { | ||
| 92 | ✗ | ImGui::SameLine(); | |
| 93 | ✗ | ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::GetStyle().ItemSpacing.x); | |
| 94 | ✗ | ImGui::TextUnformatted(", "); | |
| 95 | ✗ | ImGui::SameLine(); | |
| 96 | } | ||
| 97 | ✗ | ImGui::TextUnformatted(fmt::format("{}", satId).c_str()); | |
| 98 | ✗ | if (ImGui::IsItemHovered()) | |
| 99 | { | ||
| 100 | ✗ | ImGui::BeginTooltip(); | |
| 101 | ✗ | for (const auto& satNavData : sat.getNavigationData()) | |
| 102 | { | ||
| 103 | ✗ | ImGui::TextUnformatted(fmt::format("{}", satNavData->refTime.toYMDHMS(GPST)).c_str()); | |
| 104 | } | ||
| 105 | ✗ | ImGui::EndTooltip(); | |
| 106 | } | ||
| 107 | ✗ | i++; | |
| 108 | } | ||
| 109 | |||
| 110 | ✗ | ImGui::TableNextColumn(); | |
| 111 | ✗ | std::string iono; | |
| 112 | ✗ | for (const auto& correction : _gnssNavInfo.ionosphericCorrections.data()) | |
| 113 | { | ||
| 114 | ✗ | if (correction.satSys != satSys) { continue; } | |
| 115 | ✗ | if (!iono.empty()) { iono += ", "; } | |
| 116 | ✗ | iono += correction.alphaBeta == IonosphericCorrections::Alpha ? "α" : "β"; | |
| 117 | } | ||
| 118 | ✗ | ImGui::TextUnformatted(iono.c_str()); | |
| 119 | |||
| 120 | ✗ | ImGui::TableNextColumn(); | |
| 121 | ✗ | for (const auto& builder : _ephemerisBuilder) | |
| 122 | { | ||
| 123 | ✗ | if (builder.satId.satSys != satSys | |
| 124 | ✗ | || std::ranges::any_of(_gnssNavInfo.satellites(), [&](const auto& sat) { | |
| 125 | ✗ | if (builder.satId != sat.first) { return false; } | |
| 126 | ✗ | return std::ranges::any_of(sat.second.getNavigationData(), [&](const std::shared_ptr<NAV::SatNavData>& satNavData) { | |
| 127 | ✗ | return satNavData->refTime == builder.navData->refTime; | |
| 128 | ✗ | }); | |
| 129 | })) | ||
| 130 | { | ||
| 131 | ✗ | continue; | |
| 132 | } | ||
| 133 | |||
| 134 | ✗ | ImGui::TextUnformatted(fmt::format("{} ({}) frames: {}", builder.satId, builder.navData->refTime.toYMDHMS(GPST), builder.subframes).c_str()); | |
| 135 | } | ||
| 136 | ✗ | } | |
| 137 | |||
| 138 | ✗ | ImGui::EndTable(); | |
| 139 | } | ||
| 140 | ✗ | if (isDisabled) { ImGui::BeginDisabled(); } | |
| 141 | ✗ | } | |
| 142 | |||
| 143 | 3 | bool NAV::UbloxGnssOrbitCollector::initialize() | |
| 144 | { | ||
| 145 | LOG_TRACE("{}: called", nameId()); | ||
| 146 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (!_postProcessingLock.has_value()) |
| 147 | { | ||
| 148 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | auto guard = requestOutputValueLock(OUTPUT_PORT_INDEX_GNSS_NAV_INFO); |
| 149 | 3 | _gnssNavInfo.reset(); | |
| 150 | 3 | } | |
| 151 | else | ||
| 152 | { | ||
| 153 | ✗ | _gnssNavInfo.reset(); | |
| 154 | } | ||
| 155 | 3 | _ephemerisBuilder.clear(); | |
| 156 | 3 | _lastAccessedBuilder.clear(); | |
| 157 | 3 | _warningsNotImplemented.clear(); | |
| 158 | |||
| 159 | 3 | if (inputPins.at(INPUT_PORT_INDEX_UBLOX_OBS).isPinLinked() | |
| 160 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | && getMode() == Mode::POST_PROCESSING |
| 161 |
4/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
|
6 | && !_postProcessingLock.has_value()) |
| 162 | { | ||
| 163 | LOG_TRACE("{}: Setting post-processing lock", nameId()); | ||
| 164 | 1 | _postProcessingLock.emplace(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex); | |
| 165 | } | ||
| 166 | |||
| 167 | 3 | return true; | |
| 168 | } | ||
| 169 | |||
| 170 | 1 | void NAV::UbloxGnssOrbitCollector::onDeleteLink([[maybe_unused]] OutputPin& startPin, [[maybe_unused]] InputPin& endPin) | |
| 171 | { | ||
| 172 | LOG_TRACE("{}: called for {} ==> {}", nameId(), size_t(startPin.id), size_t(endPin.id)); | ||
| 173 | |||
| 174 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (_postProcessingLock.has_value()) |
| 175 | { | ||
| 176 | 1 | _postProcessingLock.reset(); | |
| 177 | } | ||
| 178 | 1 | } | |
| 179 | |||
| 180 | 718 | NAV::UbloxGnssOrbitCollector::EphemerisBuilder& NAV::UbloxGnssOrbitCollector::getEphemerisBuilder(const SatId& satId, const InsTime& insTime, size_t IOD) | |
| 181 | { | ||
| 182 | LOG_DATA("{}: Searching for [{}] at [{}]", nameId(), satId, insTime.toYMDHMS(GPST)); | ||
| 183 |
2/2✓ Branch 0 taken 227 times.
✓ Branch 1 taken 491 times.
|
718 | if (IOD != 0) |
| 184 | { | ||
| 185 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | _lastAccessedBuilder[satId] = IOD; |
| 186 | } | ||
| 187 | |||
| 188 |
1/2✓ Branch 1 taken 718 times.
✗ Branch 2 not taken.
|
718 | auto iter = std::ranges::find_if(_ephemerisBuilder, [&](const auto& builder) { |
| 189 |
4/4✓ Branch 1 taken 875 times.
✓ Branch 2 taken 8649 times.
✓ Branch 5 taken 671 times.
✓ Branch 6 taken 204 times.
|
9524 | return builder.satId == satId && builder.navData->refTime == insTime; |
| 190 | }); | ||
| 191 |
2/2✓ Branch 2 taken 47 times.
✓ Branch 3 taken 671 times.
|
718 | if (iter == _ephemerisBuilder.end()) |
| 192 | { | ||
| 193 | LOG_DATA("{}: Constructing new builder", nameId()); | ||
| 194 | |||
| 195 | 47 | std::shared_ptr<SatNavData> satNavData = nullptr; | |
| 196 |
2/9✓ Branch 1 taken 19 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
47 | switch (SatelliteSystem_(satId.satSys)) |
| 197 | { | ||
| 198 | 19 | case GPS: | |
| 199 |
1/2✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
|
19 | satNavData = std::make_shared<GPSEphemeris>(insTime); |
| 200 | 19 | break; | |
| 201 | 28 | case GAL: | |
| 202 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | satNavData = std::make_shared<GalileoEphemeris>(insTime); |
| 203 | 28 | break; | |
| 204 | ✗ | case GLO: | |
| 205 | // satNavData = std::make_shared<GLONASSEphemeris>(insTime); | ||
| 206 | ✗ | LOG_CRITICAL("{}: GLONASS not implemented yet.", nameId()); // TODO: Not yet supported | |
| 207 | break; | ||
| 208 | ✗ | case BDS: | |
| 209 | // satNavData = std::make_shared<BDSEphemeris>(insTime); | ||
| 210 | ✗ | LOG_CRITICAL("{}: BeiDou not implemented yet.", nameId()); // TODO: Not yet supported | |
| 211 | break; | ||
| 212 | ✗ | case QZSS: | |
| 213 | ✗ | LOG_CRITICAL("{}: QZSS not implemented yet.", nameId()); // TODO: Not yet supported | |
| 214 | break; | ||
| 215 | ✗ | case IRNSS: | |
| 216 | ✗ | LOG_CRITICAL("{}: IRNSS not implemented yet.", nameId()); // TODO: Not yet supported | |
| 217 | break; | ||
| 218 | ✗ | case SBAS: | |
| 219 | ✗ | LOG_CRITICAL("{}: SBAS not implemented yet.", nameId()); // TODO: Not yet supported | |
| 220 | break; | ||
| 221 | ✗ | case SatSys_None: | |
| 222 | ✗ | LOG_CRITICAL("{}: Satellite system cannot be none.", nameId()); | |
| 223 | break; | ||
| 224 | } | ||
| 225 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | return _ephemerisBuilder.emplace_back(satId, satNavData); |
| 226 | 47 | } | |
| 227 | |||
| 228 | LOG_DATA("{}: Found builder", nameId()); | ||
| 229 | 671 | return *iter; | |
| 230 | } | ||
| 231 | |||
| 232 | std::optional<std::reference_wrapper<NAV::UbloxGnssOrbitCollector::EphemerisBuilder>> | ||
| 233 | 1184 | NAV::UbloxGnssOrbitCollector::getEphemerisBuilder(const SatId& satId, size_t IOD) | |
| 234 | { | ||
| 235 | LOG_DATA("{}: Searching for [{}] at Issue of Data [{}]", nameId(), satId, IOD); | ||
| 236 |
1/2✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
|
1184 | _lastAccessedBuilder[satId] = IOD; |
| 237 | |||
| 238 |
1/2✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
|
1184 | auto iter = std::ranges::find_if(_ephemerisBuilder, [&](const auto& builder) { |
| 239 |
2/2✓ Branch 1 taken 1828 times.
✓ Branch 2 taken 20327 times.
|
22155 | if (builder.satId == satId) |
| 240 | { | ||
| 241 |
2/2✓ Branch 1 taken 262 times.
✓ Branch 2 taken 1566 times.
|
1828 | if (builder.navData->type == SatNavData::GPSEphemeris) |
| 242 | { | ||
| 243 | 262 | auto ephemeris = std::dynamic_pointer_cast<GPSEphemeris>(builder.navData); | |
| 244 |
3/4✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 246 times.
✓ Branch 5 taken 16 times.
|
262 | return ephemeris && ephemeris->IODE == IOD; |
| 245 | 262 | } | |
| 246 |
1/2✓ Branch 1 taken 1566 times.
✗ Branch 2 not taken.
|
1566 | if (builder.navData->type == SatNavData::GalileoEphemeris) |
| 247 | { | ||
| 248 | 1566 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(builder.navData); | |
| 249 |
3/4✓ Branch 1 taken 1566 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 876 times.
✓ Branch 5 taken 690 times.
|
1566 | return ephemeris && ephemeris->IODnav == IOD; |
| 250 | 1566 | } | |
| 251 | } | ||
| 252 | 20327 | return false; | |
| 253 | }); | ||
| 254 |
2/2✓ Branch 2 taken 1122 times.
✓ Branch 3 taken 62 times.
|
1184 | if (iter != _ephemerisBuilder.end()) |
| 255 | { | ||
| 256 | LOG_DATA("{}: Found builder", nameId()); | ||
| 257 | 1122 | return *iter; | |
| 258 | } | ||
| 259 | LOG_DATA("{}: Could not find builder. Ignoring subframe.", nameId()); | ||
| 260 | 62 | return std::nullopt; | |
| 261 | } | ||
| 262 | |||
| 263 | std::optional<std::reference_wrapper<NAV::UbloxGnssOrbitCollector::EphemerisBuilder>> | ||
| 264 | 238 | NAV::UbloxGnssOrbitCollector::getLastEphemerisBuilder(const SatId& satId) | |
| 265 | { | ||
| 266 | LOG_DATA("{}: Searching the last builder for [{}]", nameId(), satId); | ||
| 267 |
1/2✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
|
238 | if (_lastAccessedBuilder.contains(satId)) |
| 268 | { | ||
| 269 | 238 | return getEphemerisBuilder(satId, _lastAccessedBuilder.at(satId)); | |
| 270 | } | ||
| 271 | LOG_DATA("{}: Could not find last accessed builder. Ignoring subframe.", nameId()); | ||
| 272 | ✗ | return std::nullopt; | |
| 273 | } | ||
| 274 | |||
| 275 | 8207 | void NAV::UbloxGnssOrbitCollector::receiveObs(NAV::InputPin::NodeDataQueue& queue, size_t /* pinIdx */) | |
| 276 | { | ||
| 277 |
1/2✓ Branch 1 taken 8207 times.
✗ Branch 2 not taken.
|
8207 | [[maybe_unused]] auto ubloxObs = std::static_pointer_cast<const UbloxObs>(queue.extract_front()); |
| 278 | LOG_DATA("{}: [{}] Received UbloxObs {}-{}", nameId(), ubloxObs->insTime.toYMDHMS(GPST), | ||
| 279 | vendor::ublox::getStringFromMsgClass(ubloxObs->msgClass), | ||
| 280 | vendor::ublox::getStringFromMsgId(ubloxObs->msgClass, ubloxObs->msgId)); | ||
| 281 | |||
| 282 |
1/2✓ Branch 1 taken 8207 times.
✗ Branch 2 not taken.
|
8207 | if (ubloxObs->msgClass == ubx::UBX_CLASS_RXM) |
| 283 | { | ||
| 284 |
2/2✓ Branch 1 taken 6607 times.
✓ Branch 2 taken 1600 times.
|
8207 | if (static_cast<ubx::UbxRxmMessages>(ubloxObs->msgId) == ubx::UbxRxmMessages::UBX_RXM_SFRBX) |
| 285 | { | ||
| 286 |
1/2✓ Branch 2 taken 6607 times.
✗ Branch 3 not taken.
|
6607 | const auto& sfrbx = std::get<ubx::UbxRxmSfrbx>(ubloxObs->data); |
| 287 | |||
| 288 |
1/2✓ Branch 1 taken 6607 times.
✗ Branch 2 not taken.
|
6607 | SatelliteSystem satSys = ubx::getSatSys(sfrbx.gnssId); |
| 289 | 6607 | SatId satId(satSys, sfrbx.svId); | |
| 290 | LOG_DATA("{}: [{}][{}] Converting message", nameId(), ubloxObs->insTime.toYMDHMS(GPST), satId); | ||
| 291 | |||
| 292 |
2/9✓ Branch 1 taken 2396 times.
✓ Branch 2 taken 4211 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
6607 | switch (SatelliteSystem_(satSys)) |
| 293 | { | ||
| 294 | 2396 | case GPS: | |
| 295 |
1/2✓ Branch 2 taken 2396 times.
✗ Branch 3 not taken.
|
2396 | decryptGPS(satId, sfrbx, ubloxObs->insTime); |
| 296 | 2396 | break; | |
| 297 | 4211 | case GAL: | |
| 298 |
1/2✓ Branch 2 taken 4211 times.
✗ Branch 3 not taken.
|
4211 | decryptGalileo(satId, sfrbx, ubloxObs->insTime); |
| 299 | 4211 | break; | |
| 300 | ✗ | case GLO: | |
| 301 | ✗ | decryptGLONASS(satId, sfrbx, ubloxObs->insTime); | |
| 302 | ✗ | break; | |
| 303 | ✗ | case BDS: | |
| 304 | ✗ | decryptBeiDou(satId, sfrbx, ubloxObs->insTime); | |
| 305 | ✗ | break; | |
| 306 | ✗ | case QZSS: | |
| 307 | ✗ | decryptQZSS(satId, sfrbx, ubloxObs->insTime); | |
| 308 | ✗ | break; | |
| 309 | ✗ | case IRNSS: | |
| 310 | ✗ | decryptIRNSS(satId, sfrbx, ubloxObs->insTime); | |
| 311 | ✗ | break; | |
| 312 | ✗ | case SBAS: | |
| 313 | ✗ | decryptSBAS(satId, sfrbx, ubloxObs->insTime); | |
| 314 | ✗ | break; | |
| 315 | ✗ | case SatSys_None: | |
| 316 | ✗ | LOG_CRITICAL("{}: Satellite system cannot be none.", nameId()); | |
| 317 | break; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | 8207 | if (_postProcessingLock.has_value() | |
| 323 |
3/6✓ Branch 1 taken 8207 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8207 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8207 times.
✗ Branch 7 not taken.
|
8207 | && inputPins.at(INPUT_PORT_INDEX_UBLOX_OBS).isPinLinked() |
| 324 |
5/10✓ Branch 0 taken 8207 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8207 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8207 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 8207 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8207 times.
|
16414 | && inputPins.at(INPUT_PORT_INDEX_UBLOX_OBS).link.getConnectedPin()->noMoreDataAvailable) |
| 325 | { | ||
| 326 | LOG_TRACE("{}: Post-processing lock cleared as all data read.", nameId()); | ||
| 327 | ✗ | _postProcessingLock.reset(); | |
| 328 | } | ||
| 329 | 8207 | } | |
| 330 | |||
| 331 | 2396 | void NAV::UbloxGnssOrbitCollector::decryptGPS(const SatId& satId, const ubx::UbxRxmSfrbx& sfrbx, const InsTime& insTime) | |
| 332 | { | ||
| 333 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.2, p. 30f | ||
| 334 | // > For GPS L1C/A signals, there is a fairly straightforward mapping between the reported subframe | ||
| 335 | // > and the structure of subframe and words described in the GPS ICD. Each subframe comprises ten | ||
| 336 | // > data words, which are reported in the same order they are received. | ||
| 337 | // > | ||
| 338 | // > MSB LSB | ||
| 339 | // > 1 to 10: Pad (2 bits) Data (24 bits) Parity (6 bits) | ||
| 340 | // > | ||
| 341 | // > Note that as the GPS data words only comprise 30 bits, the 2 most significant bits in each word | ||
| 342 | // > reported by UBX-RXM-SFRBX are padding and should be ignored. | ||
| 343 | |||
| 344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2396 times.
|
2396 | if (sfrbx.numWords != 10) |
| 345 | { | ||
| 346 | ✗ | LOG_ERROR("{}: [{}] Received {} instead of 10 words", nameId(), satId, sfrbx.numWords); | |
| 347 | 1169 | return; | |
| 348 | } | ||
| 349 | |||
| 350 | 2396 | size_t w = 0; // Word counter | |
| 351 | |||
| 352 | // Telemetry Word | ||
| 353 | // 30 bits long, occurs every 6 seconds ┌ Integrity Status Flag | ||
| 354 | // Preamble │ ┌ Reserved | ||
| 355 | // 1 0 0 0 1 0 1 1 MSB TLM Message LSB │ │ Parity | ||
| 356 | // ┌──────┴──────┐ ┌───────────────┴──────────────────────┐ │ │ ┌──────┴────────┐ | ||
| 357 | // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ||
| 358 | LOG_DATA("{}: [{}] tlm: {} {}", nameId(), satId, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 359 | 2396 | constexpr uint8_t TLM_PREAMBLE = 0b10001011; | |
| 360 |
3/4✓ Branch 1 taken 2396 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1169 times.
✓ Branch 4 taken 1227 times.
|
2396 | if (static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111) != TLM_PREAMBLE) // Preamble found after the 2 padding bits |
| 361 | { | ||
| 362 | LOG_DATA("{}: [{}] Wrong telemetry word preamble. Ignoring SFRBX message.", nameId(), satId); | ||
| 363 | 1169 | return; | |
| 364 | } | ||
| 365 | |||
| 366 | // Handover Word (HOW) | ||
| 367 | // 30 bits long, occurs every 6 seconds anti-spoof (A-S) flag | ||
| 368 | // alert flag │ | ||
| 369 | // MSB TOW-Count Message LSB │ │ Subframe ID Parity | ||
| 370 | // ┌──────────────────┴────────────────────┐ │ │ ┌───┴──┐ ┌──────┴────────┐ | ||
| 371 | // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ||
| 372 | 1227 | w++; | |
| 373 | LOG_DATA("{}: [{}] how: {} {}", nameId(), satId, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 374 |
1/2✓ Branch 1 taken 1227 times.
✗ Branch 2 not taken.
|
1227 | auto subFrameId = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 8) & 0b111); |
| 375 | LOG_DATA("{}: [{}] subFrameId: {}", nameId(), satId, subFrameId); | ||
| 376 | |||
| 377 |
2/4✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1227 times.
|
1227 | if (subFrameId == 0 || subFrameId > 5) |
| 378 | { | ||
| 379 | ✗ | LOG_ERROR("{}: [{}] The subFrameId has to be in the range [1..=5] but it is {}", nameId(), satId, subFrameId); | |
| 380 | ✗ | return; | |
| 381 | } | ||
| 382 | |||
| 383 |
1/2✓ Branch 2 taken 1227 times.
✗ Branch 3 not taken.
|
1227 | auto gpsWeekToW = insTime.toGPSweekTow(GPST); |
| 384 | |||
| 385 | 736 | auto finishSubFrame = [&]<size_t N>(const std::shared_ptr<SatNavData>& ephemeris, size_t subFrameId, std::bitset<N>& subframesFound) { | |
| 386 |
2/4✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 736 times.
✗ Branch 3 not taken.
|
736 | if (1 <= subFrameId && subFrameId <= 3) |
| 387 | { | ||
| 388 | 736 | subframesFound.set(subFrameId - 1); | |
| 389 | |||
| 390 | LOG_DATA("{}: [{}] subframesFound: {}", nameId(), satId, subframesFound); | ||
| 391 |
2/2✓ Branch 1 taken 698 times.
✓ Branch 2 taken 38 times.
|
736 | if (subframesFound.count() == 3) |
| 392 | { | ||
| 393 | LOG_DATA("{}: [{}] [{}] All subframes found. Updating gnnsNavInfo", nameId(), satId, ephemeris->refTime.toYMDHMS(GPST)); | ||
| 394 |
3/4✓ Branch 2 taken 698 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 687 times.
|
698 | if (!_gnssNavInfo.searchNavigationData(satId, ephemeris->refTime)) |
| 395 | { | ||
| 396 |
4/8✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 14 not taken.
|
11 | LOG_DEBUG("{}: Adding new ephemeris data [{}] [{}]", nameId(), satId, ephemeris->refTime.toYMDHMS(GPST)); |
| 397 | } | ||
| 398 |
1/2✓ Branch 1 taken 698 times.
✗ Branch 2 not taken.
|
698 | std::unique_lock guard(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex, std::defer_lock); |
| 399 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 698 times.
|
698 | if (!_postProcessingLock.has_value()) |
| 400 | { | ||
| 401 | ✗ | guard.lock(); | |
| 402 | } | ||
| 403 | 698 | _gnssNavInfo.satelliteSystems |= satId.satSys; | |
| 404 |
1/2✓ Branch 1 taken 698 times.
✗ Branch 2 not taken.
|
698 | _gnssNavInfo.addSatelliteNavData(satId, ephemeris); |
| 405 | 698 | } | |
| 406 | } | ||
| 407 | 736 | }; | |
| 408 | |||
| 409 |
2/2✓ Branch 0 taken 245 times.
✓ Branch 1 taken 982 times.
|
1227 | if (subFrameId == 1) // Third through tenth words of subframe 1 shall each contain 6 parity bits as their LSBs |
| 410 | { | ||
| 411 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 1 of 11), p. 79 | ||
| 412 | // IS-GPS-200M: 20.3.3.3 Subframe 1, p. 91ff | ||
| 413 | // IS-GPS-200M: Table 20-I. Subframe 1 Parameters, p. 96 | ||
| 414 | |||
| 415 | // T_GD, af2, af1, af0 shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 416 | |||
| 417 | 245 | w++; | |
| 418 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 3 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 419 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | [[maybe_unused]] auto WN = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 20) & 0b1111111111); // 10 BITS - Transmission Week Number |
| 420 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto L2ChannelCodes = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 18) & 0b11); // 2 BITS |
| 421 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto uraIndex = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111); // 4 BITS |
| 422 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto svHealth = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 8) & 0b111111); // 6 BITS |
| 423 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto IODC = static_cast<uint16_t>(((sfrbx.dwrd.at(w) >> 6) & 0b11) << 8); // 2 MSBs - 10 BITS TOTAL |
| 424 | LOG_DATA("{}: [{}] WN {}, L2ChannelCodes {}, uraIndex {}, svHealth {}, IODC {}", nameId(), satId, WN, L2ChannelCodes, uraIndex, svHealth, std::bitset<10>(IODC)); | ||
| 425 | |||
| 426 | 245 | w++; | |
| 427 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 428 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto L2DataFlagPCode = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 29) & 0b1); // 1 BIT |
| 429 | LOG_DATA("{}: [{}] L2DataFlagPCode {}", nameId(), satId, L2DataFlagPCode); | ||
| 430 | |||
| 431 | 245 | w++; | |
| 432 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 433 | |||
| 434 | 245 | w++; | |
| 435 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 436 | |||
| 437 | 245 | w++; | |
| 438 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 439 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto T_GD = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 6) & 0b11111111); |
| 440 | LOG_DATA("{}: [{}] T_GD {}", nameId(), satId, T_GD); | ||
| 441 | |||
| 442 | 245 | w++; | |
| 443 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 444 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | IODC |= static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 LSBs - 10 BITS TOTAL |
| 445 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto toc = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 6) & 0b1111111111111111); // 16 LSBs |
| 446 | LOG_DATA("{}: [{}] IODC {} ({}), toc {}", nameId(), satId, IODC, std::bitset<10>(IODC), toc); | ||
| 447 | |||
| 448 | 245 | w++; | |
| 449 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 450 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto af2 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 BITS |
| 451 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto af1 = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 6) & 0b1111111111111111); // 16 BITS |
| 452 | LOG_DATA("{}: [{}] af2 {}, af1 {}", nameId(), satId, af2, af1); | ||
| 453 | |||
| 454 | 245 | w++; | |
| 455 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 456 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto af0 = math::interpretAs<int32_t, 22>(sfrbx.dwrd.at(w) >> 8); // 22 BITS |
| 457 | LOG_DATA("{}: [{}] af0 {}", nameId(), satId, af0); | ||
| 458 | |||
| 459 |
1/2✓ Branch 3 taken 245 times.
✗ Branch 4 not taken.
|
245 | InsTime insTimeToc(gpsWeekToW.gpsCycle, gpsWeekToW.gpsWeek, toc * std::pow(2, 4), GPST); |
| 460 | |||
| 461 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto& ephemerisBuilder = getEphemerisBuilder(satId, insTimeToc); |
| 462 | 245 | auto ephemeris = std::dynamic_pointer_cast<GPSEphemeris>(ephemerisBuilder.navData); | |
| 463 | 245 | ephemeris->toc = insTimeToc; | |
| 464 | |||
| 465 | 245 | ephemeris->L2ChannelCodes = L2ChannelCodes; | |
| 466 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | ephemeris->svAccuracy = gpsUraIdx2Val(uraIndex); |
| 467 | 245 | ephemeris->svHealth = svHealth; | |
| 468 | 245 | ephemeris->IODC = IODC; | |
| 469 | 245 | ephemeris->L2DataFlagPCode = L2DataFlagPCode; | |
| 470 | 245 | ephemeris->T_GD = T_GD * std::pow(2, -31); | |
| 471 | 245 | ephemeris->refTime = ephemeris->toc; | |
| 472 | 245 | ephemeris->a = { | |
| 473 | 245 | af0 * std::pow(2, -31), | |
| 474 | 245 | af1 * std::pow(2, -43), | |
| 475 | 245 | af2 * std::pow(2, -55), | |
| 476 | }; | ||
| 477 | LOG_DATA("{}: [{}] svAccuracy [{} m], svHealth [{}], IODC [{}], tgd [{:.3e} s]", nameId(), satId, | ||
| 478 | ephemeris->svAccuracy, ephemeris->svHealth, ephemeris->IODC, ephemeris->T_GD); | ||
| 479 | LOG_DATA("{}: [{}] toc [{}], a0 [{:.3e} s], a1 [{:.3e} s/s], a2 [{:.3e} s/s^2]", nameId(), satId, | ||
| 480 | ephemeris->toc.toYMDHMS(GPST), ephemeris->a[0], ephemeris->a[1], ephemeris->a[2]); | ||
| 481 | |||
| 482 |
1/2✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
|
245 | finishSubFrame(ephemeris, subFrameId, ephemerisBuilder.subframes); |
| 483 | 245 | } | |
| 484 |
2/2✓ Branch 0 taken 246 times.
✓ Branch 1 taken 736 times.
|
982 | else if (subFrameId == 2) // The third through tenth words of subframes 2 and 3 shall each contain six parity bits as their LSBs |
| 485 | { | ||
| 486 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 2 of 11), p. 80 | ||
| 487 | // IS-GPS-200M: 20.3.3.4 Subframes 2 and 3, p. 101ff | ||
| 488 | // IS-GPS-200M: Table 20-III. Ephemeris Parameters, p. 105 | ||
| 489 | |||
| 490 | // Crs, delta_n, M_0, Cuc, Cus shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 491 | |||
| 492 | 246 | w++; | |
| 493 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 3 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 494 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto IODE = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 BITS |
| 495 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto Crs = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 6) & 0b1111111111111111); // 16 BITS |
| 496 | LOG_DATA("{}: [{}] IODE {}, Crs {}", nameId(), satId, IODE, Crs); | ||
| 497 | |||
| 498 | 246 | w++; | |
| 499 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 500 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto delta_n = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 501 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto M_0 = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24); // 8 MSBs - 32 BITS TOTAL |
| 502 | LOG_DATA("{}: [{}] delta_n {}, M_0 {}", nameId(), satId, delta_n, std::bitset<32>(static_cast<uint32_t>(M_0))); | ||
| 503 | |||
| 504 | 246 | w++; | |
| 505 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 506 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | M_0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111); // 24 LSBs - 32 BITS TOTAL |
| 507 | LOG_DATA("{}: [{}] M_0 {} ({})", nameId(), satId, M_0, std::bitset<32>(static_cast<uint32_t>(M_0))); | ||
| 508 | |||
| 509 | 246 | w++; | |
| 510 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 511 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto Cuc = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 512 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | uint32_t e = ((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24; // 8 MSBs - 32 BITS TOTAL |
| 513 | LOG_DATA("{}: [{}] Cuc {}, e {}", nameId(), satId, Cuc, std::bitset<32>(e)); | ||
| 514 | |||
| 515 | 246 | w++; | |
| 516 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 517 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | e |= (sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111; // 24 LSBs - 32 BITS TOTAL |
| 518 | LOG_DATA("{}: [{}] e {} ({})", nameId(), satId, e, std::bitset<32>(e)); | ||
| 519 | |||
| 520 | 246 | w++; | |
| 521 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 522 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto Cus = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 523 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | uint32_t sqrt_A = ((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24; // 8 MSBs - 32 BITS TOTAL |
| 524 | LOG_DATA("{}: [{}] Cus {}, sqrt_A {}", nameId(), satId, Cus, std::bitset<32>(sqrt_A)); | ||
| 525 | |||
| 526 | 246 | w++; | |
| 527 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 528 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | sqrt_A |= (sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111; // 24 LSBs - 32 BITS TOTAL |
| 529 | LOG_DATA("{}: [{}] sqrt_A {} ({})", nameId(), satId, sqrt_A, std::bitset<32>(sqrt_A)); | ||
| 530 | |||
| 531 | 246 | w++; | |
| 532 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 533 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto toe = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 534 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto fitInterval = static_cast<bool>((sfrbx.dwrd.at(w) >> 13) & 0b1); // 1 BIT |
| 535 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | [[maybe_unused]] auto AODO = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 8) & 0b11111); // 5 BITS |
| 536 | LOG_DATA("{}: [{}] toe {}, fitInterval {}, AODO {}", nameId(), satId, toe, fitInterval, AODO); | ||
| 537 | |||
| 538 |
1/2✓ Branch 3 taken 246 times.
✗ Branch 4 not taken.
|
246 | InsTime insTimeToe(gpsWeekToW.gpsCycle, gpsWeekToW.gpsWeek, toe * std::pow(2, 4), GPST); |
| 539 | |||
| 540 |
1/2✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
|
246 | auto& ephemerisBuilder = getEphemerisBuilder(satId, insTimeToe); |
| 541 | 246 | auto ephemeris = std::dynamic_pointer_cast<GPSEphemeris>(ephemerisBuilder.navData); | |
| 542 | 246 | ephemeris->toe = insTimeToe; | |
| 543 | |||
| 544 | 246 | ephemeris->IODE = IODE; | |
| 545 | 246 | ephemeris->Crs = Crs * std::pow(2, -5); | |
| 546 | 246 | ephemeris->delta_n = semicircles2rad(delta_n * std::pow(2, -43)); | |
| 547 | 246 | ephemeris->M_0 = semicircles2rad(M_0 * std::pow(2, -31)); | |
| 548 | 246 | ephemeris->Cuc = Cuc * std::pow(2, -29); | |
| 549 | 246 | ephemeris->e = e * std::pow(2, -33); | |
| 550 | 246 | ephemeris->Cus = Cus * std::pow(2, -29); | |
| 551 | 246 | ephemeris->sqrt_A = sqrt_A * std::pow(2, -19); | |
| 552 |
1/2✓ Branch 3 taken 246 times.
✗ Branch 4 not taken.
|
246 | ephemeris->toe = InsTime(gpsWeekToW.gpsCycle, gpsWeekToW.gpsWeek, toe * std::pow(2, 4), GPST); |
| 553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
|
246 | ephemeris->fitInterval = fitInterval ? 8.0 : 4.0; |
| 554 | // AODO | ||
| 555 | |||
| 556 | LOG_DATA("{}: [{}] IODE [{}], Crs [{:.3e} m], delta_n [{:.3e} rad/s], M_0 [{:.3e} rad], Cuc [{:.3e} rad]", nameId(), satId, | ||
| 557 | ephemeris->IODE, ephemeris->Crs, ephemeris->delta_n, ephemeris->M_0, ephemeris->Cuc); | ||
| 558 | LOG_DATA("{}: [{}] e [{:.3e}], Cus [{:.3e} rad], sqrt_A [{:.3e} m^(1/2)], toe [{}], fitInterval [{:.1f}]", nameId(), satId, | ||
| 559 | ephemeris->e, ephemeris->Cus, ephemeris->sqrt_A, ephemeris->toe.toGPSweekTow(GPST), ephemeris->fitInterval); | ||
| 560 | |||
| 561 |
1/2✓ Branch 2 taken 246 times.
✗ Branch 3 not taken.
|
246 | finishSubFrame(ephemeris, subFrameId, ephemerisBuilder.subframes); |
| 562 | 246 | } | |
| 563 |
2/2✓ Branch 0 taken 245 times.
✓ Branch 1 taken 491 times.
|
736 | else if (subFrameId == 3) // The third through tenth words of subframes 2 and 3 shall each contain six parity bits as their LSBs |
| 564 | { | ||
| 565 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 3 of 11), p. 81 | ||
| 566 | // IS-GPS-200M: 20.3.3.4 Subframes 2 and 3, p. 101ff | ||
| 567 | // IS-GPS-200M: Table 20-III. Ephemeris Parameters, p. 105 | ||
| 568 | |||
| 569 | // Cic, Omega_0, Cis, i_0, Crc, omega, Omega_dot, IDOT shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 570 | |||
| 571 | 245 | w++; | |
| 572 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 3 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 573 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto Cic = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 574 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto Omega_0 = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24); // 8 MSBs - 32 BITS TOTAL |
| 575 | LOG_DATA("{}: [{}] Cic {}, Omega_0 {}", nameId(), satId, Cic, std::bitset<32>(static_cast<uint32_t>(Omega_0))); | ||
| 576 | |||
| 577 | 245 | w++; | |
| 578 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 579 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | Omega_0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111); // 24 LSBs - 32 BITS TOTAL |
| 580 | LOG_DATA("{}: [{}] Omega_0 {} ({})", nameId(), satId, Omega_0, std::bitset<32>(static_cast<uint32_t>(Omega_0))); | ||
| 581 | |||
| 582 | 245 | w++; | |
| 583 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 584 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto Cis = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 585 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto i_0 = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24); // 8 MSBs - 32 BITS TOTAL |
| 586 | LOG_DATA("{}: [{}] Cis {}, i_0 {}", nameId(), satId, Cis, std::bitset<32>(static_cast<uint32_t>(i_0))); | ||
| 587 | |||
| 588 | 245 | w++; | |
| 589 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 590 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | i_0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111); // 24 LSBs - 32 BITS TOTAL |
| 591 | LOG_DATA("{}: [{}] i_0 {} ({})", nameId(), satId, i_0, std::bitset<32>(static_cast<uint32_t>(i_0))); | ||
| 592 | |||
| 593 | 245 | w++; | |
| 594 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 595 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto Crc = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111111); // 16 BITS |
| 596 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto omega = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 6) & 0b11111111) << 24); // 8 MSBs - 32 BITS TOTAL |
| 597 | LOG_DATA("{}: [{}] Crc {}, omega {}", nameId(), satId, Crc, std::bitset<32>(static_cast<uint32_t>(omega))); | ||
| 598 | |||
| 599 | 245 | w++; | |
| 600 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 601 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | omega |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111); // 24 LSBs - 32 BITS TOTAL |
| 602 | LOG_DATA("{}: [{}] omega {} ({})", nameId(), satId, omega, std::bitset<32>(static_cast<uint32_t>(omega))); | ||
| 603 | |||
| 604 | 245 | w++; | |
| 605 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 606 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto Omega_dot = math::interpretAs<int32_t, 24>(sfrbx.dwrd.at(w) >> 6); // 24 BITS |
| 607 | LOG_DATA("{}: [{}] Omega_dot {} ({})", nameId(), satId, Omega_dot, std::bitset<32>(static_cast<uint32_t>(Omega_dot))); | ||
| 608 | |||
| 609 | 245 | w++; | |
| 610 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 611 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto IODE = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 BITS |
| 612 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto i_dot = math::interpretAs<int16_t, 14>(sfrbx.dwrd.at(w) >> 8); // 14 BITS |
| 613 | LOG_DATA("{}: [{}] IODE {}, i_dot {} ({})", nameId(), satId, IODE, i_dot, std::bitset<16>(static_cast<uint16_t>(i_dot))); | ||
| 614 | |||
| 615 |
1/2✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
|
245 | auto ephemerisBuilder = getEphemerisBuilder(satId, IODE); |
| 616 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
|
245 | if (!ephemerisBuilder.has_value()) |
| 617 | { | ||
| 618 | LOG_DATA("{}: [{}] Could not find Ephemeris builder for IODE {}", nameId(), satId, IODE); | ||
| 619 | ✗ | return; | |
| 620 | } | ||
| 621 | 245 | auto ephemeris = std::dynamic_pointer_cast<GPSEphemeris>(ephemerisBuilder->get().navData); | |
| 622 | |||
| 623 | 245 | ephemeris->Cic = Cic * std::pow(2, -29); | |
| 624 | 245 | ephemeris->Omega_0 = semicircles2rad(Omega_0 * std::pow(2, -31)); | |
| 625 | 245 | ephemeris->Cis = Cis * std::pow(2, -29); | |
| 626 | 245 | ephemeris->i_0 = semicircles2rad(i_0 * std::pow(2, -31)); | |
| 627 | 245 | ephemeris->Crc = Crc * std::pow(2, -5); | |
| 628 | 245 | ephemeris->omega = semicircles2rad(omega * std::pow(2, -31)); | |
| 629 | 245 | ephemeris->Omega_dot = semicircles2rad(Omega_dot * std::pow(2, -43)); | |
| 630 | 245 | ephemeris->IODE = IODE; | |
| 631 | 245 | ephemeris->i_dot = semicircles2rad(i_dot * std::pow(2, -43)); | |
| 632 | |||
| 633 | LOG_DATA("{}: [{}] Cic [{:.3e} rad], Omega_0 [{:.3e} rad], Cis [{:.3e} rad], i_0 [{:.3e} rad], Crc [{:.3e} m]", nameId(), satId, | ||
| 634 | ephemeris->Cic, ephemeris->Omega_0, ephemeris->Cis, ephemeris->i_0, ephemeris->Crc); | ||
| 635 | LOG_DATA("{}: [{}] omega [{:.3e} rad], Omega_dot [{:.3e} rad/s], IODE [{}], i_dot [{:.3e} rad/s]", nameId(), satId, | ||
| 636 | ephemeris->omega, ephemeris->Omega_dot, ephemeris->IODE, ephemeris->i_dot); | ||
| 637 | |||
| 638 |
1/2✓ Branch 4 taken 245 times.
✗ Branch 5 not taken.
|
245 | finishSubFrame(ephemeris, subFrameId, ephemerisBuilder->get().subframes); |
| 639 | 245 | } | |
| 640 |
2/2✓ Branch 0 taken 237 times.
✓ Branch 1 taken 254 times.
|
491 | else if (subFrameId == 4) // Words three through ten of each page contain six parity bits as their LSBs |
| 641 | { | ||
| 642 | // Page | SV ID | Description | ||
| 643 | // ------------------------ | ------------------------------ | ----------- | ||
| 644 | // 1, 6, 11, 16, 21: | 57 | Reserved | ||
| 645 | // 2, 3, 4, 5, 7, 8, 9, 10: | 25, 26, 27, 28, 29, 30, 31, 32 | almanac data for SV 25 through 32 respectively | ||
| 646 | // 12, 19, 20, 22, 23, 24: | 62, 58, 59, 60, 61, 62 | Reserved | ||
| 647 | // 13: | 52 | NMCT | ||
| 648 | // 14, 15: | 53, 54 | Reserved for system use | ||
| 649 | // 17: | 55 | Special messages | ||
| 650 | // 18: | 56 | Ionospheric and UTC data | ||
| 651 | // 25: | 63 | A-S flags/SV configurations for 32 SVs, plus SV health for SV 25 through 32 | ||
| 652 | // | ||
| 653 | // IS-GPS-200M: Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, p. 114 | ||
| 654 | // IS-GPS-200M: 20.3.3.5 Subframes 4 and 5, p. 112ff | ||
| 655 | |||
| 656 | 237 | w++; | |
| 657 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 3 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 658 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | [[maybe_unused]] auto dataId = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 28) & 0b11); // 2 BITS |
| 659 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto svId = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 22) & 0b111111); // 6 BITS |
| 660 | LOG_DATA("{}: [{}] dataId {}, svId {}", nameId(), satId, dataId, svId); | ||
| 661 | |||
| 662 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 229 times.
|
237 | if (svId == 56) // IS-GPS-200M: Figure 20-1. Data Format (sheet 8 of 11), p. 86 - for page 18 |
| 663 | { | ||
| 664 | // IS-GPS-200M: 20.3.3.5.1.6 Coordinated Universal Time (UTC) Parameters, p. 121 | ||
| 665 | // IS-GPS-200M: Table 20-IX. UTC Parameters, p. 122 | ||
| 666 | |||
| 667 | // IS-GPS-200M: 20.3.3.5.1.7 Ionospheric Data, p. 121 | ||
| 668 | // IS-GPS-200M: Table 20-X. Ionospheric Parameters, p. 123 | ||
| 669 | |||
| 670 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto alpha0 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 14) & 0b11111111); // 8 BITS |
| 671 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto alpha1 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 6) & 0b11111111); // 8 BITS |
| 672 | LOG_DATA("{}: [{}] alpha0 {}, alpha1 {}", nameId(), satId, alpha0, alpha1); | ||
| 673 | |||
| 674 | 8 | w++; | |
| 675 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 676 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto alpha2 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 BITS |
| 677 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto alpha3 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 14) & 0b11111111); // 8 BITS |
| 678 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto beta0 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 6) & 0b11111111); // 8 BITS |
| 679 | LOG_DATA("{}: [{}] alpha2 {}, alpha3 {}, beta0 {}", nameId(), satId, alpha2, alpha3, beta0); | ||
| 680 | |||
| 681 | 8 | w++; | |
| 682 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 683 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto beta1 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 BITS |
| 684 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto beta2 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 14) & 0b11111111); // 8 BITS |
| 685 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto beta3 = static_cast<int8_t>((sfrbx.dwrd.at(w) >> 6) & 0b11111111); // 8 BITS |
| 686 | LOG_DATA("{}: [{}] beta1 {}, beta2 {}, beta3 {}", nameId(), satId, beta1, beta2, beta3); | ||
| 687 | |||
| 688 | 8 | w++; | |
| 689 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 690 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto A1 = math::interpretAs<int32_t, 24>(sfrbx.dwrd.at(w) >> 6); // 24 BITS |
| 691 | LOG_DATA("{}: [{}] A1 {}", nameId(), satId, A1); | ||
| 692 | |||
| 693 | 8 | w++; | |
| 694 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 695 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto A0 = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 6) & 0b111111111111111111111111) << 8); // 24 MSBs - 32 BITS TOTAL |
| 696 | LOG_DATA("{}: [{}] A0 {}", nameId(), satId, std::bitset<32>(static_cast<uint32_t>(A0))); | ||
| 697 | |||
| 698 | 8 | w++; | |
| 699 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 700 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | A0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // 8 LSBs - 32 BITS TOTAL |
| 701 | LOG_DATA("{}: [{}] A0 {} ({})", nameId(), satId, A0, std::bitset<32>(static_cast<uint32_t>(A0))); | ||
| 702 | |||
| 703 | 8 | w++; | |
| 704 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 705 | |||
| 706 | 8 | w++; | |
| 707 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 708 | |||
| 709 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | std::unique_lock guard(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex, std::defer_lock); |
| 710 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (!_postProcessingLock.has_value()) |
| 711 | { | ||
| 712 | ✗ | guard.lock(); | |
| 713 | } | ||
| 714 |
3/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7 times.
|
8 | if (!_gnssNavInfo.ionosphericCorrections.contains(satId.satSys, IonosphericCorrections::Alpha)) |
| 715 | { | ||
| 716 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | if (auto ephemerisBuilder = getLastEphemerisBuilder(satId); |
| 717 | 1 | ephemerisBuilder.has_value()) | |
| 718 | { | ||
| 719 | 1 | auto ephemeris = std::dynamic_pointer_cast<GPSEphemeris>(ephemerisBuilder->get().navData); | |
| 720 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | LOG_DEBUG("{}: [{}] Received Ionospheric and Time system corrections [{}]", nameId(), satId.satSys, ephemeris->refTime.toYMDHMS(GPST)); |
| 721 | 1 | } | |
| 722 | else | ||
| 723 | { | ||
| 724 | ✗ | LOG_DEBUG("{}: [{}] Received Ionospheric and Time system corrections", nameId(), satId.satSys); | |
| 725 | } | ||
| 726 | } | ||
| 727 | |||
| 728 | ✗ | _gnssNavInfo.ionosphericCorrections.insert(satId.satSys, IonosphericCorrections::Alpha, | |
| 729 | { | ||
| 730 | 8 | alpha0 * std::pow(2, -30) /* [s] */, | |
| 731 | 8 | alpha1 * std::pow(2, -27) /* [s/semi-circle] */, | |
| 732 | 8 | alpha2 * std::pow(2, -24) /* [s/semi-circle^2] */, | |
| 733 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | alpha3 * std::pow(2, -24) /* [s/semi-circle^3] */, |
| 734 | }); | ||
| 735 | ✗ | _gnssNavInfo.ionosphericCorrections.insert(satId.satSys, IonosphericCorrections::Beta, | |
| 736 | { | ||
| 737 | 8 | beta0 * std::pow(2, 11) /* [s] */, | |
| 738 | 8 | beta1 * std::pow(2, 14) /* [s/semi-circle] */, | |
| 739 | 8 | beta2 * std::pow(2, 16) /* [s/semi-circle^2] */, | |
| 740 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | beta3 * std::pow(2, 16) /* [s/semi-circle^3] */, |
| 741 | }); | ||
| 742 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
8 | _gnssNavInfo.timeSysCorr[{ satId.satSys.getTimeSystem(), UTC }] = GnssNavInfo::TimeSystemCorrections{ |
| 743 | 8 | .a0 = A0 * std::pow(2, -30), | |
| 744 | 8 | .a1 = A1 * std::pow(2, -50), | |
| 745 | }; | ||
| 746 | 8 | } | |
| 747 | else | ||
| 748 | { | ||
| 749 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 6 of 11), p. 84 - for pages 1, 6, 11, 16 and 21 | ||
| 750 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 7 of 11), p. 85 - for pages 12, 19, 20, 22, 23 and 24 | ||
| 751 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 9 of 11), p. 87 - for page 25 | ||
| 752 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 10 of 11), p. 88 - for page 13 | ||
| 753 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 11 of 11), p. 89 - for pages 14, 15 and 17 | ||
| 754 | |||
| 755 | 229 | w++; | |
| 756 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 757 | 229 | w++; | |
| 758 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 759 | 229 | w++; | |
| 760 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 761 | 229 | w++; | |
| 762 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 763 | 229 | w++; | |
| 764 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 765 | 229 | w++; | |
| 766 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 767 | 229 | w++; | |
| 768 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 769 | } | ||
| 770 | } | ||
| 771 |
1/2✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
|
254 | else if (subFrameId == 5) // Words three through ten of each page contain six parity bits as their LSBs |
| 772 | { | ||
| 773 | // Page description | ||
| 774 | // 1 through 24: almanac data for SV 1 through 24 | ||
| 775 | // 25: SV health data for SV 1 through 24, the almanac reference time, the almanac reference week number | ||
| 776 | // | ||
| 777 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 4 of 11), p. 82 - for page 1 through 24 | ||
| 778 | // IS-GPS-200M: Figure 20-1. Data Format (sheet 5 of 11), p. 83 - for page 25 | ||
| 779 | // IS-GPS-200M: 20.3.3.5 Subframes 4 and 5, p. 112ff | ||
| 780 | |||
| 781 | 254 | w++; | |
| 782 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 3 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 783 | 254 | w++; | |
| 784 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 4 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 785 | 254 | w++; | |
| 786 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 5 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 787 | 254 | w++; | |
| 788 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 6 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 789 | 254 | w++; | |
| 790 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 7 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 791 | 254 | w++; | |
| 792 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 8 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 793 | 254 | w++; | |
| 794 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 9 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 795 | 254 | w++; | |
| 796 | LOG_DATA("{}: [{}] word {:2}: {} {}", nameId(), satId, w + 1 /* 10 */, std::bitset<2>(sfrbx.dwrd.at(w) >> 30), std::bitset<30>(sfrbx.dwrd.at(w))); | ||
| 797 | } | ||
| 798 | } | ||
| 799 | |||
| 800 | 4211 | void NAV::UbloxGnssOrbitCollector::decryptGalileo(const SatId& satId, const ubx::UbxRxmSfrbx& sfrbx, const InsTime& insTime) | |
| 801 | { | ||
| 802 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.5, p. 32f | ||
| 803 | // > The Galileo E1OS and E5b signals both transmit the I/NAV message but in different configurations. | ||
| 804 | // > For Galileo E1OS signals, each reported subframe contains a pair of I/NAV pages as described in | ||
| 805 | // > the Galileo ICD. | ||
| 806 | // > Galileo pages can either be "Nominal" or "Alert" pages. For Nominal pages the eight words are | ||
| 807 | // > arranged as follows: | ||
| 808 | // > | ||
| 809 | // > MSB LSB | ||
| 810 | // > 1: Even/Odd (1 bit) Page type (1 bit) Word type (6 bits) Data (122 - 99) (24 bits) | ||
| 811 | // > 2: Data (98 - 67) (32 bits) | ||
| 812 | // > 3: Data (66 - 35) (32 bits) | ||
| 813 | // > 4: Data (34 - 17) (18 bits) Tail (6 bits) Pad (8 bits) | ||
| 814 | // > 5: Even/Odd (1 bit) Page type (1 bit) Data (16 - 1) (16 bits) Reserved 1 (40 - 27) (14 bits) | ||
| 815 | // > 6: Reserved 2 (26 - 1) (26 bits) SAR (22 - 17) (6 bits) | ||
| 816 | // > 7: SAR (16 - 1) (16 bits) Spare (2 bits) CRC (24 - 11) (14 bits) | ||
| 817 | // > 8: CRC (10 - 1) (10 bits) Reserved 2 (8 bits) Tail (6 bits) Pad (8 bits) | ||
| 818 | // > | ||
| 819 | // > Alert pages are reported in very similar manner, but the page type bits will have value 1 and the | ||
| 820 | // > structure of the eight words will be slightly different (as indicated by the Galileo ICD). | ||
| 821 | |||
| 822 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4211 times.
|
4211 | if (sfrbx.numWords != 8) |
| 823 | { | ||
| 824 | ✗ | LOG_ERROR("{}: [{}] Received {} instead of 8 words", nameId(), satId, sfrbx.numWords); | |
| 825 | 695 | return; | |
| 826 | } | ||
| 827 | |||
| 828 | 4211 | size_t w = 0; // Word counter | |
| 829 | |||
| 830 |
1/2✓ Branch 1 taken 4211 times.
✗ Branch 2 not taken.
|
4211 | auto even = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 31) & 0b1); |
| 831 |
1/2✓ Branch 1 taken 4211 times.
✗ Branch 2 not taken.
|
4211 | auto pageTypeEven = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 30) & 0b1); |
| 832 |
1/2✓ Branch 1 taken 4211 times.
✗ Branch 2 not taken.
|
4211 | auto odd = static_cast<uint8_t>((sfrbx.dwrd.at(4) >> 31) & 0b1); |
| 833 |
1/2✓ Branch 1 taken 4211 times.
✗ Branch 2 not taken.
|
4211 | auto pageTypeOdd = static_cast<uint8_t>((sfrbx.dwrd.at(4) >> 30) & 0b1); |
| 834 |
1/2✓ Branch 1 taken 4211 times.
✗ Branch 2 not taken.
|
4211 | auto wordType = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 24) & 0b111111); |
| 835 | LOG_DATA("{}: [{}] wordType: {:2}, even {} ({} pageType), odd {} ({} pageType)", nameId(), satId, wordType, even, pageTypeEven, odd, pageTypeOdd); | ||
| 836 | |||
| 837 |
2/4✓ Branch 0 taken 4211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4211 times.
✗ Branch 3 not taken.
|
4211 | if (even != 0 || pageTypeEven == 1 |
| 838 |
4/4✓ Branch 0 taken 3814 times.
✓ Branch 1 taken 397 times.
✓ Branch 2 taken 237 times.
✓ Branch 3 taken 3577 times.
|
4211 | || odd != 1 || pageTypeOdd == 1) |
| 839 | { | ||
| 840 | LOG_DATA("{}: [{}] Ignoring message, because one of the page types is alert page", nameId(), satId); | ||
| 841 | 634 | return; | |
| 842 | } | ||
| 843 | |||
| 844 |
1/2✓ Branch 2 taken 3577 times.
✗ Branch 3 not taken.
|
3577 | auto gpsWeekToW = insTime.toGPSweekTow(GST); |
| 845 | |||
| 846 | 1103 | auto finishWord = [&]<size_t N>(const std::shared_ptr<SatNavData>& ephemeris, size_t wordType, std::bitset<N>& subframesFound) { | |
| 847 |
2/4✓ Branch 0 taken 1103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1103 times.
✗ Branch 3 not taken.
|
1103 | if (1 <= wordType && wordType <= 5) |
| 848 | { | ||
| 849 | 1103 | subframesFound.set(wordType - 1); | |
| 850 | |||
| 851 | LOG_DATA("{}: [{}] subframesFound: {}", nameId(), satId, subframesFound); | ||
| 852 |
2/2✓ Branch 1 taken 989 times.
✓ Branch 2 taken 114 times.
|
1103 | if (subframesFound.count() == 5) |
| 853 | { | ||
| 854 | LOG_DATA("{}: [{}] [{}] All words found. Updating gnnsNavInfo", nameId(), satId, ephemeris->refTime.toYMDHMS(GPST)); | ||
| 855 |
3/4✓ Branch 2 taken 989 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 978 times.
|
989 | if (!_gnssNavInfo.searchNavigationData(satId, ephemeris->refTime)) |
| 856 | { | ||
| 857 |
4/8✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 14 not taken.
|
11 | LOG_DEBUG("{}: Adding new ephemeris data [{}] [{}]", nameId(), satId, ephemeris->refTime.toYMDHMS(GPST)); |
| 858 | } | ||
| 859 |
1/2✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
|
989 | std::unique_lock guard(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex, std::defer_lock); |
| 860 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 989 times.
|
989 | if (!_postProcessingLock.has_value()) |
| 861 | { | ||
| 862 | ✗ | guard.lock(); | |
| 863 | } | ||
| 864 | 989 | _gnssNavInfo.satelliteSystems |= satId.satSys; | |
| 865 |
1/2✓ Branch 1 taken 989 times.
✗ Branch 2 not taken.
|
989 | _gnssNavInfo.addSatelliteNavData(satId, ephemeris); |
| 866 | 989 | } | |
| 867 | } | ||
| 868 | 1103 | }; | |
| 869 | |||
| 870 |
2/2✓ Branch 0 taken 227 times.
✓ Branch 1 taken 3350 times.
|
3577 | if (wordType == 1) // Ephemeris (1/4) |
| 871 | { | ||
| 872 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 40 Bits Allocation for I/NAV Word Type 1, p. 37 | ||
| 873 | // | ||
| 874 | // Even/Odd PageType WordType IODnav toe M_0 e sqrt_A Tail Pad Even/Odd PageType sqrt_A Reserved Reserved 1 | ||
| 875 | // 1 1 6 10 14 32 32 18 6 8 1 1 14 2 14 | ||
| 876 | // └───────────────────┬───────────────────┘ │ │ └───────┬───────┘ └───────────────────────┬──────────────────────┘ | ||
| 877 | // Ublox 1 2 3 4 5 | ||
| 878 | |||
| 879 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.1, Table 60 Ephemeris Parameters, p. 43f | ||
| 880 | // > M_0 shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 881 | |||
| 882 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 883 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | auto IODnav = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111); |
| 884 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | auto toe = static_cast<uint16_t>(sfrbx.dwrd.at(w) & 0b11111111111111); |
| 885 | LOG_DATA("{}: [{}] IODnav {}, toe {}", nameId(), satId, IODnav, toe); | ||
| 886 | |||
| 887 | 227 | w++; | |
| 888 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 889 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | auto M_0 = static_cast<int32_t>(sfrbx.dwrd.at(w)); |
| 890 | LOG_DATA("{}: [{}] M_0 {}", nameId(), satId, M_0); | ||
| 891 | |||
| 892 | 227 | w++; | |
| 893 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 894 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | uint32_t e = sfrbx.dwrd.at(w); |
| 895 | LOG_DATA("{}: [{}] e {}", nameId(), satId, e); | ||
| 896 | |||
| 897 | 227 | w++; | |
| 898 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 899 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | uint32_t sqrt_A = ((sfrbx.dwrd.at(w) >> 14) & 0b111111111111111111) << 14; |
| 900 | LOG_DATA("{}: [{}] sqrt_A {}", nameId(), satId, std::bitset<32>(sqrt_A)); | ||
| 901 | |||
| 902 | 227 | w++; | |
| 903 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 904 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | sqrt_A |= (sfrbx.dwrd.at(w) >> 16) & 0b11111111111111; |
| 905 | LOG_DATA("{}: [{}] sqrt_A {} ({})", nameId(), satId, sqrt_A, std::bitset<32>(sqrt_A)); | ||
| 906 | |||
| 907 |
1/2✓ Branch 2 taken 227 times.
✗ Branch 3 not taken.
|
227 | InsTime insTimeToe(gpsWeekToW.gpsCycle, gpsWeekToW.gpsWeek, toe * 60.0, GST); |
| 908 | |||
| 909 |
1/2✓ Branch 1 taken 227 times.
✗ Branch 2 not taken.
|
227 | auto& ephemerisBuilder = getEphemerisBuilder(satId, insTimeToe, IODnav); |
| 910 | 227 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder.navData); | |
| 911 | 227 | ephemeris->toe = insTimeToe; | |
| 912 | |||
| 913 | 227 | ephemeris->IODnav = IODnav; | |
| 914 | 227 | ephemeris->M_0 = semicircles2rad(M_0 * std::pow(2.0, -31)); | |
| 915 | 227 | ephemeris->e = e * std::pow(2.0, -33); | |
| 916 | 227 | ephemeris->sqrt_A = sqrt_A * std::pow(2.0, -19); | |
| 917 | |||
| 918 | LOG_DATA("{}: [{}] IODnav [{}], toe [{}], M_0 [{:.3e} rad], e [{:.3e}], sqrt_A [{:.3e} m^(1/2)]", nameId(), satId, | ||
| 919 | ephemeris->IODnav, ephemeris->toe.toYMDHMS(GPST), ephemeris->M_0, ephemeris->e, ephemeris->sqrt_A); | ||
| 920 | |||
| 921 |
1/2✓ Branch 2 taken 227 times.
✗ Branch 3 not taken.
|
227 | finishWord(ephemeris, wordType, ephemerisBuilder.subframes); |
| 922 | 227 | } | |
| 923 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 3114 times.
|
3350 | else if (wordType == 2) // Ephemeris (2/4) |
| 924 | { | ||
| 925 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 41 Bits Allocation for I/NAV Word Type 2, p. 37 | ||
| 926 | // | ||
| 927 | // Even/Odd PageType WordType IODnav Omega_0 Omega_0 i_0 i_0 omega omega Tail Pad Even/Odd PageType i_dot Reserved Reserved 1 | ||
| 928 | // 1 1 6 10 14 18 14 18 14 18 6 8 1 1 14 2 14 | ||
| 929 | // └──────────────────────┬────────────────────┘ └────┬─────┘ └────┬───┘ └───────┬────────┘ └──────────────────────┬──────────────────────┘ | ||
| 930 | // Ublox 1 2 3 4 5 | ||
| 931 | |||
| 932 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.1, Table 60 Ephemeris Parameters, p. 43f | ||
| 933 | // > Omega_0, i_0, omega, i_dot shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 934 | |||
| 935 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 936 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto IODnav = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111); |
| 937 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto Omega_0 = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b11111111111111) << 18); |
| 938 | LOG_DATA("{}: [{}] IODnav {}, Omega_0 {}", nameId(), satId, IODnav, std::bitset<32>(static_cast<uint32_t>(Omega_0))); | ||
| 939 | |||
| 940 | 236 | w++; | |
| 941 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 942 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | Omega_0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 14) & 0b111111111111111111); |
| 943 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto i_0 = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b11111111111111) << 18); |
| 944 | LOG_DATA("{}: [{}] Omega_0 {} ({}), i_0 {}", nameId(), satId, Omega_0, std::bitset<32>(static_cast<uint32_t>(Omega_0)), std::bitset<32>(static_cast<uint32_t>(i_0))); | ||
| 945 | |||
| 946 | 236 | w++; | |
| 947 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 948 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | i_0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 14) & 0b111111111111111111); |
| 949 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto omega = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b11111111111111) << 18); |
| 950 | LOG_DATA("{}: [{}] i_0 {} ({}), omega {}", nameId(), satId, i_0, std::bitset<32>(static_cast<uint32_t>(i_0)), std::bitset<32>(static_cast<uint32_t>(omega))); | ||
| 951 | |||
| 952 | 236 | w++; | |
| 953 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 954 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | omega |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 14) & 0b111111111111111111); |
| 955 | LOG_DATA("{}: [{}] omega {} ({})", nameId(), satId, omega, std::bitset<32>(static_cast<uint32_t>(omega))); | ||
| 956 | |||
| 957 | 236 | w++; | |
| 958 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 959 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto i_dot = math::interpretAs<int16_t, 14>(sfrbx.dwrd.at(w) >> 16); |
| 960 | LOG_DATA("{}: [{}] i_dot {} ({})", nameId(), satId, i_dot, std::bitset<16>(static_cast<uint16_t>(i_dot))); | ||
| 961 | |||
| 962 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto ephemerisBuilder = getEphemerisBuilder(satId, IODnav); |
| 963 |
2/2✓ Branch 1 taken 27 times.
✓ Branch 2 taken 209 times.
|
236 | if (!ephemerisBuilder.has_value()) |
| 964 | { | ||
| 965 | LOG_DATA("{}: [{}] Could not find Ephemeris builder for IODnav {}", nameId(), satId, IODnav); | ||
| 966 | 27 | return; | |
| 967 | } | ||
| 968 | 209 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder->get().navData); | |
| 969 | |||
| 970 | 209 | ephemeris->Omega_0 = semicircles2rad(Omega_0 * std::pow(2.0, -31)); | |
| 971 | 209 | ephemeris->i_0 = semicircles2rad(i_0 * std::pow(2.0, -31)); | |
| 972 | 209 | ephemeris->omega = semicircles2rad(omega * std::pow(2.0, -31)); | |
| 973 | 209 | ephemeris->i_dot = semicircles2rad(i_dot * std::pow(2.0, -43)); | |
| 974 | |||
| 975 | LOG_DATA("{}: [{}] IODnav [{}], Omega_0 [{} rad], i_0 [{:.3e} rad], omega [{:.3e} rad], i_dot [{:.3e} rad/s]", nameId(), satId, | ||
| 976 | ephemeris->IODnav, ephemeris->Omega_0, ephemeris->i_0, ephemeris->omega, ephemeris->i_dot); | ||
| 977 | |||
| 978 |
1/2✓ Branch 4 taken 209 times.
✗ Branch 5 not taken.
|
209 | finishWord(ephemeris, wordType, ephemerisBuilder->get().subframes); |
| 979 | 209 | } | |
| 980 |
2/2✓ Branch 0 taken 228 times.
✓ Branch 1 taken 2886 times.
|
3114 | else if (wordType == 3) // Ephemeris (3/4) and SISA |
| 981 | { | ||
| 982 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 42 Bits Allocation for I/NAV Word Type 3, p. 38 | ||
| 983 | // | ||
| 984 | // Even/Odd PageType WordType IODnav Omega_dot Omega_dot delta_n Cuc Cuc Cus Crc Crc Crs Tail Pad Even/Odd PageType Crs SISA(E1,E5b) Reserved 1 | ||
| 985 | // 1 1 6 10 14 10 16 6 10 16 6 10 8 6 8 1 1 8 8 14 | ||
| 986 | // └───────────────────────┬─────────────────────┘ └──────────┬──────────┘ └─────┬─────┘ └────────┬────────┘ └───────────────────────┬───────────────────────┘ | ||
| 987 | // Ublox 1 2 3 4 5 | ||
| 988 | |||
| 989 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.1, Table 60 Ephemeris Parameters, p. 43f | ||
| 990 | // > Omega_dot, delta_n, Cuc, Cus, Crc, Crs shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 991 | |||
| 992 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 993 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto IODnav = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111); |
| 994 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto Omega_dot = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b11111111111111) << 10); |
| 995 | LOG_DATA("{}: [{}] IODnav {}, Omega_dot {}", nameId(), satId, IODnav, std::bitset<32>(static_cast<uint32_t>(Omega_dot))); | ||
| 996 | |||
| 997 | 228 | w++; | |
| 998 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 999 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | Omega_dot |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 22) & 0b1111111111); |
| 1000 | 228 | Omega_dot = math::interpretAs<int32_t, 24>(Omega_dot); | |
| 1001 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto delta_n = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 6) & 0b1111111111111111); |
| 1002 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto Cuc = static_cast<int16_t>((sfrbx.dwrd.at(w) & 0b111111) << 10); |
| 1003 | LOG_DATA("{}: [{}] Omega_dot {} ({}), delta_n {}, Cuc {}", nameId(), satId, | ||
| 1004 | Omega_dot, std::bitset<32>(static_cast<uint32_t>(Omega_dot)), delta_n, std::bitset<16>(static_cast<uint16_t>(Cuc))); | ||
| 1005 | |||
| 1006 | 228 | w++; | |
| 1007 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1008 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | Cuc |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 22) & 0b1111111111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1009 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto Cus = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 6) & 0b1111111111111111); |
| 1010 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto Crc = static_cast<int16_t>((sfrbx.dwrd.at(w) & 0b111111) << 10); |
| 1011 | LOG_DATA("{}: [{}] Cuc {} ({}), Cus {}, Crc {}", nameId(), satId, Cuc, std::bitset<16>(static_cast<uint16_t>(Cuc)), Cus, std::bitset<16>(static_cast<uint16_t>(Crc))); | ||
| 1012 | |||
| 1013 | 228 | w++; | |
| 1014 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1015 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | Crc |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 22) & 0b1111111111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1016 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto Crs = static_cast<int16_t>(((sfrbx.dwrd.at(w) >> 14) & 0b11111111) << 8); |
| 1017 | LOG_DATA("{}: [{}] Crc {} ({}), Crs {}", nameId(), satId, Crc, std::bitset<16>(static_cast<uint16_t>(Crc)), std::bitset<16>(static_cast<uint16_t>(Crs))); | ||
| 1018 | |||
| 1019 | 228 | w++; | |
| 1020 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1021 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | Crs |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1022 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto SISA = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 14) & 0b11111111); |
| 1023 | LOG_DATA("{}: [{}] Crs {} ({}), SISA {}", nameId(), satId, Crs, std::bitset<16>(static_cast<uint16_t>(Crs)), SISA); | ||
| 1024 | |||
| 1025 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | auto ephemerisBuilder = getEphemerisBuilder(satId, IODnav); |
| 1026 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 225 times.
|
228 | if (!ephemerisBuilder.has_value()) |
| 1027 | { | ||
| 1028 | LOG_DATA("{}: [{}] Could not find Ephemeris builder for IODnav {}", nameId(), satId, IODnav); | ||
| 1029 | 3 | return; | |
| 1030 | } | ||
| 1031 | 225 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder->get().navData); | |
| 1032 | |||
| 1033 | 225 | ephemeris->Omega_dot = semicircles2rad(Omega_dot * std::pow(2.0, -43)); | |
| 1034 | 225 | ephemeris->delta_n = semicircles2rad(delta_n * std::pow(2.0, -43)); | |
| 1035 | 225 | ephemeris->Cuc = Cuc * std::pow(2.0, -29); | |
| 1036 | 225 | ephemeris->Cus = Cus * std::pow(2.0, -29); | |
| 1037 | 225 | ephemeris->Crc = Crc * std::pow(2.0, -5); | |
| 1038 | 225 | ephemeris->Crs = Crs * std::pow(2.0, -5); | |
| 1039 |
1/2✓ Branch 1 taken 225 times.
✗ Branch 2 not taken.
|
225 | ephemeris->signalAccuracy = galSisaIdx2Val(SISA); |
| 1040 | |||
| 1041 | LOG_DATA("{}: [{}] IODnav [{}], Omega_dot [{} rad/s], delta_n [{:.3e} rad/s], Cuc [{:.3e} rad], Cus [{:.3e} rad/s], Crc [{:.3e} m], Crs [{:.3e} m], SISA [{:.3e} m]", nameId(), satId, | ||
| 1042 | ephemeris->IODnav, ephemeris->Omega_dot, ephemeris->delta_n, ephemeris->Cuc, ephemeris->Cus, ephemeris->Crc, ephemeris->Crs, ephemeris->signalAccuracy); | ||
| 1043 | |||
| 1044 |
1/2✓ Branch 4 taken 225 times.
✗ Branch 5 not taken.
|
225 | finishWord(ephemeris, wordType, ephemerisBuilder->get().subframes); |
| 1045 | 225 | } | |
| 1046 |
2/2✓ Branch 0 taken 237 times.
✓ Branch 1 taken 2649 times.
|
2886 | else if (wordType == 4) // SVID, Ephemeris (4/4), and Clock correction parameters |
| 1047 | { | ||
| 1048 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 43 Bits Allocation for I/NAV Word Type 4, p. 38 | ||
| 1049 | // | ||
| 1050 | // Even/Odd PageType WordType IODnav SVID Cic Cic Cis toc toc af0 af0 af1 Tail Pad Even/Odd PageType af1 af2 Spare Reserved 1 | ||
| 1051 | // 1 1 6 10 6 8 8 16 8 6 26 5 13 6 8 1 1 8 6 2 14 | ||
| 1052 | // └───────────────────────┬─────────────────────┘ └─────┬─────┘ └──┬───┘ └────────┬────────┘ └───────────────────────┬─────────────────────┘ | ||
| 1053 | // Ublox 1 2 3 4 5 | ||
| 1054 | |||
| 1055 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.1, Table 60 Ephemeris Parameters, p. 43f | ||
| 1056 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.3, Table 63 Galileo Clock Correction Parameters, p. 46 | ||
| 1057 | // > Cic, Cis, af0, af1, af2 shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 1058 | |||
| 1059 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1060 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto IODnav = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 14) & 0b1111111111); |
| 1061 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | [[maybe_unused]] auto SVID = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 8) & 0b111111); |
| 1062 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto Cic = static_cast<int16_t>((sfrbx.dwrd.at(w) & 0b11111111) << 8); |
| 1063 | LOG_DATA("{}: [{}] IODnav {}, SVID {}, Cic {}", nameId(), satId, IODnav, SVID, std::bitset<16>(static_cast<uint16_t>(Cic))); | ||
| 1064 | |||
| 1065 | 237 | w++; | |
| 1066 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1067 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | Cic |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 24) & 0b11111111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1068 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto Cis = static_cast<int16_t>((sfrbx.dwrd.at(w) >> 8) & 0b1111111111111111); |
| 1069 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto toc = static_cast<uint16_t>((sfrbx.dwrd.at(w) & 0b11111111) << 6); |
| 1070 | LOG_DATA("{}: [{}] Cic {} ({}), Cis {}, toc {}", nameId(), satId, Cic, std::bitset<16>(static_cast<uint16_t>(Cic)), Cis, std::bitset<16>(toc)); | ||
| 1071 | |||
| 1072 | 237 | w++; | |
| 1073 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1074 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | toc |= static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 26) & 0b111111); |
| 1075 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto af0 = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b11111111111111111111111111) << 5); |
| 1076 | LOG_DATA("{}: [{}] toc {} ({}), af0 {}", nameId(), satId, toc, std::bitset<16>(toc), std::bitset<32>(static_cast<uint32_t>(af0))); | ||
| 1077 | |||
| 1078 | 237 | w++; | |
| 1079 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1080 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | af0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 27) & 0b11111); |
| 1081 | 237 | af0 = math::interpretAs<int32_t, 31>(af0); | |
| 1082 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto af1 = static_cast<int32_t>(((sfrbx.dwrd.at(w) >> 14) & 0b1111111111111) << 8); |
| 1083 | LOG_DATA("{}: [{}] af0 {} ({}), af1 {}", nameId(), satId, af0, std::bitset<32>(static_cast<uint32_t>(af0)), std::bitset<32>(static_cast<uint32_t>(af1))); | ||
| 1084 | |||
| 1085 | 237 | w++; | |
| 1086 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1087 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | af1 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 22) & 0b11111111); |
| 1088 | 237 | af1 = math::interpretAs<int32_t, 21>(af1); | |
| 1089 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto af2 = math::interpretAs<int8_t, 6>(sfrbx.dwrd.at(w) >> 16); |
| 1090 | LOG_DATA("{}: [{}] af1 {} ({}), af1 {}", nameId(), satId, af1, std::bitset<32>(static_cast<uint32_t>(af1)), std::bitset<8>(static_cast<uint8_t>(af2))); | ||
| 1091 | |||
| 1092 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto ephemerisBuilder = getEphemerisBuilder(satId, IODnav); |
| 1093 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 209 times.
|
237 | if (!ephemerisBuilder.has_value()) |
| 1094 | { | ||
| 1095 | LOG_DATA("{}: [{}] Could not find Ephemeris builder for IODnav {}", nameId(), satId, IODnav); | ||
| 1096 | 28 | return; | |
| 1097 | } | ||
| 1098 | 209 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder->get().navData); | |
| 1099 | |||
| 1100 |
1/2✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
|
209 | InsTime insTimeToc(gpsWeekToW.gpsCycle, gpsWeekToW.gpsWeek, toc * 60.0, GST); |
| 1101 | |||
| 1102 | 209 | ephemeris->Cic = Cic * std::pow(2.0, -29); | |
| 1103 | 209 | ephemeris->Cis = Cis * std::pow(2.0, -29); | |
| 1104 | 209 | ephemeris->toc = insTimeToc; | |
| 1105 | 209 | ephemeris->refTime = ephemeris->toc; | |
| 1106 | 209 | ephemeris->a = { | |
| 1107 | 209 | af0 * std::pow(2, -34), | |
| 1108 | 209 | af1 * std::pow(2, -46), | |
| 1109 | 209 | af2 * std::pow(2, -59), | |
| 1110 | }; | ||
| 1111 | |||
| 1112 | LOG_DATA("{}: [{}] IODnav [{}], Cic [{:.3e} rad], Cis [{:.3e} rad]", nameId(), satId, ephemeris->IODnav, ephemeris->Cic, ephemeris->Cis); | ||
| 1113 | LOG_DATA("{}: [{}] toc [{}], a0 [{:.3e} s], a1 [{:.3e} s/s], a2 [{:.3e} s/s^2]", nameId(), satId, | ||
| 1114 | ephemeris->toc.toYMDHMS(GPST), ephemeris->a[0], ephemeris->a[1], ephemeris->a[2]); | ||
| 1115 | |||
| 1116 |
1/2✓ Branch 4 taken 209 times.
✗ Branch 5 not taken.
|
209 | finishWord(ephemeris, wordType, ephemerisBuilder->get().subframes); |
| 1117 | 209 | } | |
| 1118 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 2413 times.
|
2649 | else if (wordType == 5) // Ionospheric correction, BGD, signal health and data validity status and GST |
| 1119 | { | ||
| 1120 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 44 Bits Allocation for I/NAV Word Type 5, p. 38 | ||
| 1121 | // | ||
| 1122 | // Even/Odd PageType WordType ai0 ai1 ai2 ai2 Region 1-5 BGD(E1,E5a) BGD(E1,E5b) BGD(E1,E5b) E5b_HS E1b_HS E5b_DVS E1b_DVS WN TOW TOW Spare Tail Pad Even/Odd PageType Spare Reserved 1 | ||
| 1123 | // 1 1 6 11 11 2 12 5x1 10 5 5 2 2 1 1 12 9 11 7 13 6 1 1 16 14 | ||
| 1124 | // └─────────────────────┬───────────────────┘ └───────────────────┬───────────────────┘ └─────────────────────────┬──────────────────────────┘ └─────────┬─────────┘ └──────────────────┬────────────────┘ | ||
| 1125 | // Ublox 1 2 3 4 5 | ||
| 1126 | |||
| 1127 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.6, Table 67 Ionospheric Correction Parameters, p. 48 | ||
| 1128 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.5, Table 65 BGD Parameters, p. 47 | ||
| 1129 | // > ai1, ai2, BGD(E1,E5a), BGD(E1,E5b) shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 1130 | |||
| 1131 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1132 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto ai0 = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 13) & 0b11111111111); |
| 1133 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto ai1 = math::interpretAs<int16_t, 11>((sfrbx.dwrd.at(w) >> 2) & 0b11111111111); |
| 1134 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto ai2 = static_cast<int16_t>((sfrbx.dwrd.at(w) & 0b11) << 12); |
| 1135 | LOG_DATA("{}: [{}] ai0 {} ({}), ai1 {} ({}), ai2 {}", nameId(), satId, | ||
| 1136 | ai0, std::bitset<16>(ai0), ai1, std::bitset<16>(static_cast<uint16_t>(ai1)), std::bitset<16>(static_cast<uint16_t>(ai2))); | ||
| 1137 | |||
| 1138 | 236 | w++; | |
| 1139 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1140 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | ai2 |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 20) & 0b111111111111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1141 | 236 | ai2 = math::interpretAs<int16_t, 14>(ai2); | |
| 1142 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto BGD_E1_E5a = math::interpretAs<int16_t, 10>((sfrbx.dwrd.at(w) >> 5) & 0b1111111111); |
| 1143 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto BGD_E1_E5b = static_cast<int16_t>((sfrbx.dwrd.at(w) & 0b11111) << 5); |
| 1144 | LOG_DATA("{}: [{}] ai2 {} ({}), BGD_E1_E5a {}, BGD_E1_E5b {}", nameId(), satId, ai2, std::bitset<16>(static_cast<uint16_t>(ai2)), BGD_E1_E5a, std::bitset<16>(static_cast<uint16_t>(BGD_E1_E5b))); | ||
| 1145 | |||
| 1146 | 236 | w++; | |
| 1147 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1148 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | BGD_E1_E5b |= static_cast<int16_t>((sfrbx.dwrd.at(w) >> 27) & 0b11111); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) |
| 1149 | 236 | BGD_E1_E5b = math::interpretAs<int16_t, 10>(BGD_E1_E5b); | |
| 1150 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto E5b_HS = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 25) & 0b11); |
| 1151 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto E1b_HS = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 23) & 0b11); |
| 1152 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto E5b_DVS = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 22) & 0b1); |
| 1153 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto E1b_DVS = static_cast<uint8_t>((sfrbx.dwrd.at(w) >> 21) & 0b1); |
| 1154 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | [[maybe_unused]] auto WN = static_cast<uint16_t>((sfrbx.dwrd.at(w) >> 9) & 0b111111111111); |
| 1155 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | [[maybe_unused]] uint32_t TOW = (sfrbx.dwrd.at(w) & 0b111111111) << 11; |
| 1156 | LOG_DATA("{}: [{}] BGD_E1_E5b {} ({}), E5b_HS {}, E1b_HS {}, E5b_DVS {}, E1b_DVS {}, WN {}, TOW {}", nameId(), satId, | ||
| 1157 | BGD_E1_E5b, std::bitset<16>(static_cast<uint16_t>(BGD_E1_E5b)), E5b_HS, E1b_HS, E5b_DVS, E1b_DVS, WN, std::bitset<32>(TOW)); | ||
| 1158 | |||
| 1159 | 236 | w++; | |
| 1160 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1161 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | TOW |= (sfrbx.dwrd.at(w) >> 21) & 0b11111111111; |
| 1162 | LOG_DATA("{}: [{}] TOW {} ({})", nameId(), satId, TOW, std::bitset<32>(TOW)); | ||
| 1163 | |||
| 1164 | 236 | w++; | |
| 1165 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1166 | |||
| 1167 |
1/2✓ Branch 1 taken 236 times.
✗ Branch 2 not taken.
|
236 | auto ephemerisBuilder = getLastEphemerisBuilder(satId); |
| 1168 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 233 times.
|
236 | if (!ephemerisBuilder.has_value()) |
| 1169 | { | ||
| 1170 | LOG_DATA("{}: [{}] Could not find any ephemeris builder", nameId(), satId); | ||
| 1171 | 3 | return; | |
| 1172 | } | ||
| 1173 | 233 | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder->get().navData); | |
| 1174 | |||
| 1175 | 233 | ephemeris->BGD_E1_E5a = BGD_E1_E5a * std::pow(2.0, -32); | |
| 1176 | 233 | ephemeris->BGD_E1_E5b = BGD_E1_E5b * std::pow(2.0, -32); | |
| 1177 | 233 | ephemeris->svHealth = { | |
| 1178 | .E5a_DataValidityStatus = {}, | ||
| 1179 | .E5b_DataValidityStatus = static_cast<GalileoEphemeris::SvHealth::DataValidityStatus>(E5b_DVS), | ||
| 1180 | .E1B_DataValidityStatus = static_cast<GalileoEphemeris::SvHealth::DataValidityStatus>(E1b_DVS), | ||
| 1181 | .E5a_SignalHealthStatus = {}, | ||
| 1182 | .E5b_SignalHealthStatus = static_cast<GalileoEphemeris::SvHealth::SignalHealthStatus>(E5b_HS), | ||
| 1183 | .E1B_SignalHealthStatus = static_cast<GalileoEphemeris::SvHealth::SignalHealthStatus>(E1b_HS), | ||
| 1184 | }; | ||
| 1185 | 233 | ephemeris->dataSource[0] = true; // I/NAV E1-B | |
| 1186 | 233 | ephemeris->dataSource[9] = true; // af0-af2, Toc, SISA are for E5b,E1 | |
| 1187 | |||
| 1188 | { | ||
| 1189 |
1/2✓ Branch 1 taken 233 times.
✗ Branch 2 not taken.
|
233 | std::unique_lock guard(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex, std::defer_lock); |
| 1190 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 233 times.
|
233 | if (!_postProcessingLock.has_value()) |
| 1191 | { | ||
| 1192 | ✗ | guard.lock(); | |
| 1193 | } | ||
| 1194 | |||
| 1195 |
3/4✓ Branch 1 taken 233 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 232 times.
|
233 | if (!_gnssNavInfo.ionosphericCorrections.contains(satId.satSys, IonosphericCorrections::Alpha)) |
| 1196 | { | ||
| 1197 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | LOG_DEBUG("{}: [{}] Received Ionospheric corrections [{}]", nameId(), satId.satSys, ephemeris->refTime.toYMDHMS(GPST)); |
| 1198 | } | ||
| 1199 | |||
| 1200 | // ‘sfu’ (solar flux unit) is not a SI unit but can be converted as: 1 sfu = 10e-22 W/(m2*Hz) | ||
| 1201 | ✗ | _gnssNavInfo.ionosphericCorrections.insert(satId.satSys, IonosphericCorrections::Alpha, | |
| 1202 | { | ||
| 1203 | 233 | ai0 * std::pow(2.0, -2) /* [sfu] */, | |
| 1204 | 233 | ai1 * std::pow(2.0, -8) /* [sfu/degree] */, | |
| 1205 |
1/2✓ Branch 2 taken 233 times.
✗ Branch 3 not taken.
|
233 | ai2 * std::pow(2.0, -15) /* [sfu/degree^2] */, |
| 1206 | 0.0, | ||
| 1207 | }); | ||
| 1208 | 233 | } | |
| 1209 | |||
| 1210 | LOG_DATA("{}: [{}] BGD_E1_E5a [{:.3e} s], BGD_E1_E5b [{:.3e} rad]", nameId(), satId, ephemeris->BGD_E1_E5a, ephemeris->BGD_E1_E5b); | ||
| 1211 | |||
| 1212 |
1/2✓ Branch 4 taken 233 times.
✗ Branch 5 not taken.
|
233 | finishWord(ephemeris, wordType, ephemerisBuilder->get().subframes); |
| 1213 | 233 | } | |
| 1214 |
2/2✓ Branch 0 taken 237 times.
✓ Branch 1 taken 2176 times.
|
2413 | else if (wordType == 6) // GST-UTC conversion parameters |
| 1215 | { | ||
| 1216 | // Galileo-OS-SIS-ICD-v2.0: ch. 4.3.5, Table 44 Bits Allocation for I/NAV Word Type 6, p. 38 | ||
| 1217 | // | ||
| 1218 | // Even/Odd PageType WordType A0 A0 A1 dt_LS t0t WNot WN_LSF DN dt_LSF TOW Tail Pad Even/Odd PageType TOW Spare Reserved 1 | ||
| 1219 | // 1 1 6 24 8 24 8 8 8 8 3 8 7 6 8 1 1 13 3 14 | ||
| 1220 | // └───────────────┬──────────────┘ └──┬─┘ └──────────┬───────────┘ └────────────┬───────────┘ └────────────────────┬───────────────────┘ | ||
| 1221 | // Ublox 1 2 3 4 5 | ||
| 1222 | |||
| 1223 | // Galileo-OS-SIS-ICD-v2.0: ch. 5.1.7, Table 68 Ionospheric Correction Parameters, p. 49 | ||
| 1224 | // > A0, A1, dt_LS, dt_LSF shall be two's complement, with the sign bit (+ or -) occupying the MSB | ||
| 1225 | |||
| 1226 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 1 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1227 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto A0 = static_cast<int32_t>((sfrbx.dwrd.at(w) & 0b111111111111111111111111) << 8); |
| 1228 | LOG_DATA("{}: [{}] A0 {}", nameId(), satId, std::bitset<32>(static_cast<uint32_t>(A0))); | ||
| 1229 | |||
| 1230 | 237 | w++; | |
| 1231 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 2 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1232 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | A0 |= static_cast<int32_t>((sfrbx.dwrd.at(w) >> 24) & 0b11111111); |
| 1233 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto A1 = math::interpretAs<int32_t, 24>(sfrbx.dwrd.at(w) & 0b111111111111111111111111); |
| 1234 | LOG_DATA("{}: [{}] A0 {} ({}), A1 {} ({})", nameId(), satId, A0, std::bitset<32>(static_cast<uint32_t>(A0)), A1, std::bitset<32>(static_cast<uint32_t>(A1))); | ||
| 1235 | |||
| 1236 | 237 | w++; | |
| 1237 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 3 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1238 | |||
| 1239 | 237 | w++; | |
| 1240 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 4 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1241 | |||
| 1242 | 237 | w++; | |
| 1243 | LOG_DATA("{}: [{}] word {:2}: {}", nameId(), satId, w + 1 /* 5 */, std::bitset<32>(sfrbx.dwrd.at(w))); | ||
| 1244 | |||
| 1245 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | std::unique_lock guard(outputPins.at(OUTPUT_PORT_INDEX_GNSS_NAV_INFO).dataAccessMutex, std::defer_lock); |
| 1246 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 237 times.
|
237 | if (!_postProcessingLock.has_value()) |
| 1247 | { | ||
| 1248 | ✗ | guard.lock(); | |
| 1249 | } | ||
| 1250 | |||
| 1251 |
1/2✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
|
237 | auto key = std::make_pair(satId.satSys.getTimeSystem(), UTC); |
| 1252 |
3/4✓ Branch 2 taken 237 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 236 times.
|
237 | if (!_gnssNavInfo.timeSysCorr.contains(key)) |
| 1253 | { | ||
| 1254 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
2 | if (auto ephemerisBuilder = getLastEphemerisBuilder(satId); |
| 1255 | 1 | ephemerisBuilder.has_value()) | |
| 1256 | { | ||
| 1257 | ✗ | auto ephemeris = std::dynamic_pointer_cast<GalileoEphemeris>(ephemerisBuilder->get().navData); | |
| 1258 | ✗ | LOG_DEBUG("{}: [{}] Received Time system corrections [{}]", nameId(), satId.satSys, ephemeris->refTime.toYMDHMS(GPST)); | |
| 1259 | ✗ | } | |
| 1260 | else | ||
| 1261 | { | ||
| 1262 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | LOG_DEBUG("{}: [{}] Received Time system corrections", nameId(), satId.satSys); |
| 1263 | } | ||
| 1264 | } | ||
| 1265 | |||
| 1266 |
1/2✓ Branch 2 taken 237 times.
✗ Branch 3 not taken.
|
237 | _gnssNavInfo.timeSysCorr[key] = GnssNavInfo::TimeSystemCorrections{ |
| 1267 | 237 | .a0 = A0 * std::pow(2, -30), | |
| 1268 | 237 | .a1 = A1 * std::pow(2, -50), | |
| 1269 | }; | ||
| 1270 | 237 | } | |
| 1271 | } | ||
| 1272 | |||
| 1273 | ✗ | void NAV::UbloxGnssOrbitCollector::decryptGLONASS([[maybe_unused]] const SatId& satId, const ubx::UbxRxmSfrbx& /* sfrbx */, const InsTime& /* insTime */) | |
| 1274 | { | ||
| 1275 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.3, p. 31 | ||
| 1276 | // > For GLONASS L1OF and L2OF signals, each reported subframe contains a string as described in | ||
| 1277 | // > the GLONASS ICD. This string comprises 85 data bits which are reported over three 32 bit words | ||
| 1278 | // > in the UBX-RXM-SFRBX message. Data bits 1 to 8 are always a hamming code, whilst bits 81 to 84 | ||
| 1279 | // > are a string number and bit 85 is the idle chip, which should always have a value of zero. The | ||
| 1280 | // > meaning of other bits vary with string and frame number. | ||
| 1281 | // > The fourth and final 32 bit word in the UBX-RXM-SFRBX message contains frame and superframe | ||
| 1282 | // > numbers (where available). These values aren't actually transmitted by the SVs, but are deduced | ||
| 1283 | // > by the receiver and are included to aid decoding of the transmitted data. However, the receiver | ||
| 1284 | // > does not always know these values, in which case a value of zero is reported. | ||
| 1285 | // > | ||
| 1286 | // > MSB LSB | ||
| 1287 | // > 1: Idle chip (1 bit, always 0) String # (4 bits) Data (80 - 54) (27 bits) | ||
| 1288 | // > 2: Data (53 - 22) (32 bits) | ||
| 1289 | // > 3: Data (21 - 9) (13 bits) Hammering code (8 bits) Pad (11 bits) | ||
| 1290 | // > 4: Superframe # (16 bits) Pad (8 bits) Frame # (8 bits) | ||
| 1291 | // > | ||
| 1292 | // > In some circumstances, (especially on startup) the receiver may be able to decode data from a | ||
| 1293 | // > GLONASS SV before it can identify the SV. When this occurs UBX-RXM-SFRBX messages will be | ||
| 1294 | // > issued with an svId of 255 to indicate "unknown". | ||
| 1295 | |||
| 1296 | ✗ | if (!_warningsNotImplemented.contains(satId.satSys)) | |
| 1297 | { | ||
| 1298 | ✗ | LOG_WARN("{}: ubx orbit collector is not implemented for GLONASS yet.", nameId()); // TODO: not implemented yet. | |
| 1299 | ✗ | _warningsNotImplemented.insert(satId.satSys); | |
| 1300 | } | ||
| 1301 | |||
| 1302 | // auto ephemeris = std::dynamic_pointer_cast<GLONASSEphemeris>(ephemerisBuilder->get().navData); | ||
| 1303 | |||
| 1304 | // sfrbx.freqId; | ||
| 1305 | // _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<GLONASSEphemeris>(epoch, tau_c, | ||
| 1306 | // -m_tau_n, gamma_n, static_cast<bool>(health), | ||
| 1307 | // pos, vel, accelLuniSolar, | ||
| 1308 | // frequencyNumber_accuracyCode)); | ||
| 1309 | ✗ | } | |
| 1310 | |||
| 1311 | ✗ | void NAV::UbloxGnssOrbitCollector::decryptBeiDou([[maybe_unused]] const SatId& satId, const ubx::UbxRxmSfrbx& /* sfrbx */, const InsTime& /* insTime */) | |
| 1312 | { | ||
| 1313 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.4, p. 32 | ||
| 1314 | // > For BeiDou (B1I) signals, there is a fairly straightforward mapping between the reported subframe | ||
| 1315 | // > and the structure of subframe and words described in the BeiDou ICD. Each subframe comprises | ||
| 1316 | // > ten data words, which are reported in the same order they are received. | ||
| 1317 | // > | ||
| 1318 | // > MSB LSB | ||
| 1319 | // > 1 to 10: Pad (2 bits) Data (22 bits) Parity (8 bits) | ||
| 1320 | // > | ||
| 1321 | // > Note that as the BeiDou data words only comprise 30 bits, the 2 most significant bits in each word | ||
| 1322 | // > reported by UBX-RXM-SFRBX are padding and should be ignored. | ||
| 1323 | |||
| 1324 | ✗ | if (!_warningsNotImplemented.contains(satId.satSys)) | |
| 1325 | { | ||
| 1326 | ✗ | LOG_WARN("{}: ubx orbit collector is not implemented for BeiDou yet.", nameId()); // TODO: not implemented yet. | |
| 1327 | ✗ | _warningsNotImplemented.insert(satId.satSys); | |
| 1328 | } | ||
| 1329 | |||
| 1330 | // auto ephemeris = std::dynamic_pointer_cast<BDSEphemeris>(ephemerisBuilder->get().navData); | ||
| 1331 | |||
| 1332 | // _gnssNavInfo.addSatelliteNavData({ satSys, satNum }, std::make_shared<BDSEphemeris>(epoch, toe, | ||
| 1333 | // IODE_IODnav_AODE_IODEC, fitInterval_AODC, a, | ||
| 1334 | // sqrt_A, e, i_0, Omega_0, omega, M_0, | ||
| 1335 | // delta_n, Omega_dot, i_dot, Cus, Cuc, | ||
| 1336 | // Cis, Cic, Crs, Crc, | ||
| 1337 | // signalAccuracy, svHealth, | ||
| 1338 | // tgd_bgd5a_TGD1, IODC_bgd5b_TGD2)); | ||
| 1339 | ✗ | } | |
| 1340 | |||
| 1341 | ✗ | void NAV::UbloxGnssOrbitCollector::decryptQZSS([[maybe_unused]] const SatId& satId, const ubx::UbxRxmSfrbx& /* sfrbx */, const InsTime& /* insTime */) | |
| 1342 | { | ||
| 1343 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.7, p. 34 | ||
| 1344 | // > The structure of the data delivered by QZSS L1C/A signals is effectively identical to that of GPS | ||
| 1345 | // > (L1C/A). Similarly the QZSS L2C signal is effectively identical to the GPS (L2C). | ||
| 1346 | // > The QZSS (L1SAIF) signal is different and uses the same data block format as used by SBAS | ||
| 1347 | // > (L1C/A). QZSS (SAIF) signals can be distinguished from QZSS (L1C/A and L2C) by noting that they | ||
| 1348 | // > have 8 words, instead of 10 for QZSS (L1C/A and L2C). | ||
| 1349 | |||
| 1350 | ✗ | if (!_warningsNotImplemented.contains(satId.satSys)) | |
| 1351 | { | ||
| 1352 | ✗ | LOG_WARN("{}: ubx orbit collector is not implemented for QZSS yet.", nameId()); // TODO: not implemented yet. | |
| 1353 | ✗ | _warningsNotImplemented.insert(satId.satSys); | |
| 1354 | } | ||
| 1355 | ✗ | } | |
| 1356 | |||
| 1357 | ✗ | void NAV::UbloxGnssOrbitCollector::decryptIRNSS([[maybe_unused]] const SatId& satId, const ubx::UbxRxmSfrbx& /* sfrbx */, const InsTime& /* insTime */) | |
| 1358 | { | ||
| 1359 | ✗ | if (!_warningsNotImplemented.contains(satId.satSys)) | |
| 1360 | { | ||
| 1361 | ✗ | LOG_WARN("{}: ubx orbit collector is not implemented for IRNSS yet.", nameId()); // TODO: not implemented yet. | |
| 1362 | ✗ | _warningsNotImplemented.insert(satId.satSys); | |
| 1363 | } | ||
| 1364 | ✗ | } | |
| 1365 | |||
| 1366 | ✗ | void NAV::UbloxGnssOrbitCollector::decryptSBAS([[maybe_unused]] const SatId& satId, const ubx::UbxRxmSfrbx& /* sfrbx */, const InsTime& /* insTime */) | |
| 1367 | { | ||
| 1368 | // u-blox 8 / u-blox M8: Receiver description - Including protocol specification, ch. 10.6, p. 33f | ||
| 1369 | |||
| 1370 | ✗ | if (!_warningsNotImplemented.contains(satId.satSys)) | |
| 1371 | { | ||
| 1372 | ✗ | LOG_WARN("{}: ubx orbit collector is not implemented for SBAS yet.", nameId()); // TODO: not implemented yet. | |
| 1373 | ✗ | _warningsNotImplemented.insert(satId.satSys); | |
| 1374 | } | ||
| 1375 | ✗ | } | |
| 1376 |