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