0.2.0
Loading...
Searching...
No Matches
AntexReader.hpp
Go to the documentation of this file.
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
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>
33#include "util/Eigen.hpp"
34#include "util/Logger.hpp"
36#include "util/StringUtil.hpp"
37#include <Eigen/src/Core/Matrix.h>
38#include <fmt/core.h>
39
40namespace NAV
41{
42
45{
46 public:
49 {
51 Eigen::Vector3d phaseCenterOffsetToARP = Eigen::Vector3d::Zero();
52 };
53
55 struct Antenna
56 {
59 {
65 : date(date), from(from), until(until) {}
66
70
72 std::unordered_map<Frequency_, AntennaFreqInfo> freqInformation;
73 };
74
76 std::vector<AntennaInfo> antennaInfo;
77 };
78
80 static AntexReader& Get()
81 {
82 static AntexReader self;
83 return self;
84 }
85
88 {
89 if (!_antennas.empty()) { return; }
90
91 LOG_DEBUG("Reading ANTEX files started...");
92
93 auto path = flow::GetProgramRootPath() / "resources" / "gnss" / "antex";
94 if (!std::filesystem::exists(path))
95 {
96 LOG_WARN("Not reading ANTEX files because path does not exist: {}", path);
97 return;
98 }
99 for (const auto& entry : std::filesystem::directory_iterator(path))
100 {
101 if (entry.path().extension() != ".atx") { continue; }
102 LOG_DEBUG("Reading {}...", entry.path().string());
103
104 std::ifstream fs(entry.path());
105 if (!fs.good())
106 {
107 LOG_ERROR("Could not read ANTEX file: {}", entry.path().string());
108 return;
109 }
110
111 auto extHeaderLabel = [](const std::string& line) {
112 return str::trim_copy(std::string_view(line).substr(60, 20));
113 };
114
115 std::string line;
116
117 bool antenna = false;
118 std::string antennaType;
119 InsTime date;
120 InsTime validFrom;
121 InsTime validUntil;
122 Frequency_ frequency = Freq_None;
123 while (std::getline(fs, line) && !fs.eof())
124 {
125 auto label = extHeaderLabel(line);
126 if (label == "START OF ANTENNA") { antenna = true; }
127 else if (label == "END OF ANTENNA")
128 {
129 antenna = false;
130 antennaType.clear();
131 date.reset();
132 validFrom.reset();
133 validUntil.reset();
134 }
135 else if (antenna)
136 {
137 if (label == "TYPE / SERIAL NO")
138 {
139 antennaType = str::trim_copy(line.substr(0, 20));
140 // if (auto pos = antennaType.find(" ");
141 // pos != std::string::npos)
142 // {
143 // antennaType = antennaType.substr(0, pos);
144 // }
145 }
146 else if (label == "METH / BY / # / DATE")
147 {
148 // " COD/ESA 0 29-JAN-17 METH / BY / # / DATE"
149 auto strDate = line.substr(50, 10);
150 auto day = std::stoi(strDate.substr(0, 2));
151 auto strMon = strDate.substr(3, 3);
152 int mon = 0;
153 if (strMon == "JAN") { mon = 1; }
154 if (strMon == "FEB") { mon = 2; }
155 if (strMon == "MAR") { mon = 3; }
156 if (strMon == "APR") { mon = 4; }
157 if (strMon == "MAY") { mon = 5; }
158 if (strMon == "JUN") { mon = 6; }
159 if (strMon == "JUL") { mon = 7; }
160 if (strMon == "AUG") { mon = 8; }
161 if (strMon == "SEP") { mon = 9; }
162 if (strMon == "OCT") { mon = 10; }
163 if (strMon == "NOV") { mon = 11; }
164 if (strMon == "DEZ") { mon = 12; }
165 auto year = 2000 + std::stoi(strDate.substr(7, 2));
166 date = InsTime(year, mon, day, 0, 0, 0.0, GPST);
167 }
168 else if (label == "VALID FROM")
169 {
170 validFrom = InsTime(std::stoi(line.substr(0, 6)),
171 std::stoi(line.substr(6, 6)),
172 std::stoi(line.substr(12, 6)),
173 std::stoi(line.substr(18, 6)),
174 std::stoi(line.substr(24, 6)),
175 std::stod(line.substr(30, 13)),
176 GPST);
177 }
178 else if (label == "VALID UNTIL")
179 {
180 validUntil = InsTime(std::stoi(line.substr(0, 6)),
181 std::stoi(line.substr(6, 6)),
182 std::stoi(line.substr(12, 6)),
183 std::stoi(line.substr(18, 6)),
184 std::stoi(line.substr(24, 6)),
185 std::stod(line.substr(30, 13)),
186 GPST);
187 }
188 else if (label == "START OF FREQUENCY")
189 {
190 frequency = getFreqFromString(line.substr(3, 3));
191 }
192 else if (label == "END OF FREQUENCY") { frequency = Freq_None; }
193 else if (frequency != Freq_None)
194 {
195 if (label == "NORTH / EAST / UP")
196 {
197 auto& antenna = _antennas[antennaType];
198 _antennaNames.insert(antennaType);
199 auto antInfo = std::find_if(antenna.antennaInfo.begin(), antenna.antennaInfo.end(), [&](const Antenna::AntennaInfo& antInfo) {
200 return antInfo.from == validFrom && antInfo.until == validUntil;
201 });
202 if (antInfo == antenna.antennaInfo.end())
203 {
204 antenna.antennaInfo.emplace_back(date, validFrom, validUntil);
205 antInfo = antenna.antennaInfo.end() - 1;
206 }
207
208 if (antInfo->freqInformation.contains(frequency) && antInfo->date > date)
209 {
210 LOG_TRACE(" Antenna '{}' [{}]{} already exists.", antennaType, Frequency(frequency),
211 !validFrom.empty() || !validUntil.empty() ? fmt::format(" (valid [{}] - [{}])", validFrom.toYMDHMS(GPST), validUntil.toYMDHMS(GPST)) : "");
212 }
213 else
214 {
215 antInfo->freqInformation[frequency].phaseCenterOffsetToARP = Eigen::Vector3d(str::stod(line.substr(0, 10), 0.0),
216 str::stod(line.substr(10, 10), 0.0),
217 str::stod(line.substr(20, 10), 0.0))
218 * 1e-3;
219 LOG_DATA(" Adding antenna '{}' [{}]{} phaseCenterOffsetToARP: {}", antennaType, Frequency(frequency),
220 !validFrom.empty() || !validUntil.empty() ? fmt::format(" (valid [{}] - [{}])", validFrom.toYMDHMS(GPST), validUntil.toYMDHMS(GPST)) : "",
221 antInfo->freqInformation.at(frequency).phaseCenterOffsetToARP.transpose());
222 }
223 }
224 }
225 }
226 }
227 }
228 LOG_DEBUG("Reading ANTEX file finished.");
229 }
230
232 void reset()
233 {
234 _notFoundAnt.clear();
235 _notFoundFreq.clear();
236 }
237
244 template<typename ReceiverType>
245 std::optional<Eigen::Vector3d> getAntennaPhaseCenterOffsetToARP(const std::string& antennaType, Frequency_ freq, const InsTime& insTime,
246 [[maybe_unused]] ReceiverType receiver, [[maybe_unused]] const std::string& nameId)
247 {
248 if (_antennas.contains(antennaType))
249 {
250 const auto& antenna = _antennas.at(antennaType);
251
252 auto antInfo = antenna.antennaInfo.cend();
253 if (antenna.antennaInfo.size() == 1) // One element only, so take it
254 {
255 antInfo = antenna.antennaInfo.begin();
256 }
257 else // No element is not possible, so more than one here, so search for time
258 {
259 antInfo = std::find_if(antenna.antennaInfo.begin(), antenna.antennaInfo.end(), [&](const Antenna::AntennaInfo& antInfo) {
260 return (antInfo.from.empty() && antInfo.until.empty())
261 || (antInfo.from.empty() && insTime <= antInfo.until)
262 || (antInfo.until.empty() && antInfo.from <= insTime)
263 || (antInfo.from <= insTime && insTime <= antInfo.until);
264 });
265 }
266 if (antInfo == antenna.antennaInfo.end()) // None matching, so take last
267 {
268 antInfo = antenna.antennaInfo.cend() - 1;
269 }
270
271 if (antInfo->freqInformation.contains(freq))
272 {
273 return antInfo->freqInformation.at(freq).phaseCenterOffsetToARP;
274 }
275 if (!_notFoundFreq.contains(std::make_pair(antennaType, freq)))
276 {
277 LOG_WARN("{}: Cannot determine phase center offset, because antenna type '{}' is does not have frequency [{}] in the ANTEX file."
278 " 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.",
279 nameId, antennaType, Frequency(freq));
280 _notFoundFreq.insert(std::make_pair(antennaType, freq));
281 }
282 }
283 else if (!_notFoundAnt.contains(antennaType))
284 {
285 LOG_WARN("{}: Cannot determine phase center offset, because antenna type '{}' for receiver '{}' is not found in the ANTEX files.",
286 nameId, antennaType, receiver);
287 _notFoundAnt.insert(antennaType);
288 }
289
290 return std::nullopt;
291 }
292
294 const std::set<std::string>& antennas() const { return _antennaNames; };
295
296 private:
298 AntexReader() = default;
299
301 std::unordered_map<std::string, Antenna> _antennas;
302
304 std::set<std::string> _antennaNames;
305
307 std::unordered_set<std::string> _notFoundAnt;
308
310 std::unordered_set<std::pair<std::string, Frequency_>> _notFoundFreq;
311
314 static Frequency_ getFreqFromString(const std::string& str)
315 {
316 if (str == "G01") { return G01; }
317 if (str == "G02") { return G02; }
318 if (str == "G05") { return G05; }
319 if (str == "R01") { return R01; }
320 if (str == "R02") { return R02; }
321 if (str == "E01") { return E01; }
322 if (str == "E05") { return E05; }
323 if (str == "E07") { return E07; }
324 if (str == "E08") { return E08; }
325 if (str == "E06") { return E06; }
326 if (str == "C01") { return B01; }
327 if (str == "C02") { return B02; }
328 if (str == "C07") { return B07; }
329 if (str == "C06") { return B06; }
330 if (str == "J01") { return J01; }
331 if (str == "J02") { return J02; }
332 if (str == "J05") { return J05; }
333 if (str == "J06") { return J06; }
334 if (str == "S01") { return S01; }
335 if (str == "S05") { return S05; }
336
337 return Freq_None;
338 }
339};
340
341} // namespace NAV
Vector space operations.
Save/Load the Nodes.
Frequency definition for different satellite systems.
Frequency_
Enumerate for GNSS frequencies.
Definition Frequency.hpp:26
@ E07
Galileo E5b (1207.14 MHz).
Definition Frequency.hpp:34
@ J01
QZSS L1 (1575.42 MHz).
Definition Frequency.hpp:47
@ B02
Beidou B1-2 (1561.098 MHz).
Definition Frequency.hpp:42
@ S01
SBAS L1 (1575.42 MHz).
Definition Frequency.hpp:53
@ E06
Galileo E6 (1278.75 MHz).
Definition Frequency.hpp:33
@ Freq_None
None.
Definition Frequency.hpp:27
@ R02
GLONASS, "G2" (1246 MHz).
Definition Frequency.hpp:37
@ E01
Galileo, "E1" (1575.42 MHz).
Definition Frequency.hpp:31
@ B06
Beidou B3 (1268.52 MHz).
Definition Frequency.hpp:44
@ E05
Galileo E5a (1176.45 MHz).
Definition Frequency.hpp:32
@ S05
SBAS L5 (1176.45 MHz).
Definition Frequency.hpp:54
@ R01
GLONASS, "G1" (1602 MHZ).
Definition Frequency.hpp:36
@ G01
GPS L1 (1575.42 MHz).
Definition Frequency.hpp:28
@ B01
Beidou B1 (1575.42 MHz).
Definition Frequency.hpp:41
@ J05
QZSS L5 (1176.45 MHz).
Definition Frequency.hpp:49
@ J02
QZSS L2 (1227.6 MHz).
Definition Frequency.hpp:48
@ B07
Beidou B2b (1207.14 MHz).
Definition Frequency.hpp:45
@ E08
Galileo E5 (E5a + E5b) (1191.795MHz).
Definition Frequency.hpp:35
@ J06
QZSS L6 / LEX (1278.75 MHz).
Definition Frequency.hpp:50
@ G05
GPS L5 (1176.45 MHz).
Definition Frequency.hpp:30
The class is responsible for all time-related tasks.
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
Definition Logger.hpp:67
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Definition Logger.hpp:73
#define LOG_WARN
Error occurred, but a fallback option exists and program continues to work normally.
Definition Logger.hpp:71
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Utility functions for std::pair.
GNSS Satellite System.
Utility functions for working with std::strings.
Time System defintions.
@ GPST
GPS Time.
Definition TimeSystem.hpp:29
ANTEX file reader.
Definition AntexReader.hpp:45
std::optional< Eigen::Vector3d > getAntennaPhaseCenterOffsetToARP(const std::string &antennaType, Frequency_ freq, const InsTime &insTime, ReceiverType receiver, const std::string &nameId)
Get the Antenna Phase Center Offset To ARP if it is found in the ANTEX file.
Definition AntexReader.hpp:245
const std::set< std::string > & antennas() const
Antennas read from the ANTEX files.
Definition AntexReader.hpp:294
static AntexReader & Get()
Get the static Instance of the reader.
Definition AntexReader.hpp:80
void initialize()
Initialize from ANTEX file.
Definition AntexReader.hpp:87
void reset()
Reset the temporary variables.
Definition AntexReader.hpp:232
Frequency definition for different satellite systems.
Definition Frequency.hpp:59
The class is responsible for all time-related tasks.
Definition InsTime.hpp:667
constexpr InsTime_YMDHMS toYMDHMS(TimeSystem timesys=UTC, int digits=-1) const
Converts this time object into a different format.
Definition InsTime.hpp:828
constexpr bool empty() const
Checks if the Time object has a value.
Definition InsTime.hpp:1045
void reset()
Resets the InsTime object.
Definition InsTime.hpp:1051
Antenna frequency dependant information.
Definition AntexReader.hpp:49
Eigen::Vector3d phaseCenterOffsetToARP
Eccentricities of the mean antenna phase center relative to the antenna reference point (ARP)....
Definition AntexReader.hpp:51
Antenna info.
Definition AntexReader.hpp:59
AntennaInfo(const InsTime &date, const InsTime &from, const InsTime &until)
Constructor.
Definition AntexReader.hpp:64
InsTime date
Date of measurement.
Definition AntexReader.hpp:67
InsTime until
Valid until.
Definition AntexReader.hpp:69
InsTime from
Valid from.
Definition AntexReader.hpp:68
std::unordered_map< Frequency_, AntennaFreqInfo > freqInformation
Frequency dependant information.
Definition AntexReader.hpp:72
Antenna information.
Definition AntexReader.hpp:56
std::vector< AntennaInfo > antennaInfo
Antenna Information.
Definition AntexReader.hpp:76