INSTINCT Code Coverage Report


Directory: src/
File: Navigation/GNSS/Positioning/AntexReader.hpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 235 243 96.7%
Functions: 14 14 100.0%
Branches: 326 554 58.8%

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 /// @file AntexReader.hpp
10 /// @brief ANTEX file reader
11 /// @author T. Topp (topp@ins.uni-stuttgart.de)
12 /// @date 2024-05-19
13
14 #pragma once
15
16 #include <algorithm>
17 #include <cstddef>
18 #include <filesystem>
19 #include <fstream>
20 #include <mutex>
21 #include <set>
22 #include <optional>
23 #include <string>
24 #include <unordered_map>
25 #include <unordered_set>
26 #include <utility>
27 #include <vector>
28 #include "Navigation/GNSS/Core/Frequency.hpp"
29 #include "Navigation/GNSS/Core/SatelliteSystem.hpp"
30 #include "Navigation/Time/InsTime.hpp"
31 #include "Navigation/Time/TimeSystem.hpp"
32 #include "Navigation/Transformations/Units.hpp"
33 #include "internal/FlowManager.hpp"
34 #include "util/Eigen.hpp"
35 #include "util/Logger.hpp"
36 #include "util/Container/Pair.hpp"
37 #include "util/StringUtil.hpp"
38 #include <Eigen/src/Core/Matrix.h>
39 #include <fmt/core.h>
40
41 namespace NAV
42 {
43
44 /// @brief ANTEX file reader
45 class AntexReader
46 {
47 public:
48 /// Antenna frequency dependant information
49 struct AntennaFreqInfo
50 {
51 /// Eccentricities of the mean antenna phase center relative to the antenna reference point (ARP). North, east and up component in [m]
52 Eigen::Vector3d phaseCenterOffsetToARP = Eigen::Vector3d::Zero();
53 /// Phase center variation pattern independent from azimuth [mm]
54 /// - First row is zenith angle in [rad]
55 /// - Second row is the values
56 Eigen::Matrix2Xd patternAzimuthIndependent;
57 /// Phase center variation [mm]
58 /// - First row is zenith angle in [rad]
59 /// - First column is the azimuth angle in [rad]
60 Eigen::MatrixXd pattern;
61 };
62
63 /// Antenna information
64 struct Antenna
65 {
66 /// Antenna info
67 struct AntennaInfo
68 {
69 /// @brief Constructor
70 /// @param[in] date Date of measurement
71 /// @param[in] from Valid from
72 /// @param[in] until Valid until
73 73164 AntennaInfo(const InsTime& date, const InsTime& from, const InsTime& until)
74 73164 : date(date), from(from), until(until) {}
75
76 InsTime date; ///< Date of measurement
77 InsTime from; ///< Valid from
78 InsTime until; ///< Valid until
79
80 double zenithStart = 0.0; ///< Zenith start of the phase center variation pattern in [rad]
81 double zenithEnd = 0.0; ///< Zenith end of the phase center variation pattern in [rad]
82 double zenithDelta = 0.0; ///< Zenith delta of the phase center variation pattern in [rad]
83 double azimuthStart = 0.0; ///< Azimuth start of the phase center variation pattern in [rad]
84 double azimuthEnd = 0.0; ///< Azimuth end of the phase center variation pattern in [rad]
85 double azimuthDelta = 0.0; ///< Azimuth delta of the phase center variation pattern in [rad]
86
87 /// Frequency dependant information
88 std::unordered_map<Frequency_, AntennaFreqInfo> freqInformation;
89 };
90 /// Serial number
91 std::string serialNumber;
92
93 /// Antenna Information
94 std::vector<AntennaInfo> antennaInfo;
95 };
96
97 /// @brief Get the static Instance of the reader
98 83880 static AntexReader& Get()
99 {
100
3/4
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 83789 times.
✓ Branch 3 taken 91 times.
✗ Branch 4 not taken.
83880 static AntexReader self;
101 83880 return self;
102 }
103
104 /// @brief Initialize from ANTEX file
105 118 void initialize()
106 {
107
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 91 times.
118 if (!_antennas.empty()) { return; }
108
109
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 91 times.
✗ Branch 7 not taken.
182 LOG_DEBUG("Reading ANTEX files started...");
110
111
7/14
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 91 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 91 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 91 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 91 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 91 times.
✗ Branch 20 not taken.
91 auto path = flow::GetProgramRootPath() / "resources" / "gnss" / "antex";
112
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
91 if (!std::filesystem::exists(path))
113 {
114 LOG_WARN("Not reading ANTEX files because path does not exist: {}", path);
115 return;
116 }
117
4/6
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 11 taken 455 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 455 times.
✓ Branch 15 taken 91 times.
546 for (const auto& entry : std::filesystem::directory_iterator(path))
118 {
119
4/6
✓ Branch 1 taken 455 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 455 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 182 times.
✓ Branch 11 taken 273 times.
455 if (entry.path().extension() != ".atx") { continue; }
120
3/6
✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 273 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 273 times.
✗ Branch 10 not taken.
273 LOG_DEBUG("Reading {}...", entry.path().string());
121
122
1/2
✓ Branch 2 taken 273 times.
✗ Branch 3 not taken.
273 std::ifstream fs(entry.path());
123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 273 times.
273 if (!fs.good())
124 {
125 LOG_ERROR("Could not read ANTEX file: {}", entry.path().string());
126 return;
127 }
128
129 25234573 auto extHeaderLabel = [](const std::string& line) {
130
1/2
✓ Branch 2 taken 25234573 times.
✗ Branch 3 not taken.
25234573 return str::trim_copy(std::string_view(line).substr(60, 20));
131 };
132
133 273 std::string line;
134 273 size_t lineNumber = 0;
135
136 273 bool antennaStarted = false;
137 273 Antenna* antenna = nullptr;
138 273 std::vector<NAV::AntexReader::Antenna::AntennaInfo>::iterator antInfo;
139 273 std::string antennaType;
140 273 InsTime date;
141 273 InsTime validFrom;
142 273 InsTime validUntil;
143 273 Frequency_ frequency = Freq_None;
144 273 const double azimuthStart = 0.0;
145 273 const double azimuthEnd = deg2rad(360.0);
146 273 double azimuthDelta = 0.0;
147 273 double zenithStart = 0.0;
148 273 double zenithEnd = 0.0;
149 273 double zenithDelta = 0.0;
150 #if LOG_LEVEL <= LOG_LEVEL_DATA
151 bool patternLogging = false;
152 #endif
153
7/10
✓ Branch 1 taken 25234846 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25234846 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 25234573 times.
✓ Branch 7 taken 273 times.
✓ Branch 9 taken 25234573 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 25234573 times.
✓ Branch 12 taken 273 times.
25234846 while (std::getline(fs, line) && !fs.eof())
154 {
155 25234573 lineNumber++;
156
1/2
✓ Branch 1 taken 25234573 times.
✗ Branch 2 not taken.
25234573 auto label = extHeaderLabel(line);
157
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 25161227 times.
25234573 if (label == "START OF ANTENNA") { antennaStarted = true; }
158
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 25087881 times.
25161227 else if (label == "END OF ANTENNA")
159 {
160 73346 antennaStarted = false;
161 73346 antenna = nullptr;
162 73346 antInfo = {};
163 73346 antennaType.clear();
164 73346 date.reset();
165 73346 validFrom.reset();
166 73346 validUntil.reset();
167 73346 azimuthDelta = 0.0;
168 73346 zenithStart = 0.0;
169 73346 zenithEnd = 0.0;
170 73346 zenithDelta = 0.0;
171 }
172
2/2
✓ Branch 0 taken 25049661 times.
✓ Branch 1 taken 38220 times.
25087881 else if (antennaStarted)
173 {
174
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 24976315 times.
25049661 if (label == "TYPE / SERIAL NO")
175 {
176
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 antennaType = str::trim_copy(line.substr(0, 20));
177
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 std::string serialNumber = str::trim_copy(line.substr(20, 20));
178
4/6
✓ Branch 1 taken 33124 times.
✓ Branch 2 taken 40222 times.
✓ Branch 4 taken 33124 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 33124 times.
✗ Branch 8 not taken.
73346 if (!serialNumber.empty()) { antennaType += ":" + serialNumber; }
179
180
1/2
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
73346 antenna = &_antennas[antennaType];
181
1/2
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
73346 antenna->serialNumber = serialNumber;
182
1/2
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
73346 _antennaNames.insert(antennaType);
183 73346 }
184
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 24902969 times.
24976315 else if (label == "METH / BY / # / DATE")
185 {
186 // " COD/ESA 0 29-JAN-17 METH / BY / # / DATE"
187
1/2
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
73346 auto strDate = line.substr(50, 10);
188
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 auto day = std::stoi(strDate.substr(0, 2));
189
1/2
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
73346 auto strMon = strDate.substr(3, 3);
190 73346 int mon = 0;
191
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34762 times.
✓ Branch 4 taken 38584 times.
73346 if (strMon == "JAN") { mon = 1; }
192
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2184 times.
✓ Branch 4 taken 71162 times.
73346 if (strMon == "FEB") { mon = 2; }
193
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5824 times.
✓ Branch 4 taken 67522 times.
73346 if (strMon == "MAR") { mon = 3; }
194
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3458 times.
✓ Branch 4 taken 69888 times.
73346 if (strMon == "APR") { mon = 4; }
195
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5005 times.
✓ Branch 4 taken 68341 times.
73346 if (strMon == "MAY") { mon = 5; }
196
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7189 times.
✓ Branch 4 taken 66157 times.
73346 if (strMon == "JUN") { mon = 6; }
197
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1729 times.
✓ Branch 4 taken 71617 times.
73346 if (strMon == "JUL") { mon = 7; }
198
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 546 times.
✓ Branch 4 taken 72800 times.
73346 if (strMon == "AUG") { mon = 8; }
199
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4732 times.
✓ Branch 4 taken 68614 times.
73346 if (strMon == "SEP") { mon = 9; }
200
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2457 times.
✓ Branch 4 taken 70889 times.
73346 if (strMon == "OCT") { mon = 10; }
201
3/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2457 times.
✓ Branch 4 taken 70889 times.
73346 if (strMon == "NOV") { mon = 11; }
202
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 73346 times.
73346 if (strMon == "DEZ") { mon = 12; }
203
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 auto year = 2000 + std::stoi(strDate.substr(7, 2));
204
1/2
✓ Branch 2 taken 73346 times.
✗ Branch 3 not taken.
73346 date = InsTime(year, mon, day, 0, 0, 0.0, GPST);
205 73346 }
206
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 24829623 times.
24902969 else if (label == "DAZI")
207 {
208 // Increment of the azimuth: 2X,F6.1,52X
209 // 0 to 360 with increment 'DAZI' (in degrees).
210 // 360 degrees have to be divisible by 'DAZI'.
211 // Common value for 'DAZI': 5.0
212 // For non-azimuth-dependent phase center
213 // variations '0.0' has to be specified.
214 //
215 // 5.0 DAZI
216
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 azimuthDelta = deg2rad(std::stod(line.substr(2, 6)));
217 }
218
2/2
✓ Branch 2 taken 73346 times.
✓ Branch 3 taken 24756277 times.
24829623 else if (label == "ZEN1 / ZEN2 / DZEN")
219 {
220 // Receiver antenna: 2X,3F6.1,40X
221 // Definition of the grid in zenith angle:
222 // Zenith distance 'ZEN1' to 'ZEN2' with increment 'DZEN' (in degrees).
223 // 'DZEN' has to be > 0.0.
224 // 'ZEN1' and 'ZEN2' always have to be multiples of 'DZEN'.
225 // 'ZEN2' always has to be greater than 'ZEN1'.
226 // Common value for 'DZEN': 5.0
227 // Example: ' 0.0 90.0 5.0'
228 //
229 // 0.0 90.0 5.0 ZEN1 / ZEN2 / DZEN
230
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 zenithStart = deg2rad(std::stod(line.substr(2, 6)));
231
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 zenithEnd = deg2rad(std::stod(line.substr(8, 6)));
232
2/4
✓ Branch 1 taken 73346 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73346 times.
✗ Branch 5 not taken.
73346 zenithDelta = deg2rad(std::stod(line.substr(14, 6)));
233 }
234
2/2
✓ Branch 2 taken 33124 times.
✓ Branch 3 taken 24723153 times.
24756277 else if (label == "VALID FROM")
235 {
236
7/14
✓ Branch 1 taken 33124 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33124 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 33124 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 33124 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 33124 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 33124 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 33124 times.
✗ Branch 20 not taken.
132496 validFrom = InsTime(std::stoi(line.substr(0, 6)),
237
1/2
✓ Branch 1 taken 33124 times.
✗ Branch 2 not taken.
66248 std::stoi(line.substr(6, 6)),
238
1/2
✓ Branch 1 taken 33124 times.
✗ Branch 2 not taken.
66248 std::stoi(line.substr(12, 6)),
239
1/2
✓ Branch 1 taken 33124 times.
✗ Branch 2 not taken.
66248 std::stoi(line.substr(18, 6)),
240 33124 std::stoi(line.substr(24, 6)),
241
3/6
✓ Branch 1 taken 33124 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33124 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 33124 times.
✗ Branch 8 not taken.
66248 std::stod(line.substr(30, 13)),
242 33124 GPST);
243 }
244
2/2
✓ Branch 2 taken 18837 times.
✓ Branch 3 taken 24704316 times.
24723153 else if (label == "VALID UNTIL")
245 {
246
7/14
✓ Branch 1 taken 18837 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18837 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18837 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 18837 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18837 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 18837 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 18837 times.
✗ Branch 20 not taken.
75348 validUntil = InsTime(std::stoi(line.substr(0, 6)),
247
1/2
✓ Branch 1 taken 18837 times.
✗ Branch 2 not taken.
37674 std::stoi(line.substr(6, 6)),
248
1/2
✓ Branch 1 taken 18837 times.
✗ Branch 2 not taken.
37674 std::stoi(line.substr(12, 6)),
249
1/2
✓ Branch 1 taken 18837 times.
✗ Branch 2 not taken.
37674 std::stoi(line.substr(18, 6)),
250 18837 std::stoi(line.substr(24, 6)),
251
3/6
✓ Branch 1 taken 18837 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18837 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18837 times.
✗ Branch 8 not taken.
37674 std::stod(line.substr(30, 13)),
252 18837 GPST);
253 }
254
2/2
✓ Branch 2 taken 402493 times.
✓ Branch 3 taken 24301823 times.
24704316 else if (label == "START OF FREQUENCY")
255 {
256
2/4
✓ Branch 1 taken 402493 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 402493 times.
✗ Branch 5 not taken.
402493 frequency = Frequency_(Frequency::fromString(line.substr(3, 3)));
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402493 times.
402493 if (frequency == Freq_None)
258 {
259 LOG_WARN(" AntexReader: Invalid frequency [{}] in line {} of file '{}'", line.substr(3, 3), lineNumber, entry.path());
260 continue;
261 }
262
263 #if LOG_LEVEL <= LOG_LEVEL_DATA
264 patternLogging = true;
265 #endif
266
267
1/2
✓ Branch 1 taken 402493 times.
✗ Branch 2 not taken.
402493 antInfo = std::ranges::find_if(antenna->antennaInfo, [&](const Antenna::AntennaInfo& antInfo) {
268
3/4
✓ Branch 1 taken 329329 times.
✓ Branch 2 taken 34671 times.
✓ Branch 4 taken 329329 times.
✗ Branch 5 not taken.
364000 return antInfo.from == validFrom && antInfo.until == validUntil;
269 });
270
2/2
✓ Branch 2 taken 73164 times.
✓ Branch 3 taken 329329 times.
402493 if (antInfo == antenna->antennaInfo.end())
271 {
272
1/2
✓ Branch 1 taken 73164 times.
✗ Branch 2 not taken.
73164 antenna->antennaInfo.emplace_back(date, validFrom, validUntil);
273 73164 antInfo = antenna->antennaInfo.end() - 1;
274 }
275
276 402493 antInfo->zenithStart = zenithStart;
277 402493 antInfo->zenithEnd = zenithEnd;
278 402493 antInfo->zenithDelta = zenithDelta;
279 402493 antInfo->azimuthStart = azimuthStart;
280 402493 antInfo->azimuthEnd = azimuthEnd;
281 402493 antInfo->azimuthDelta = azimuthDelta;
282
283
6/10
✓ Branch 2 taken 402493 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4550 times.
✓ Branch 5 taken 397943 times.
✓ Branch 8 taken 4550 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 4550 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 402493 times.
402493 if (antInfo->freqInformation.contains(frequency) && antInfo->date > date)
284 {
285 LOG_TRACE(" Antenna '{}' [{}]{} already exists.", antennaType, Frequency(frequency),
286 !validFrom.empty() || !validUntil.empty() ? fmt::format(" (valid [{}] - [{}])", validFrom.toYMDHMS(GPST), validUntil.toYMDHMS(GPST)) : "");
287 frequency = Freq_None;
288 }
289 }
290
2/2
✓ Branch 2 taken 402493 times.
✓ Branch 3 taken 23899330 times.
24301823 else if (label == "END OF FREQUENCY") { frequency = Freq_None; }
291
2/2
✓ Branch 0 taken 23495472 times.
✓ Branch 1 taken 403858 times.
23899330 else if (frequency != Freq_None)
292 {
293
2/2
✓ Branch 2 taken 402493 times.
✓ Branch 3 taken 23092979 times.
23495472 if (label == "NORTH / EAST / UP")
294 {
295
2/4
✓ Branch 2 taken 402493 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 402493 times.
✗ Branch 7 not taken.
1207479 antInfo->freqInformation[frequency].phaseCenterOffsetToARP = Eigen::Vector3d(str::stod(line.substr(0, 10), 0.0),
296
1/2
✓ Branch 2 taken 402493 times.
✗ Branch 3 not taken.
804986 str::stod(line.substr(10, 10), 0.0),
297
1/2
✓ Branch 2 taken 402493 times.
✗ Branch 3 not taken.
804986 str::stod(line.substr(20, 10), 0.0))
298
3/6
✓ Branch 1 taken 402493 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 402493 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 402493 times.
✗ Branch 8 not taken.
1609972 * 1e-3;
299 LOG_DATA(" Adding antenna '{}' [{}]{} phaseCenterOffsetToARP: {}", antennaType, Frequency(frequency),
300 !validFrom.empty() || !validUntil.empty() ? fmt::format(" (valid [{}] - [{}])", validFrom.toYMDHMS(GPST), validUntil.toYMDHMS(GPST)) : "",
301 antInfo->freqInformation.at(frequency).phaseCenterOffsetToARP.transpose());
302 }
303
4/6
✓ Branch 1 taken 23092979 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23092979 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 402493 times.
✓ Branch 8 taken 22690486 times.
23092979 else if (line.substr(3, 5) == "NOAZI")
304 {
305 // (Values of a non- | The flag 'NOAZI' denotes a non-azimuth- | 3X,A5,mF8.2
306 // azimuth-dependent | dependent pattern that has to be |
307 // pattern) | specified in any case (also if 'DAZI' > |
308 // | 0.0). |
309 // | Phase pattern values in millimeters from |
310 // | 'ZEN1' to 'ZEN2' (with increment 'DZEN').|
311 // | All values on one line. |
312
1/2
✓ Branch 2 taken 402493 times.
✗ Branch 3 not taken.
402493 Eigen::Matrix2Xd& pattern = antInfo->freqInformation.at(frequency).patternAzimuthIndependent;
313
2/4
✓ Branch 1 taken 402493 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 402493 times.
✗ Branch 5 not taken.
402493 pattern = Eigen::Matrix2Xd::Zero(2, static_cast<int>(std::round(zenithEnd / zenithDelta)) + 1);
314
2/4
✓ Branch 1 taken 402493 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 402493 times.
✗ Branch 5 not taken.
402493 pattern.row(0).setLinSpaced(zenithStart, zenithEnd);
315
2/2
✓ Branch 1 taken 7642908 times.
✓ Branch 2 taken 402493 times.
8045401 for (int c = 0; c < pattern.cols(); c++)
316 {
317
3/6
✓ Branch 1 taken 7642908 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7642908 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7642908 times.
✗ Branch 8 not taken.
7642908 pattern(1, c) = std::stod(line.substr((static_cast<size_t>(c) + 1) * 8, 8)) * 1e-3;
318 }
319 LOG_DATA(" Adding antenna '{}' [{}] NOAZI pattern", antennaType, Frequency(frequency));
320 }
321
1/2
✓ Branch 0 taken 22690486 times.
✗ Branch 1 not taken.
22690486 else if (azimuthDelta > 0.0)
322 {
323 // (Values of an | The azimuth-dependent pattern has to be | F8.1,mF8.2
324 // azimuth-dependent | specified, if 'DAZI' > 0.0. The first |
325 // pattern) | value in each line denotes the azimuth |
326 // | angle followed by the phase pattern |
327 // | values in millimeters from 'ZEN1' to |
328 // | 'ZEN2' (with increment 'DZEN'). |
329 // | All values of one azimuth angle on one |
330 // | line. |
331
1/2
✓ Branch 2 taken 22690486 times.
✗ Branch 3 not taken.
22690486 Eigen::MatrixXd& pattern = antInfo->freqInformation.at(frequency).pattern;
332
333
2/2
✓ Branch 1 taken 304304 times.
✓ Branch 2 taken 22386182 times.
22690486 if (pattern.cols() == 0)
334 {
335 pattern = Eigen::MatrixXd::Zero(static_cast<int>(std::round(azimuthEnd / azimuthDelta)) + 2,
336
2/4
✓ Branch 1 taken 304304 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 304304 times.
✗ Branch 5 not taken.
304304 static_cast<int>(std::round(zenithEnd / zenithDelta)) + 2);
337
3/6
✓ Branch 1 taken 304304 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 304304 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 304304 times.
✗ Branch 9 not taken.
304304 pattern.row(0).rightCols(pattern.cols() - 1).setLinSpaced(zenithStart, zenithEnd);
338
3/6
✓ Branch 1 taken 304304 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 304304 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 304304 times.
✗ Branch 9 not taken.
304304 pattern.col(0).bottomRows(pattern.rows() - 1).setLinSpaced(azimuthStart, azimuthEnd);
339 }
340
2/4
✓ Branch 1 taken 22690486 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22690486 times.
✗ Branch 5 not taken.
22690486 double azimuth = deg2rad(std::stod(line.substr(0, 8)));
341 22690486 int r = static_cast<int>(std::round((azimuth - azimuthStart) / azimuthDelta)) + 1;
342
2/2
✓ Branch 1 taken 450699158 times.
✓ Branch 2 taken 22690486 times.
473389644 for (int c = 0; c < pattern.cols() - 1; c++)
343 {
344
3/6
✓ Branch 1 taken 450699158 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 450699158 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 450699158 times.
✗ Branch 8 not taken.
450699158 pattern(r, c + 1) = std::stod(line.substr((static_cast<size_t>(c) + 1) * 8, 8)) * 1e-3;
345 }
346
347 #if LOG_LEVEL <= LOG_LEVEL_DATA
348 if (patternLogging)
349 {
350 LOG_DATA(" Adding antenna '{}' [{}] azimuth dependent pattern", antennaType, Frequency(frequency));
351 patternLogging = false;
352 }
353 #endif
354 }
355 }
356 }
357 }
358 364 }
359
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 91 times.
✗ Branch 7 not taken.
182 LOG_DEBUG("Reading ANTEX file finished.");
360 91 }
361
362 /// @brief Reset the temporary variables
363 111 void reset()
364 {
365 111 _notFoundAnt.clear();
366 111 _notFoundFreq.clear();
367 111 }
368
369 /// @brief Get the Antenna Phase Center Offset To ARP if it is found in the ANTEX file
370 /// @param[in] antennaType Antenna Type
371 /// @param[in] freq Frequency
372 /// @param[in] insTime Time
373 /// @param[in] nameId NameId of the calling node for Log output
374 /// @return Phase center offset in north, east, up components in [m]
375 41808 std::optional<Eigen::Vector3d> getAntennaPhaseCenterOffsetToARP(const std::string& antennaType, Frequency_ freq, const InsTime& insTime,
376 [[maybe_unused]] const std::string& nameId) const
377 {
378
3/4
✓ Branch 1 taken 41808 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 41800 times.
41808 if (auto antFreqInfo = getAntennaFrequencyInfo(antennaType, freq, insTime, nameId))
379 {
380
1/2
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
8 return antFreqInfo->get().phaseCenterOffsetToARP;
381 }
382
383 41800 return std::nullopt;
384 }
385
386 /// @brief Gets the phase center variation for given elevation and azimuth
387 /// @param[in] antennaType Antenna Type
388 /// @param[in] freq Frequency
389 /// @param[in] insTime Time
390 /// @param[in] elevation Elevation angle in [rad]
391 /// @param[in] azimuth Azimuth in [rad] or nullopt to use the azimuth independent (NOAZI)
392 /// @param[in] nameId NameId of the calling node for Log output
393 /// @return The interpolated phase center variation in [m]
394 41817 std::optional<double> getAntennaPhaseCenterVariation(const std::string& antennaType, Frequency_ freq, const InsTime& insTime,
395 double elevation, std::optional<double> azimuth,
396 [[maybe_unused]] const std::string& nameId) const
397 {
398 LOG_DATA("{}: getAntennaPhaseCenterVariation({}, {}, {}, {}, {})", nameId, antennaType, Frequency(freq), insTime.toYMDHMS(GPST), elevation, azimuth);
399
1/2
✓ Branch 1 taken 41817 times.
✗ Branch 2 not taken.
41817 auto antInfo = getAntennaInfo(antennaType, insTime, nameId);
400
2/2
✓ Branch 1 taken 41798 times.
✓ Branch 2 taken 19 times.
41817 if (!antInfo.has_value()) { return std::nullopt; }
401
402 19 double zenith = deg2rad(90.0) - elevation;
403
404
2/2
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 2 times.
36 if (zenith < antInfo->get().zenithStart || zenith > antInfo->get().zenithEnd
405
10/10
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 4 times.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 1 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 9 times.
✓ Branch 17 taken 6 times.
✓ Branch 18 taken 13 times.
36 || (azimuth && (azimuth < antInfo->get().azimuthStart || azimuth > antInfo->get().azimuthEnd)))
406 {
407 LOG_DATA("{}: The zenith or azimuth provided are outside the pattern in the ANTEX file", nameId);
408 6 return std::nullopt;
409 }
410
1/2
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
13 auto antFreqInfo = getAntennaFrequencyInfo(antInfo->get(), antennaType, freq, nameId);
411
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (!antFreqInfo.has_value()) { return std::nullopt; }
412
413
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 9 times.
13 if (!azimuth.has_value())
414 {
415 4 const Eigen::Matrix2Xd& pattern = antFreqInfo->get().patternAzimuthIndependent;
416 4 Eigen::Index zenithLoc = -1;
417
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
4 if (zenith == pattern(0, 0)) { zenithLoc = 1; }
418
3/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
3 else if (zenith == pattern(0, Eigen::last)) { zenithLoc = pattern.cols() - 1; }
419 else
420 {
421
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
6 zenithLoc = std::distance(
422
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 pattern.row(0).begin(),
423
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 std::upper_bound(pattern.row(0).begin(),
424
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 pattern.row(0).end(),
425 zenith));
426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (zenithLoc == 0) { zenithLoc++; }
427 }
428 4 Eigen::Index uLoc = zenithLoc - 1;
429
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 double a = pattern(0, uLoc);
430
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 double b = pattern(0, zenithLoc);
431 4 double t = (zenith - a) / (b - a);
432
433 LOG_DATA("{}: t = {:.3f} [a = {:.1f}°, z = {:.1f}°, b = {:.1f}°]", nameId, t, rad2deg(a), rad2deg(zenith), rad2deg(b));
434 LOG_DATA("{}: zenith {:.1f}° at idx {} = {:.5f}", nameId, rad2deg(zenith), zenithLoc, std::lerp(pattern(1, uLoc), pattern(1, zenithLoc), t));
435
436
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 return std::lerp(pattern(1, uLoc), pattern(1, zenithLoc), t);
437 }
438
439 9 const Eigen::MatrixXd& pattern = antFreqInfo->get().pattern;
440 9 Eigen::Index zenithLoc = -1;
441 9 Eigen::Index azimuthLoc = -1;
442
3/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 7 times.
9 if (zenith == pattern(0, 1)) { zenithLoc = 2; }
443
3/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
7 else if (zenith == pattern(0, Eigen::last)) { zenithLoc = pattern.cols() - 1; }
444 else
445 {
446
4/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
15 zenithLoc = std::distance(
447
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 pattern.row(0).rightCols(pattern.cols() - 1).begin(),
448
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 std::upper_bound(pattern.row(0).rightCols(pattern.cols() - 1).begin(),
449
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 pattern.row(0).rightCols(pattern.cols() - 1).end(),
450 zenith));
451
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if (zenithLoc != pattern.cols() - 1) { zenithLoc++; }
452 }
453
3/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 6 times.
9 if (*azimuth == pattern(1, 0)) { azimuthLoc = 2; }
454
3/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
6 else if (*azimuth == pattern(Eigen::last, 0)) { azimuthLoc = pattern.rows() - 1; }
455 else
456 {
457
4/8
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
12 azimuthLoc = std::distance(
458
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 pattern.col(0).bottomRows(pattern.rows() - 1).begin(),
459
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 std::upper_bound(pattern.col(0).bottomRows(pattern.rows() - 1).begin(),
460
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 pattern.col(0).bottomRows(pattern.rows() - 1).end(),
461 4 *azimuth));
462
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (azimuthLoc != pattern.rows() - 1) { azimuthLoc++; }
463 }
464
465 9 Eigen::Index uZenithLoc = zenithLoc - 1;
466
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 double za = pattern(0, uZenithLoc);
467
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 double zb = pattern(0, zenithLoc);
468 9 double zt = (zenith - za) / (zb - za);
469 LOG_DATA("{}: zenith: t = {:.3f} [a = {:.1f}°, {:.1f}°, b = {:.1f}°]", nameId, zt, rad2deg(za), rad2deg(zenith), rad2deg(zb));
470 9 Eigen::Index uAzimuthLoc = azimuthLoc - 1;
471
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 double aa = pattern(uAzimuthLoc, 0);
472
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 double ab = pattern(azimuthLoc, 0);
473 9 double at = (*azimuth - aa) / (ab - aa);
474 LOG_DATA("{}: azimuth: t = {:.3f} [a = {:.1f}°, {:.1f}°, b = {:.1f}°]", nameId, at, rad2deg(aa), rad2deg(*azimuth), rad2deg(ab));
475
476 LOG_DATA("{}: bilinearInterpolation(tx = {:.1f}, ty = {:.1f}, c00 = {:.5f}, c10 = {:.5f}, c01 = {:.5f}, c11 = {:.5f})", nameId,
477 zt, at,
478 pattern(uAzimuthLoc, uZenithLoc), pattern(azimuthLoc, uZenithLoc),
479 pattern(uAzimuthLoc, zenithLoc), pattern(azimuthLoc, zenithLoc));
480 9 double v = math::bilinearInterpolation(at, zt,
481
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 pattern(uAzimuthLoc, uZenithLoc), pattern(azimuthLoc, uZenithLoc),
482
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
9 pattern(uAzimuthLoc, zenithLoc), pattern(azimuthLoc, zenithLoc));
483 LOG_DATA("{}: azimuth {:.1f}°, zenith {:.1f}° at idx ({},{}) = {:.5f}", nameId, rad2deg(*azimuth), rad2deg(zenith), azimuthLoc, zenithLoc, v);
484
485 9 return v;
486 }
487
488 /// Antennas read from the ANTEX files
489 1 const std::set<std::string>& antennas() const
490 {
491 1 return _antennaNames;
492 };
493
494 private:
495 /// @brief Constructor
496 91 AntexReader() = default;
497
498 /// Antennas read from the ANTEX files
499 std::unordered_map<std::string, Antenna> _antennas;
500
501 /// Ordered names of all antennas
502 std::set<std::string> _antennaNames;
503
504 /// List of Antennas not found to emit a warning
505 mutable std::unordered_set<std::string> _notFoundAnt;
506
507 /// List of Frequencies not found to emit a warning
508 mutable std::unordered_set<std::pair<std::string, Frequency_>> _notFoundFreq;
509
510 /// @brief Get the antenna info object
511 /// @param[in] antennaType Antenna Type
512 /// @param[in] insTime Time
513 /// @param[in] nameId NameId of the calling node for Log output
514 83645 std::optional<std::reference_wrapper<const Antenna::AntennaInfo>> getAntennaInfo(const std::string& antennaType, const InsTime& insTime,
515 [[maybe_unused]] const std::string& nameId) const
516 {
517
3/4
✓ Branch 1 taken 83645 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 83597 times.
✓ Branch 4 taken 48 times.
83645 if (!_antennas.contains(antennaType))
518 {
519
3/4
✓ Branch 1 taken 83597 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 83588 times.
83597 if (!_notFoundAnt.contains(antennaType))
520 {
521
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
9 LOG_WARN("{}: Antenna type '{}' is not found in the ANTEX files.",
522 nameId, antennaType);
523
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 _notFoundAnt.insert(antennaType);
524 }
525 83597 return std::nullopt;
526 }
527
528
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 const auto& antenna = _antennas.at(antennaType);
529
530 48 auto antInfo = antenna.antennaInfo.cend();
531
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 4 times.
48 if (antenna.antennaInfo.size() == 1) // One element only, so take it
532 {
533 44 antInfo = antenna.antennaInfo.begin();
534 }
535 else // No element is not possible, so more than one here, so search for time
536 {
537
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 antInfo = std::ranges::find_if(antenna.antennaInfo, [&](const Antenna::AntennaInfo& antInfo) {
538
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 return (antInfo.from.empty() && antInfo.until.empty())
539
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 || (antInfo.from.empty() && insTime <= antInfo.until)
540
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7 || (antInfo.until.empty() && antInfo.from <= insTime)
541
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 4 times.
14 || (antInfo.from <= insTime && insTime <= antInfo.until);
542 });
543 }
544
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 47 times.
48 if (antInfo == antenna.antennaInfo.end()) // None matching, so take last
545 {
546 1 antInfo = antenna.antennaInfo.cend() - 1;
547 }
548
549 48 return *antInfo;
550 }
551
552 /// @brief Get the antenna frequency info object
553 /// @param[in] antennaType Antenna Type
554 /// @param[in] freq Frequency
555 /// @param[in] insTime Time
556 /// @param[in] nameId NameId of the calling node for Log output
557 41827 std::optional<std::reference_wrapper<const AntennaFreqInfo>> getAntennaFrequencyInfo(const std::string& antennaType, Frequency_ freq,
558 const InsTime& insTime,
559 const std::string& nameId) const
560 {
561
3/4
✓ Branch 1 taken 41827 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 41799 times.
41827 if (auto antInfo = getAntennaInfo(antennaType, insTime, nameId))
562 {
563
1/2
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 return getAntennaFrequencyInfo(antInfo->get(), antennaType, freq, nameId);
564 }
565
566 41799 return std::nullopt;
567 }
568
569 /// @brief Get the antenna frequency info object
570 /// @param[in] antInfo Antenna Info object
571 /// @param[in] antennaType Antenna Type
572 /// @param[in] freq Frequency
573 /// @param[in] nameId NameId of the calling node for Log output
574 41 std::optional<std::reference_wrapper<const AntennaFreqInfo>> getAntennaFrequencyInfo(const Antenna::AntennaInfo& antInfo,
575 const std::string& antennaType, Frequency_ freq,
576 [[maybe_unused]] const std::string& nameId) const
577 {
578
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 1 times.
41 if (antInfo.freqInformation.contains(freq))
579 {
580
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 return antInfo.freqInformation.at(freq);
581 }
582
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.
1 if (!_notFoundFreq.contains(std::make_pair(antennaType, freq)))
583 {
584
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 LOG_WARN("{}: Antenna type '{}' is does not have frequency [{}] in the ANTEX file."
585 " Please provide a new ANTEX file under 'resources/gnss/antex' or consider not using the frequency, as this can introduce height errors of several centimeter.",
586 nameId, antennaType, Frequency(freq));
587
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 _notFoundFreq.insert(std::make_pair(antennaType, freq));
588 }
589
590 1 return std::nullopt;
591 }
592 };
593
594 } // namespace NAV
595