INSTINCT Code Coverage Report


Directory: src/
File: Nodes/DataProvider/GNSS/FileReader/RinexObsFile.cpp
Date: 2025-07-19 10:51:51
Exec Total Coverage
Lines: 302 391 77.2%
Functions: 17 21 81.0%
Branches: 499 1046 47.7%

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 "RinexObsFile.hpp"
10
11 #include <fmt/ranges.h>
12
13 #include "util/Eigen.hpp"
14
15 #include "internal/NodeManager.hpp"
16 #include "util/Logger.hpp"
17 namespace nm = NAV::NodeManager;
18 #include "internal/FlowManager.hpp"
19 #include "internal/gui/widgets/HelpMarker.hpp"
20
21 #include "util/StringUtil.hpp"
22
23 #include "Navigation/GNSS/Core/SatelliteSystem.hpp"
24 #include "Navigation/GNSS/Core/Code.hpp"
25 #include "NodeData/GNSS/GnssObs.hpp"
26
27 #include "util/Vendor/RINEX/RINEXUtilities.hpp"
28
29 namespace NAV
30 {
31
32 163 RinexObsFile::RinexObsFile()
33
4/8
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 163 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 163 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 163 times.
✗ Branch 14 not taken.
163 : Node(typeStatic())
34 {
35 LOG_TRACE("{}: called", name);
36
37 163 _hasConfig = true;
38 163 _guiConfigDefaultWindowSize = { 517, 118 };
39
40
4/8
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 163 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 163 times.
✓ Branch 9 taken 163 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
489 nm::CreateOutputPin(this, "GnssObs", Pin::Type::Flow, { NAV::GnssObs::type() }, &RinexObsFile::pollData);
41 326 }
42
43 424 RinexObsFile::~RinexObsFile()
44 {
45 LOG_TRACE("{}: called", nameId());
46 424 }
47
48 277 std::string RinexObsFile::typeStatic()
49 {
50
1/2
✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
554 return "RinexObsFile";
51 }
52
53 std::string RinexObsFile::type() const
54 {
55 return typeStatic();
56 }
57
58 114 std::string RinexObsFile::category()
59 {
60
1/2
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
228 return "Data Provider";
61 }
62
63 void RinexObsFile::guiConfig()
64 {
65 if (auto res = FileReader::guiConfig(R"(Rinex Obs (.obs .rnx .*o){.obs,.rnx,(.+[.]\d\d?[oO])},.*)",
66 { ".obs", ".rnx", "(.+[.]\\d\\d?[oO])" }, size_t(id), nameId()))
67 {
68 LOG_DEBUG("{}: Path changed to {}", nameId(), _path);
69 flow::ApplyChanges();
70 if (res == FileReader::PATH_CHANGED)
71 {
72 doReinitialize();
73 }
74 else
75 {
76 doDeinitialize();
77 }
78 }
79 ImGui::Text("Supported versions: ");
80 std::ranges::for_each(_supportedVersions, [](double x) {
81 ImGui::SameLine();
82 ImGui::Text("%0.2f", x);
83 });
84
85 ImGui::Checkbox("Erase less precise codes", &_eraseLessPreciseCodes);
86 ImGui::SameLine();
87 gui::widgets::HelpMarker("Whether to remove less precise codes (e.g. if G1X (L1C combined) is present, don't use G1L (L1C pilot) and G1S (L1C data))");
88 }
89
90 [[nodiscard]] json RinexObsFile::save() const
91 {
92 LOG_TRACE("{}: called", nameId());
93
94 json j;
95
96 j["FileReader"] = FileReader::save();
97 j["eraseLessPreciseCodes"] = _eraseLessPreciseCodes;
98
99 return j;
100 }
101
102 49 void RinexObsFile::restore(json const& j)
103 {
104 LOG_TRACE("{}: called", nameId());
105
106
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 if (j.contains("FileReader"))
107 {
108 49 FileReader::restore(j.at("FileReader"));
109 }
110
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 if (j.contains("eraseLessPreciseCodes"))
111 {
112 49 j.at("eraseLessPreciseCodes").get_to(_eraseLessPreciseCodes);
113 }
114 49 }
115
116 49 bool RinexObsFile::initialize()
117 {
118 LOG_TRACE("{}: called", nameId());
119
120 49 return FileReader::initialize();
121 }
122
123 49 void RinexObsFile::deinitialize()
124 {
125 LOG_TRACE("{}: called", nameId());
126
127 49 FileReader::deinitialize();
128
129 49 _version = 0.0;
130 49 _timeSystem = TimeSys_None;
131 49 _obsDescription.clear();
132 49 _rcvClockOffsAppl = false;
133 49 _receiverInfo = {};
134 98 }
135
136 98 bool RinexObsFile::resetNode()
137 {
138 LOG_TRACE("{}: called", nameId());
139
140 98 FileReader::resetReader();
141
142 98 return true;
143 }
144
145 48 FileReader::FileType RinexObsFile::determineFileType()
146 {
147 1633 auto extHeaderLabel = [](std::string line) {
148 // Remove any trailing non text characters
149
2/4
✓ Branch 3 taken 1636 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1636 times.
✗ Branch 8 not taken.
122375 line.erase(std::ranges::find_if(line, [](int ch) { return std::iscntrl(ch); }), line.end());
150
151
1/2
✓ Branch 2 taken 1636 times.
✗ Branch 3 not taken.
1636 return str::trim_copy(std::string_view(line).substr(60, 20));
152 };
153
154
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
48 std::filesystem::path filepath = getFilepath();
155
156
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 auto filestreamHeader = std::ifstream(filepath);
157
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 if (filestreamHeader.good())
158 {
159 49 std::string line;
160 // --------------------------------------- RINEX VERSION / TYPE ------------------------------------------
161
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 std::getline(filestreamHeader, line);
162
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 str::rtrim(line);
163
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (line.size() != 80)
164 {
165 LOG_ERROR("{}: Not a valid RINEX OBS file. Lines should be 80 characters long but the file has {}.", nameId(), line.size() - 1);
166 return FileReader::FileType::NONE;
167 }
168
169
3/6
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 49 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 48 times.
49 if (extHeaderLabel(line) != "RINEX VERSION / TYPE")
170 {
171 LOG_ERROR("{}: Not a valid RINEX OBS file. Could not read 'RINEX VERSION / TYPE' line.", nameId());
172 return FileReader::FileType::NONE;
173 }
174
175
3/6
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 49 times.
✗ Branch 8 not taken.
48 double version = std::stod(str::trim_copy(line.substr(0, 20))); // FORMAT: F9.2,11X
176
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
48 if (!_supportedVersions.contains(version))
177 {
178 LOG_ERROR("{}: RINEX version {} is not supported. Supported versions are [{}]", nameId(),
179 version, fmt::join(_supportedVersions.begin(), _supportedVersions.end(), ", "));
180 return FileReader::FileType::NONE;
181 }
182
183
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
48 std::string fileType = str::trim_copy(line.substr(20, 20)); // FORMAT: A1,19X
184
2/4
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
48 if (fileType.at(0) != 'O')
185 {
186 LOG_ERROR("{}: Not a valid RINEX OBS file. File type '{}' not recognized.", nameId(), fileType);
187 doDeinitialize();
188 return FileReader::FileType::NONE;
189 }
190
2/4
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
47 std::string satSystem = str::trim_copy(line.substr(40, 20)); // FORMAT: A1,19X
191
7/12
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 46 times.
✓ Branch 8 taken 3 times.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 45 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 48 times.
49 if (SatelliteSystem::fromChar(satSystem.at(0)) == SatSys_None && satSystem.at(0) != 'M')
192 {
193 LOG_ERROR("{}: Not a valid RINEX OBS file. Satellite System '{}' not recognized.", nameId(), satSystem.at(0));
194 doDeinitialize();
195 return FileReader::FileType::NONE;
196 }
197 // ---------------------------------------- PGM / RUN BY / DATE ------------------------------------------
198
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 std::getline(filestreamHeader, line);
199
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
48 str::rtrim(line);
200
3/6
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 49 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 48 times.
49 if (extHeaderLabel(line) != "PGM / RUN BY / DATE")
201 {
202 LOG_ERROR("{}: Not a valid RINEX OBS file. Could not read 'PGM / RUN BY / DATE' line.", nameId());
203 return FileReader::FileType::NONE;
204 }
205
206 // ----------------------------------------- END OF HEADER -------------------------------------------
207
4/6
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1537 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1536 times.
✓ Branch 7 taken 1 times.
1536 while (std::getline(filestreamHeader, line))
208 {
209
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1536 str::rtrim(line);
210
4/6
✓ Branch 2 taken 1536 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1537 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 49 times.
✓ Branch 10 taken 1488 times.
1537 if (extHeaderLabel(line) == "END OF HEADER")
211 {
212 49 return FileReader::FileType::ASCII;
213 }
214 }
215
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 LOG_ERROR("{}: Not a valid RINEX NAV file. Could not read 'END OF HEADER' line.", nameId());
216 return FileReader::FileType::NONE;
217 49 }
218
219 LOG_ERROR("{}: Could not determine file type because file could not be opened '{}' line.", nameId(), filepath.string());
220 return FileReader::FileType::NONE;
221 49 }
222
223 48 void RinexObsFile::readHeader()
224 {
225 LOG_TRACE("{}: called", nameId());
226
227 48 std::string line;
228
229 // --------------------------------------- RINEX VERSION / TYPE ------------------------------------------
230
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 getline(line);
231
3/6
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
49 _version = std::stod(str::trim_copy(line.substr(0, 20)));
232
3/6
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 49 times.
✗ Branch 9 not taken.
48 LOG_DEBUG("{}: Version: {:3.2f}", nameId(), _version); // FORMAT: F9.2,11X
233
5/10
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 49 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 49 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 49 times.
✗ Branch 15 not taken.
49 LOG_DEBUG("{}: SatSys : {}", nameId(), str::trim_copy(line.substr(40, 20))); // FORMAT: A1,19X
234
235 // #######################################################################################################
236
8/12
✓ Branch 1 taken 1484 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1484 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1483 times.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 1485 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1485 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1485 times.
✓ Branch 14 taken 1 times.
1485 while (getline(line) && !eof())
237 {
238
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1485 times.
1485 if (line.size() < 60)
239 {
240 LOG_WARN("{}: Skipping header line because it does not include a header label: '{}'", nameId(), line);
241 continue;
242 }
243
2/4
✓ Branch 1 taken 1482 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1485 times.
✗ Branch 5 not taken.
1485 auto headerLabel = str::trim_copy(line.substr(60, 20));
244
3/4
✓ Branch 1 taken 1482 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1433 times.
✓ Branch 4 taken 49 times.
1484 if (headerLabel == "PGM / RUN BY / DATE")
245 {
246 // Name of program creating current file
247 LOG_DATA("{}: Program: {}", nameId(), str::trim_copy(line.substr(0, 20))); // FORMAT: A20
248 // Name of agency creating current file
249 LOG_DATA("{}: Run by : {}", nameId(), str::trim_copy(line.substr(20, 20))); // FORMAT: A20
250 // Date and time of file creation
251 LOG_DATA("{}: Date : {}", nameId(), str::trim_copy(line.substr(40, 20))); // FORMAT: A20
252 }
253
3/4
✓ Branch 1 taken 1436 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1342 times.
✓ Branch 4 taken 94 times.
1433 else if (headerLabel == "COMMENT")
254 {
255 LOG_DATA("{}: Comment: {}", nameId(), line.substr(0, 60)); // FORMAT: A60
256 }
257
3/4
✓ Branch 1 taken 1340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 1291 times.
1342 else if (headerLabel == "MARKER NAME")
258 {
259
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto markerName = str::trim_copy(line.substr(0, 60)); // FORMAT: A60
260 49 if (!markerName.empty())
261 {
262 LOG_DATA("{}: Marker name: {}", nameId(), markerName);
263 }
264 49 }
265
3/4
✓ Branch 1 taken 1290 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 1253 times.
1291 else if (headerLabel == "MARKER NUMBER")
266 {
267
2/4
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
37 auto markerNumber = str::trim_copy(line.substr(0, 20)); // FORMAT: A20
268 37 if (!markerNumber.empty())
269 {
270 LOG_DATA("{}: Marker number: {}", nameId(), markerNumber);
271 }
272 37 }
273
3/4
✓ Branch 1 taken 1255 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 1211 times.
1253 else if (headerLabel == "MARKER TYPE")
274 {
275
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
44 auto markerType = str::trim_copy(line.substr(0, 60)); // FORMAT: A20,40X
276 44 if (!markerType.empty())
277 {
278 LOG_DATA("{}: Marker type: {}", nameId(), markerType);
279 }
280 44 }
281
3/4
✓ Branch 1 taken 1210 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 1161 times.
1211 else if (headerLabel == "OBSERVER / AGENCY")
282 {
283
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto observer = str::trim_copy(line.substr(0, 20)); // FORMAT: A20,A40
284
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto agency = str::trim_copy(line.substr(20, 40));
285
3/4
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 36 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
49 if (!observer.empty() || !agency.empty())
286 {
287 LOG_DATA("{}: Observer '{}', Agency '{}'", nameId(), observer, agency);
288 }
289 49 }
290
3/4
✓ Branch 1 taken 1164 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 1115 times.
1161 else if (headerLabel == "REC # / TYPE / VERS")
291 {
292
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto receiverNumber = str::trim_copy(line.substr(0, 20)); // FORMAT: 3A20
293
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto receiverType = str::trim_copy(line.substr(20, 20));
294
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto receiverVersion = str::trim_copy(line.substr(40, 20));
295
5/6
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 35 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
49 if (!receiverNumber.empty() || !receiverType.empty() || !receiverVersion.empty())
296 {
297 LOG_DATA("{}: RecNum '{}', recType '{}', recVersion '{}'", nameId(),
298 receiverNumber, receiverType, receiverVersion);
299 }
300 49 }
301
3/4
✓ Branch 1 taken 1115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 1066 times.
1115 else if (headerLabel == "ANT # / TYPE")
302 {
303
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto antennaNumber = str::trim_copy(line.substr(0, 20)); // FORMAT: 2A20
304
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 auto antennaType = str::trim_copy(line.substr(20, 20));
305
4/4
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 32 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 14 times.
49 if (!antennaNumber.empty() || !antennaType.empty())
306 {
307 LOG_DATA("{}: antNum '{}', antType '{}'", nameId(), antennaNumber, antennaType);
308 }
309
5/8
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 35 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 49 times.
✗ Branch 9 not taken.
49 if (!antennaType.empty() || antennaType != "Unknown")
310 {
311
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 _receiverInfo.antennaType = antennaType;
312 }
313 49 }
314
3/4
✓ Branch 1 taken 1067 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 1023 times.
1066 else if (headerLabel == "APPROX POSITION XYZ")
315 {
316 // Geocentric approximate marker position (Units: Meters, System: ITRS recommended)
317 // Optional for moving platforms
318
3/6
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
88 Eigen::Vector3d position_xyz{ std::stod(str::trim_copy(line.substr(0, 14))),
319
3/6
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
87 std::stod(str::trim_copy(line.substr(14, 14))),
320
4/8
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 44 times.
✗ Branch 11 not taken.
44 std::stod(str::trim_copy(line.substr(28, 14))) }; // FORMAT: 3F14.4
321
322 LOG_DATA("{}: Approx Position XYZ: {} (not used yet)", nameId(), position_xyz.transpose());
323
324
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
43 _receiverInfo.e_approxPos = position_xyz;
325 }
326
3/4
✓ Branch 1 taken 1018 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 970 times.
1023 else if (headerLabel == "ANTENNA: DELTA H/E/N")
327 {
328 // Antenna height: Height of the antenna reference point (ARP) above the marker [m]
329
3/6
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
48 double antennaHeight = std::stod(str::trim_copy(line.substr(0, 14))); // FORMAT: F14.4,
330 // Horizontal eccentricity of ARP relative to the marker (east) [m]
331
3/6
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
48 double antennaEccentricityEast = std::stod(str::trim_copy(line.substr(14, 14))); // FORMAT: 2F14.4,
332 // Horizontal eccentricity of ARP relative to the marker (north) [m]
333
3/6
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
48 double antennaEccentricityNorth = std::stod(str::trim_copy(line.substr(28, 14)));
334
335 LOG_DATA("{}: Antenna delta H/E/N: {}, {}, {} (not used yet)", nameId(),
336 antennaHeight, antennaEccentricityEast, antennaEccentricityNorth);
337
338
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 _receiverInfo.antennaDeltaNEU = Eigen::Vector3d(antennaEccentricityNorth, antennaEccentricityEast, antennaHeight);
339 }
340
3/4
✓ Branch 1 taken 971 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 970 times.
970 else if (headerLabel == "ANTENNA: DELTA X/Y/Z")
341 {
342 // Position of antenna reference point for antenna on vehicle (m): XYZ vector in body-fixed coordinate system
343
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
2 [[maybe_unused]] Eigen::Vector3d antennaDeltaXYZ{ std::stod(str::trim_copy(line.substr(0, 14))),
344
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
2 std::stod(str::trim_copy(line.substr(14, 14))),
345
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 std::stod(str::trim_copy(line.substr(28, 14))) }; // FORMAT: 3F14.4
346
347 LOG_DATA("{}: Antenna Delta XYZ: {} (not used yet)", nameId(), antennaDeltaXYZ.transpose());
348 }
349
2/4
✓ Branch 1 taken 969 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 969 times.
✗ Branch 4 not taken.
970 else if (headerLabel == "ANTENNA: PHASECENTER")
350 {
351 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "ANTENNA: PHASECENTER");
352 }
353
2/4
✓ Branch 1 taken 971 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 971 times.
✗ Branch 4 not taken.
969 else if (headerLabel == "ANTENNA: B.SIGHT XYZ")
354 {
355 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "ANTENNA: B.SIGHT XYZ");
356 }
357
2/4
✓ Branch 1 taken 972 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 972 times.
✗ Branch 4 not taken.
971 else if (headerLabel == "ANTENNA: ZERODIR AZI")
358 {
359 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "ANTENNA: ZERODIR AZI");
360 }
361
2/4
✓ Branch 1 taken 972 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 972 times.
✗ Branch 4 not taken.
972 else if (headerLabel == "ANTENNA: ZERODIR XYZ")
362 {
363 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "ANTENNA: ZERODIR XYZ");
364 }
365
2/4
✓ Branch 1 taken 973 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 973 times.
✗ Branch 4 not taken.
972 else if (headerLabel == "CENTER OF MASS: XYZ")
366 {
367 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "CENTER OF MASS: XYZ");
368 }
369
3/4
✓ Branch 1 taken 972 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 225 times.
✓ Branch 4 taken 747 times.
973 else if (headerLabel == "SYS / # / OBS TYPES")
370 {
371 // Satellite system code (G/R/E/J/C/I/S) - FORMAT: A1,
372
2/4
✓ Branch 1 taken 226 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 225 times.
✗ Branch 5 not taken.
225 auto satSys = SatelliteSystem::fromChar(line.at(0));
373
374 // Number of different observation types for the specified satellite system - Format: 2X,I3,
375
2/4
✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 221 times.
✗ Branch 5 not taken.
225 size_t numSpecifications = std::stoul(line.substr(3, 3));
376
377 223 std::string debugOutput;
378
2/2
✓ Branch 0 taken 2837 times.
✓ Branch 1 taken 225 times.
3062 for (size_t n = 0, nLine = 1, i = 7; n < numSpecifications; n++, nLine++, i += 4)
379 {
380 // Observation descriptors: Type, Band, Attribute - FORMAT 13(1X,A3)
381
382
2/4
✓ Branch 1 taken 2839 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2845 times.
✗ Branch 5 not taken.
2837 NAV::vendor::RINEX::ObsType type = NAV::vendor::RINEX::obsTypeFromChar(line.at(i));
383
2/4
✓ Branch 1 taken 2834 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2840 times.
✗ Branch 5 not taken.
2845 Frequency freq = NAV::vendor::RINEX::getFrequencyFromBand(satSys, line.at(i + 1) - '0');
384
1/2
✓ Branch 1 taken 2836 times.
✗ Branch 2 not taken.
2840 auto attribute = line.at(i + 2);
385
4/6
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 2801 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2849 times.
2836 if (freq == B01 && attribute == 'I') { freq = B02; }
386
1/2
✓ Branch 1 taken 2840 times.
✗ Branch 2 not taken.
2849 Code code = Code::fromFreqAttr(freq, attribute);
387
388
2/4
✓ Branch 1 taken 2834 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2833 times.
✗ Branch 5 not taken.
2840 _obsDescription[satSys].push_back(NAV::vendor::RINEX::ObservationDescription{ .type = type, .code = code });
389
390
3/6
✓ Branch 1 taken 2835 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2853 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2845 times.
✗ Branch 8 not taken.
2833 debugOutput += fmt::format("({},{},{})", NAV::vendor::RINEX::obsTypeToChar(type), freq, code);
391
392
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 2741 times.
2839 if (nLine == 13)
393 {
394
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
98 getline(line);
395 100 nLine = 0;
396 100 i = 3;
397 }
398 }
399
400 LOG_DATA("{}: Obs Type {} with {} specifications [{}]", nameId(),
401 satSys, numSpecifications, debugOutput);
402 225 }
403
3/4
✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 721 times.
✓ Branch 4 taken 27 times.
747 else if (headerLabel == "SIGNAL STRENGTH UNIT")
404 {
405 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "SIGNAL STRENGTH UNIT");
406 }
407
3/4
✓ Branch 1 taken 721 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 686 times.
✓ Branch 4 taken 35 times.
721 else if (headerLabel == "INTERVAL")
408 {
409 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "INTERVAL");
410 }
411
3/4
✓ Branch 1 taken 686 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 637 times.
686 else if (headerLabel == "TIME OF FIRST OBS")
412 {
413
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 [[maybe_unused]] auto year = std::stoi(line.substr(0, 6));
414
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
49 [[maybe_unused]] auto month = std::stoi(line.substr(6, 6));
415
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
48 [[maybe_unused]] auto day = std::stoi(line.substr(12, 6));
416
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 [[maybe_unused]] auto hour = std::stoi(line.substr(18, 6));
417
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 [[maybe_unused]] auto min = std::stoi(line.substr(24, 6));
418
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 [[maybe_unused]] auto sec = std::stold(line.substr(30, 13));
419
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 _timeSystem = TimeSystem::fromString(line.substr(30 + 13 + 5, 3));
420 LOG_DATA("{}: Time of first obs: {} GPST (originally in '{}' time)", nameId(),
421 InsTime{ static_cast<uint16_t>(year),
422 static_cast<uint16_t>(month),
423 static_cast<uint16_t>(day),
424 static_cast<uint16_t>(hour),
425 static_cast<uint16_t>(min),
426 sec,
427 _timeSystem }
428 .toYMDHMS(GPST),
429 std::string(_timeSystem));
430 }
431
3/4
✓ Branch 1 taken 637 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 598 times.
✓ Branch 4 taken 39 times.
637 else if (headerLabel == "TIME OF LAST OBS")
432 {
433 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "TIME OF LAST OBS");
434 }
435
2/4
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 598 times.
598 else if (headerLabel == "RCV CLOCK OFFS APPL")
436 {
437 if (str::stoi(line.substr(0, 6), 0))
438 {
439 _rcvClockOffsAppl = true;
440 LOG_INFO("{}: Data (epoch, pseudorange, phase) corrected by the reported clock offset.", nameId());
441 }
442 LOG_TRACE("{}: Receiver clock offset applies: {}", nameId(), _rcvClockOffsAppl);
443 }
444
2/4
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 598 times.
✗ Branch 4 not taken.
598 else if (headerLabel == "SYS / DCBS APPLIED")
445 {
446 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "SYS / DCBS APPLIED");
447 }
448
2/4
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 598 times.
✗ Branch 4 not taken.
598 else if (headerLabel == "SYS / PCVS APPLIED")
449 {
450 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "SYS / PCVS APPLIED");
451 }
452
2/4
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 598 times.
✗ Branch 4 not taken.
598 else if (headerLabel == "SYS / SCALE FACTOR")
453 {
454 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "SYS / SCALE FACTOR");
455 }
456
3/4
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 181 times.
✓ Branch 4 taken 417 times.
598 else if (headerLabel == "SYS / PHASE SHIFT")
457 {
458 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "SYS / PHASE SHIFT");
459 }
460
3/4
✓ Branch 1 taken 181 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 52 times.
181 else if (headerLabel == "GLONASS SLOT / FRQ #")
461 {
462 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "GLONASS SLOT / FRQ #");
463 }
464
3/4
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 40 times.
129 else if (headerLabel == "GLONASS COD/PHS/BIS")
465 {
466 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "GLONASS COD/PHS/BIS");
467 }
468
3/4
✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 20 times.
89 else if (headerLabel == "LEAP SECONDS")
469 {
470 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "LEAP SECONDS");
471 }
472
3/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 20 times.
69 else if (headerLabel == "# OF SATELLITES")
473 {
474 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "# OF SATELLITES");
475 }
476
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
49 else if (headerLabel == "PRN / # OF OBS")
477 {
478 LOG_TRACE("{}: '{}' not implemented yet", nameId(), "PRN / # OF OBS");
479 }
480
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
49 else if (headerLabel == "END OF HEADER")
481 {
482 49 break;
483 }
484 else
485 {
486 LOG_WARN("{}: Unknown header label '{}' in line '{}'", nameId(), headerLabel, line);
487 }
488 1484 }
489
490
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
50 if (_timeSystem == TimeSys_None) // If time system not set, try to apply default value
491 {
492 if (_obsDescription.size() == 1)
493 {
494 switch (SatelliteSystem_(_obsDescription.begin()->first))
495 {
496 case GPS:
497 _timeSystem = GPST;
498 break;
499 case GLO:
500 _timeSystem = GLNT;
501 break;
502 case GAL:
503 _timeSystem = UTC;
504 break;
505 case QZSS:
506 _timeSystem = QZSST;
507 break;
508 case BDS:
509 _timeSystem = BDT;
510 break;
511 case IRNSS:
512 _timeSystem = IRNSST;
513 break;
514 default:
515 LOG_CRITICAL("{}: Could not determine time system of the file because satellite system '{}' has no default.",
516 nameId(), SatelliteSystem(_obsDescription.begin()->first));
517 break;
518 }
519 }
520 else
521 {
522 LOG_CRITICAL("{}: Could not determine time system of the file.", nameId());
523 }
524 }
525 49 }
526
527 8633 std::shared_ptr<const NodeData> RinexObsFile::pollData()
528 {
529 8633 std::string line;
530
531 8633 InsTime epochTime;
532
533 // 0: OK | 1: power failure between previous and current epoch | > 1 : Special event
534 8633 int epochFlag = -1;
535 8633 size_t nSatellites = 0;
536
10/14
✓ Branch 0 taken 8632 times.
✓ Branch 1 taken 8585 times.
✓ Branch 3 taken 8632 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8583 times.
✓ Branch 6 taken 49 times.
✓ Branch 8 taken 8584 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 8584 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8584 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 8584 times.
✓ Branch 16 taken 8634 times.
17217 while (epochFlag != 0 && !eof() && getline(line)) // Read lines till epoch record with valid epoch flag
537 {
538
1/2
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
8584 str::trim(line);
539
540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8584 times.
8584 if (line.empty())
541 {
542 continue;
543 }
544
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8584 times.
✗ Branch 4 not taken.
8584 if (line.at(0) == '>') // EPOCH record - Record identifier: > - Format: A1,
545 {
546
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto year = std::stoi(line.substr(2, 4)); // Format: 1X,I4,
547
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto month = std::stoi(line.substr(7, 2)); // Format: 1X,I2.2,
548
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto day = std::stoi(line.substr(10, 2)); // Format: 1X,I2.2,
549
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto hour = std::stoi(line.substr(13, 2)); // Format: 1X,I2.2,
550
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto min = std::stoi(line.substr(16, 2)); // Format: 1X,I2.2,
551
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 auto sec = std::stold(line.substr(18, 11)); // Format: F11.7,2X,I1,
552
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 nSatellites = std::stoul(line.substr(29 + 3, 3)); // Format: I3,6X,F15.12
553
554 8584 [[maybe_unused]] double recClkOffset = 0.0;
555 try
556 {
557
6/10
✓ Branch 1 taken 1450 times.
✓ Branch 2 taken 7133 times.
✓ Branch 4 taken 1450 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1450 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1450 times.
✓ Branch 10 taken 7133 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
8584 recClkOffset = line.size() >= 41 + 3 ? std::stod(line.substr(41, 15)) : 0.0; // Format: F15.12
558 }
559 catch (const std::exception& /* exception */)
560 {
561 LOG_DATA("{}: 'recClkOffset' not mentioned in file --> recClkOffset = {}", nameId(), recClkOffset);
562 }
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8583 times.
8583 if (_rcvClockOffsAppl)
564 {
565 sec -= recClkOffset;
566 }
567
568
1/2
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
8583 epochTime = InsTime{ static_cast<uint16_t>(year), static_cast<uint16_t>(month), static_cast<uint16_t>(day),
569 static_cast<uint16_t>(hour), static_cast<uint16_t>(min), sec,
570 _timeSystem };
571
572
2/4
✓ Branch 1 taken 8584 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8584 times.
✗ Branch 5 not taken.
8584 epochFlag = std::stoi(line.substr(31, 1)); // Format: 2X,I1,
573
574 LOG_DATA("{}: {}, epochFlag {}, numSats {}, recClkOffset {}", nameId(),
575 epochTime.toYMDHMS(), epochFlag, nSatellites, recClkOffset);
576 }
577 }
578
2/2
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 8584 times.
8634 if (epochTime.empty())
579 {
580 49 return nullptr;
581 }
582
583
1/2
✓ Branch 1 taken 8583 times.
✗ Branch 2 not taken.
8584 auto gnssObs = std::make_shared<GnssObs>();
584 8583 gnssObs->insTime = epochTime;
585
586 // TODO: while loop till eof() or epochFlag == 0 (in case some other flags in the file)
587
588 8582 size_t satCnt = 0;
589
12/16
✓ Branch 1 taken 275490 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 275486 times.
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 275481 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 266947 times.
✓ Branch 9 taken 8534 times.
✓ Branch 11 taken 266941 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 266942 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 266898 times.
✓ Branch 17 taken 44 times.
✓ Branch 18 taken 266897 times.
✓ Branch 19 taken 8583 times.
275487 while (!eof() && peek() != '>' && getline(line)) // Read observation records till line with '>'
590 {
591
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 266899 times.
266897 if (line.empty())
592 {
593 continue;
594 }
595
2/4
✓ Branch 1 taken 266899 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 266899 times.
✗ Branch 5 not taken.
266899 auto satSys = SatelliteSystem::fromChar(line.at(0)); // Format: A1,
596
2/4
✓ Branch 1 taken 266878 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 266882 times.
✗ Branch 5 not taken.
266899 auto satNum = static_cast<uint8_t>(std::stoi(line.substr(1, 2))); // Format: I2.2,
597
598 LOG_DATA("{}: [{}] {}{}:", nameId(), gnssObs->insTime.toYMDHMS(GPST), char(satSys), satNum);
599
600 266883 size_t curExtractLoc = 3;
601
3/4
✓ Branch 1 taken 266893 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2698946 times.
✓ Branch 9 taken 251302 times.
2950462 for (const auto& obsDesc : _obsDescription.at(satSys))
602 {
603
2/2
✓ Branch 1 taken 15396 times.
✓ Branch 2 taken 2683395 times.
2698837 if (line.size() < curExtractLoc + 14) // Remaining elements are all blank
604 {
605 15396 break;
606 }
607
608
2/4
✓ Branch 1 taken 2682888 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2682251 times.
✗ Branch 5 not taken.
2683395 auto strObs = str::trim_copy(line.substr(curExtractLoc, 14)); // Format: F14.3
609 2682442 curExtractLoc += 14;
610
2/2
✓ Branch 1 taken 368419 times.
✓ Branch 2 taken 2314397 times.
2682442 if (strObs.empty())
611 {
612 368419 curExtractLoc += 2;
613 368419 continue;
614 }
615 // Observation value depending on definition type
616 2314397 double observation{};
617 try
618 {
619
1/2
✓ Branch 1 taken 2315079 times.
✗ Branch 2 not taken.
2314397 observation = std::stod(strObs);
620 }
621 catch (const std::exception& e)
622 {
623 if ((*gnssObs)({ obsDesc.code, satNum }).pseudorange)
624 {
625 if (obsDesc.type == NAV::vendor::RINEX::ObsType::L) // Phase
626 {
627 LOG_WARN("{}: observation of satSys = {} contains no carrier phase. This happens if the CN0 is so small that the PLL could not lock, even if the DLL has locked (= pseudorange available). The observation is still valid.", nameId(), char(satSys));
628 }
629 else if (obsDesc.type == NAV::vendor::RINEX::ObsType::D) // Doppler
630 {
631 LOG_WARN("{}: observation of satSys = {} contains no doppler.", nameId(), char(satSys));
632 }
633 }
634 continue;
635 }
636
637 // TODO: Springer Handbook of Global Navigation, p. 1211 prefer attributes over others and let user decide also which ones to take into the calculation
638
639 // Loss of lock indicator
640 // Bit 0 set: Lost lock between previous and current observation: Cycle slip possible.
641 // For phase observations only. Note: Bit 0 is the least significant bit.
642 // Bit 1 set: Half-cycle ambiguity/slip possible. Software not capable of handling half
643 // cycles should skip this observation. Valid for the current epoch only.
644 // Bit 2 set: Galileo BOC-tracking of an MBOC-modulated signal (may suffer from increased noise).
645 2315079 uint8_t LLI = 0;
646
2/2
✓ Branch 1 taken 2267489 times.
✓ Branch 2 taken 47520 times.
2315079 if (line.size() > curExtractLoc)
647 {
648
1/2
✓ Branch 1 taken 2267425 times.
✗ Branch 2 not taken.
2267489 char LLIc = line.at(curExtractLoc);
649
2/2
✓ Branch 0 taken 2200037 times.
✓ Branch 1 taken 67388 times.
2267425 if (LLIc == ' ')
650 {
651 2200037 LLIc = '0';
652 }
653 2267425 LLI = static_cast<uint8_t>(LLIc - '0');
654 }
655 2314945 curExtractLoc++; // Go over Loss of lock indicator (LLI)
656
657 // Signal Strength Indicator (SSI)
658 //
659 // Carrier to Noise ratio(RINEX) | Carrier to Noise ratio(dbHz)
660 // 1 (minimum possible signal strength) | < 12
661 // 2 | 12-17
662 // 3 | 18-23
663 // 4 | 24-29
664 // 5 (average/good S/N ratio) | 30-35
665 // 6 | 36-41
666 // 7 | 42-47
667 // 8 | 48-53
668 // 9 (maximum possible signal strength) | ≥ 54
669 // 0 or blank: not known, don't care | -
670 2314945 uint8_t SSI = 0;
671
2/2
✓ Branch 1 taken 2267328 times.
✓ Branch 2 taken 47545 times.
2314945 if (line.size() > curExtractLoc)
672 {
673
1/2
✓ Branch 1 taken 2267436 times.
✗ Branch 2 not taken.
2267328 char SSIc = line.at(curExtractLoc);
674
2/2
✓ Branch 0 taken 885732 times.
✓ Branch 1 taken 1381704 times.
2267436 if (SSIc == ' ')
675 {
676 885732 SSIc = '0';
677 }
678 2267436 SSI = static_cast<uint8_t>(SSIc - '0');
679 }
680 2314981 curExtractLoc++; // Go over Signal Strength Indicator (SSI)
681
682
4/6
✓ Branch 0 taken 610401 times.
✓ Branch 1 taken 591286 times.
✓ Branch 2 taken 503369 times.
✓ Branch 3 taken 610421 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2314981 switch (obsDesc.type)
683 {
684 610401 case NAV::vendor::RINEX::ObsType::C: // Code / Pseudorange
685
1/2
✓ Branch 2 taken 610419 times.
✗ Branch 3 not taken.
610387 (*gnssObs)({ obsDesc.code, satNum }).pseudorange = { .value = observation,
686 1220820 .SSI = SSI };
687 610403 break;
688 591286 case NAV::vendor::RINEX::ObsType::L: // Phase
689
1/2
✓ Branch 2 taken 591298 times.
✗ Branch 3 not taken.
591280 (*gnssObs)({ obsDesc.code, satNum }).carrierPhase = { .value = observation,
690 .SSI = SSI,
691 1182584 .LLI = LLI };
692 591285 break;
693 503369 case NAV::vendor::RINEX::ObsType::D: // Doppler
694
1/2
✓ Branch 4 taken 503372 times.
✗ Branch 5 not taken.
503369 (*gnssObs)({ obsDesc.code, satNum }).doppler = observation;
695 503372 break;
696 610421 case NAV::vendor::RINEX::ObsType::S: // Raw signal strength(carrier to noise ratio)
697
1/2
✓ Branch 4 taken 610434 times.
✗ Branch 5 not taken.
610421 (*gnssObs)({ obsDesc.code, satNum }).CN0 = observation;
698 610434 break;
699 case NAV::vendor::RINEX::ObsType::I:
700 case NAV::vendor::RINEX::ObsType::X:
701 case NAV::vendor::RINEX::ObsType::Error:
702 LOG_WARN("{}: ObsType {} not supported", nameId(), size_t(obsDesc.type));
703 break;
704 }
705
706
2/4
✓ Branch 1 taken 2315221 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2315240 times.
✗ Branch 7 not taken.
2314998 gnssObs->satData(SatId{ satSys, satNum }).frequencies |= obsDesc.code.getFrequency();
707
708 LOG_DATA("{}: {}-{}-{}: {}, LLI {}, SSI {}", nameId(),
709 NAV::vendor::RINEX::obsTypeToChar(obsDesc.type), obsDesc.code, satNum,
710 observation, LLI, SSI);
711
712
4/6
✓ Branch 0 taken 2315241 times.
✓ Branch 1 taken 13 times.
✓ Branch 3 taken 2315173 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2315285 times.
✗ Branch 7 not taken.
2315254 if (_eraseLessPreciseCodes) { eraseLessPreciseCodes(gnssObs, obsDesc.code.getFrequency(), satNum); }
713 2683717 }
714
715
2/2
✓ Branch 3 taken 266803 times.
✓ Branch 4 taken 99 times.
266698 if (gnssObs->data.back().pseudorange)
716 {
717 266803 if (!gnssObs->data.back().carrierPhase)
718 {
719 LOG_DATA("{}: A data record at epoch {} (plus leap seconds) contains Pseudorange, but is missing carrier phase.", nameId(), epochTime.toYMDHMS());
720 }
721 266804 if (!gnssObs->data.back().doppler)
722 {
723 LOG_DATA("{}: A data record at epoch {} (plus leap seconds) contains Pseudorange, but is missing doppler.", nameId(), epochTime.toYMDHMS());
724 }
725 266805 if (!gnssObs->data.back().CN0)
726 {
727 LOG_DATA("{}: A data record at epoch {} (plus leap seconds) contains Pseudorange, but is missing raw signal strength(carrier to noise ratio).", nameId(), epochTime.toYMDHMS());
728 }
729 }
730 266905 satCnt++;
731 }
732
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 8490 times.
8583 if (satCnt != nSatellites)
733 {
734
4/8
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 93 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 93 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 93 times.
✗ Branch 14 not taken.
93 LOG_WARN("{}: [{}] {} satellites read, but epoch header specified {} satellites", nameId(), gnssObs->insTime.toYMDHMS(GPST), satCnt, nSatellites);
735 }
736
737 8583 gnssObs->receiverInfo = _receiverInfo;
738
739
1/2
✓ Branch 2 taken 8584 times.
✗ Branch 3 not taken.
8584 invokeCallbacks(OUTPUT_PORT_INDEX_GNSS_OBS, gnssObs);
740 8584 return gnssObs;
741 8633 }
742
743 2315158 void RinexObsFile::eraseLessPreciseCodes(const std::shared_ptr<NAV::GnssObs>& gnssObs, const Frequency& freq, uint16_t satNum) // NOLINT(readability-convert-member-functions-to-static)
744 {
745 9749597 auto eraseLessPrecise = [&](const Code& third, const Code& second, const Code& prime) {
746 3551945 auto eraseSatDataWithCode = [&](const Code& code) {
747 LOG_DATA("{}: Searching for {}-{}", nameId(), code, satNum);
748
1/2
✓ Branch 2 taken 3551803 times.
✗ Branch 3 not taken.
3551945 auto iter = std::ranges::find_if(gnssObs->data, [code, satNum](const GnssObs::ObservationData& idData) {
749
1/2
✓ Branch 2 taken 185357342 times.
✗ Branch 3 not taken.
184941348 return idData.satSigId == SatSigId{ code, satNum };
750 });
751
2/2
✓ Branch 3 taken 47003 times.
✓ Branch 4 taken 3504796 times.
3551803 if (iter != gnssObs->data.end())
752 {
753 LOG_DATA("{}: Erasing {}-{}", nameId(), code, satNum);
754
1/2
✓ Branch 3 taken 47003 times.
✗ Branch 4 not taken.
47003 gnssObs->data.erase(iter);
755 }
756 3551799 };
757
758
3/4
✓ Branch 3 taken 9751706 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1344342 times.
✓ Branch 6 taken 8407364 times.
9749597 if (gnssObs->contains({ prime, satNum }))
759 {
760
1/2
✓ Branch 1 taken 1344338 times.
✗ Branch 2 not taken.
1344342 eraseSatDataWithCode(second);
761
1/2
✓ Branch 1 taken 1344329 times.
✗ Branch 2 not taken.
1344338 eraseSatDataWithCode(third);
762 }
763
3/4
✓ Branch 3 taken 8407631 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 863493 times.
✓ Branch 6 taken 7544138 times.
8407364 else if (gnssObs->contains({ second, satNum }))
764 {
765
1/2
✓ Branch 1 taken 863472 times.
✗ Branch 2 not taken.
863493 eraseSatDataWithCode(third);
766 }
767 9751939 };
768
769
8/11
✓ Branch 1 taken 2314857 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 761760 times.
✓ Branch 5 taken 815051 times.
✓ Branch 6 taken 376151 times.
✓ Branch 7 taken 286550 times.
✓ Branch 8 taken 45204 times.
✓ Branch 9 taken 4712 times.
✓ Branch 10 taken 25916 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
2315158 switch (SatelliteSystem_(freq.getSatSys()))
770 {
771 761760 case GPS:
772
4/8
✓ Branch 1 taken 761750 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 761762 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 761812 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 761879 times.
✗ Branch 11 not taken.
761760 eraseLessPrecise(Code::G1S, Code::G1L, Code::G1X); ///< L1C (data, pilot, combined)
773
4/8
✓ Branch 1 taken 761863 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 761873 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 761877 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 761887 times.
✗ Branch 11 not taken.
761879 eraseLessPrecise(Code::G2S, Code::G2L, Code::G2X); ///< L2C-code (medium, long, combined)
774
4/8
✓ Branch 1 taken 761884 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 761884 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 761889 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 761875 times.
✗ Branch 11 not taken.
761887 eraseLessPrecise(Code::G5I, Code::G5Q, Code::G5X); ///< L5 (data, pilot, combined)
775 761875 break;
776 815051 case GAL:
777
4/8
✓ Branch 1 taken 815044 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 815052 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 815046 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 815070 times.
✗ Branch 11 not taken.
815051 eraseLessPrecise(Code::E1B, Code::E1C, Code::E1X); ///< OS (data, pilot, combined)
778
4/8
✓ Branch 1 taken 815075 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 815065 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 815067 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 815077 times.
✗ Branch 11 not taken.
815070 eraseLessPrecise(Code::E5I, Code::E5Q, Code::E5X); ///< E5a (data, pilot, combined)
779
4/8
✓ Branch 1 taken 815059 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 815069 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 815076 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 815068 times.
✗ Branch 11 not taken.
815077 eraseLessPrecise(Code::E6B, Code::E6C, Code::E6X); ///< E6 (data, pilot, combined)
780
4/8
✓ Branch 1 taken 815064 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 815074 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 815074 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 815081 times.
✗ Branch 11 not taken.
815068 eraseLessPrecise(Code::E7I, Code::E7Q, Code::E7X); ///< E5b (data, pilot, combined)
781
4/8
✓ Branch 1 taken 815070 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 815075 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 815076 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 815066 times.
✗ Branch 11 not taken.
815081 eraseLessPrecise(Code::E8I, Code::E8Q, Code::E8X); ///< E5 AltBOC (data, pilot, combined)
782 815066 break;
783 376151 case GLO:
784
4/8
✓ Branch 1 taken 376142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 376146 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 376156 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 376181 times.
✗ Branch 11 not taken.
376151 eraseLessPrecise(Code::R3I, Code::R3Q, Code::R3X); ///< L3 (data, pilot, combined)
785
4/8
✓ Branch 1 taken 376184 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 376180 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 376185 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 376179 times.
✗ Branch 11 not taken.
376181 eraseLessPrecise(Code::R4A, Code::R4B, Code::R4X); ///< G1a (data, pilot, combined)
786
4/8
✓ Branch 1 taken 376177 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 376182 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 376180 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 376174 times.
✗ Branch 11 not taken.
376179 eraseLessPrecise(Code::R6A, Code::R6B, Code::R6X); ///< G2a (data, pilot, combined)
787 376174 break;
788 286550 case BDS:
789
4/8
✓ Branch 1 taken 286550 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286548 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286550 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286547 times.
✗ Branch 11 not taken.
286550 eraseLessPrecise(Code::B1D, Code::B1P, Code::B1X); ///< B1 (data, pilot, combined)
790
4/8
✓ Branch 1 taken 286547 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286546 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286548 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286546 times.
✗ Branch 11 not taken.
286547 eraseLessPrecise(Code::B2I, Code::B2Q, Code::B2X); ///< B1I(OS), B1Q, combined
791
4/8
✓ Branch 1 taken 286547 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286549 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286545 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286546 times.
✗ Branch 11 not taken.
286546 eraseLessPrecise(Code::B5D, Code::B5P, Code::B5X); ///< B2a (data, pilot, combined)
792
4/8
✓ Branch 1 taken 286546 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286545 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286543 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286548 times.
✗ Branch 11 not taken.
286546 eraseLessPrecise(Code::B6I, Code::B6Q, Code::B6X); ///< B3I, B3Q, combined
793
4/8
✓ Branch 1 taken 286550 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286549 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286549 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286548 times.
✗ Branch 11 not taken.
286548 eraseLessPrecise(Code::B7I, Code::B7Q, Code::B7X); ///< B2I(OS), B2Q, combined
794
4/8
✓ Branch 1 taken 286548 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286548 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286549 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286545 times.
✗ Branch 11 not taken.
286548 eraseLessPrecise(Code::B7D, Code::B7P, Code::B7Z); ///< B2b (data, pilot, combined)
795
4/8
✓ Branch 1 taken 286545 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 286548 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 286547 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 286548 times.
✗ Branch 11 not taken.
286545 eraseLessPrecise(Code::B8D, Code::B8P, Code::B8X); ///< B2 (B2a+B2b) (data, pilot, combined)
796 286548 break;
797 45204 case QZSS:
798
4/8
✓ Branch 1 taken 45204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45204 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45204 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45204 times.
✗ Branch 11 not taken.
45204 eraseLessPrecise(Code::J1S, Code::J1L, Code::J1X); ///< L1C (data, pilot, combined)
799
4/8
✓ Branch 1 taken 45204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45204 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45204 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45204 times.
✗ Branch 11 not taken.
45204 eraseLessPrecise(Code::J2S, Code::J2L, Code::J2X); ///< L2C-code (medium, long, combined)
800
4/8
✓ Branch 1 taken 45204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45204 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45204 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45204 times.
✗ Branch 11 not taken.
45204 eraseLessPrecise(Code::J5I, Code::J5Q, Code::J5X); ///< L5 (data, pilot, combined)
801
4/8
✓ Branch 1 taken 45204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45204 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45204 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45204 times.
✗ Branch 11 not taken.
45204 eraseLessPrecise(Code::J5D, Code::J5P, Code::J5Z); ///< L5 (data, pilot, combined)
802
4/8
✓ Branch 1 taken 45204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45204 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45204 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45204 times.
✗ Branch 11 not taken.
45204 eraseLessPrecise(Code::J6S, Code::J6L, Code::J6X); ///< LEX signal (short, long, combined)
803 45204 break;
804 4712 case IRNSS:
805
4/8
✓ Branch 1 taken 4712 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4712 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4712 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4712 times.
✗ Branch 11 not taken.
4712 eraseLessPrecise(Code::I5B, Code::I5C, Code::I5X); ///< RS (data, pilot, combined)
806
4/8
✓ Branch 1 taken 4712 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4712 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4712 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4712 times.
✗ Branch 11 not taken.
4712 eraseLessPrecise(Code::I9B, Code::I9C, Code::I9X); ///< RS (data, pilot, combined)
807 4712 break;
808 25916 case SBAS:
809
4/8
✓ Branch 1 taken 25916 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25916 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 25916 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 25915 times.
✗ Branch 11 not taken.
25916 eraseLessPrecise(Code::S5I, Code::S5Q, Code::S5X); ///< L5 (data, pilot, combined)
810 25915 break;
811 case SatSys_None:
812 break;
813 }
814 2315004 }
815
816 } // namespace NAV
817