0.5.1
Loading...
Searching...
No Matches
GnssObs.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
9/// @file GnssObs.hpp
10/// @brief GNSS Observation messages
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @date 2022-04-26
13
14#pragma once
15
16#include <cstdint>
17#include <limits>
18#include <optional>
19#include <vector>
20#include <algorithm>
21#include <Eigen/Core>
22
23#include "NodeData/NodeData.hpp"
24
28#include "util/Assert.h"
29
30namespace NAV
31{
32/// GNSS Observation message information
33class GnssObs : public NodeData
34{
35 public:
36 /// @brief Observation types
37 enum ObservationType : uint8_t
38 {
39 Pseudorange, ///< Pseudorange
40 Carrier, ///< Carrier-Phase
41 Doppler, ///< Doppler (Pseudorange rate)
43 };
44
45 /// @brief Stores the satellites observations
47 {
48 /// Pseudorange
50 {
51 /// Pseudorange measurement [m]
52 double value = 0.0;
53
54 /// @brief Signal Strength Indicator (SSI) projected into interval 1-9
55 ///
56 /// Carrier to Noise ratio(dbHz) | Carrier to Noise ratio(RINEX)
57 /// :-: | ---
58 /// - | 0 or blank: not known, don't care
59 /// < 12 | 1 (minimum possible signal strength)
60 /// 12-17 | 2
61 /// 18-23 | 3
62 /// 24-29 | 4
63 /// 30-35 | 5 (threshold for good tracking)
64 /// 36-41 | 6
65 /// 42-47 | 7
66 /// 48-53 | 8
67 /// ≥ 54 | 9 (maximum possible signal strength)
68 uint8_t SSI = 0;
69 };
70
71 /// Carrier phase
73 {
74 /// Carrier phase measurement [cycles]
75 double value = 0.0;
76
77 /// @brief Signal Strength Indicator (SSI) projected into interval 1-9
78 ///
79 /// Carrier to Noise ratio(dbHz) | Carrier to Noise ratio(RINEX)
80 /// :-: | ---
81 /// - | 0 or blank: not known, don't care
82 /// < 12 | 1 (minimum possible signal strength)
83 /// 12-17 | 2
84 /// 18-23 | 3
85 /// 24-29 | 4
86 /// 30-35 | 5 (threshold for good tracking)
87 /// 36-41 | 6
88 /// 42-47 | 7
89 /// 48-53 | 8
90 /// ≥ 54 | 9 (maximum possible signal strength)
91 uint8_t SSI = 0;
92
93 /// Loss of Lock Indicator [0...6] (only associated with the phase observation)
94 uint8_t LLI = 0;
95 };
96
97 /// @brief Constructor
98 /// @param[in] satSigId Satellite signal identifier (frequency and satellite number)
100
101#ifdef TESTING
102 /// @brief Constructor
103 /// @param[in] satSigId Satellite signal identifier (frequency and satellite number)
104 /// @param[in] pseudorange Pseudorange measurement [m] and Signal Strength Indicator (SSI)
105 /// @param[in] carrierPhase Carrier phase measurement [cycles], Signal Strength Indicator (SSI) and Loss of Lock Indicator (LLI)
106 /// @param[in] doppler Doppler measurement [Hz]
107 /// @param[in] CN0 Carrier-to-Noise density [dBHz]
109 std::optional<Pseudorange> pseudorange,
110 std::optional<CarrierPhase> carrierPhase,
111 std::optional<double> doppler,
112 std::optional<double> CN0)
117 CN0(CN0)
118 {}
119#endif
120
121 SatSigId satSigId = { Code::None, 0 }; ///< SignalId and satellite number
122 std::optional<Pseudorange> pseudorange; ///< Pseudorange measurement [m]
123 std::optional<CarrierPhase> carrierPhase; ///< Carrier phase measurement [cycles]
124 std::optional<double> doppler; ///< Doppler measurement [Hz]
125 std::optional<double> CN0; ///< Carrier-to-Noise density [dBHz]
126 };
127
128 /// @brief Useful information of the satellites
130 {
131 SatId satId; ///< Satellite identifier
132 Frequency frequencies = Freq_None; ///< Frequencies transmitted by this satellite
133 };
134
135#ifdef TESTING
136 /// Default constructor
137 GnssObs() = default;
138
139 /// @brief Constructor
140 /// @param[in] insTime Epoch time
141 /// @param[in] data Observation data
142 /// @param[in] satData Satellite data
143 GnssObs(const InsTime& insTime, std::vector<ObservationData> data, std::vector<SatelliteData> satData)
145 {
146 this->insTime = insTime;
147 }
148#endif
149 /// @brief Returns the type of the data class
150 /// @return The data type
151 [[nodiscard]] static std::string type()
152 {
153 return "GnssObs";
154 }
155
156 /// @brief Returns the type of the data class
157 /// @return The data type
158 [[nodiscard]] std::string getType() const override { return type(); }
159
160 /// @brief Returns the parent types of the data class
161 /// @return The parent data types
162 [[nodiscard]] static std::vector<std::string> parentTypes()
163 {
164 return { NodeData::type() };
165 }
166
167 /// @brief Satellite observations
168 std::vector<ObservationData> data;
169
170 /// @brief Access or insert the satellite data
171 /// @param satId Satellite identifier
172 /// @return The satellite data
174 {
175 auto iter = std::ranges::find_if(_satData, [&satId](const SatelliteData& sat) {
176 return sat.satId == satId;
177 });
178 if (iter != _satData.end())
179 {
180 return *iter;
181 }
182
183 _satData.emplace_back();
184 _satData.back().satId = satId;
185 return _satData.back();
186 }
187
188 /// @brief Access the satellite data
189 /// @param satId Satellite identifier
190 /// @return The satellite data if in the list
191 [[nodiscard]] std::optional<std::reference_wrapper<const SatelliteData>> satData(const SatId& satId) const
192 {
193 auto iter = std::ranges::find_if(_satData, [&satId](const SatelliteData& sat) {
194 return sat.satId == satId;
195 });
196 if (iter != _satData.end())
197 {
198 return *iter;
199 }
200 return std::nullopt;
201 }
202
203 /// @brief Checks if an element with the identifier exists
204 /// @param[in] satSigId Signal id
205 /// @return True if the element exists
206 [[nodiscard]] bool contains(const SatSigId& satSigId) const
207 {
208 auto iter = std::ranges::find_if(data, [&satSigId](const ObservationData& idData) {
209 return idData.satSigId == satSigId;
210 });
211 return iter != data.end();
212 }
213
214 /// @brief Return the element with the identifier or a newly constructed one if it did not exist
215 /// @param[in] satSigId Signal id
216 /// @return The element found in the observations or a newly constructed one
218 {
219 auto iter = std::ranges::find_if(data, [&satSigId](const ObservationData& idData) {
220 return idData.satSigId == satSigId;
221 });
222 if (iter != data.end())
223 {
224 return *iter;
225 }
226
227 data.emplace_back(satSigId);
228 return data.back();
229 }
230
231 /// @brief Return the element with the identifier
232 /// @param[in] satSigId Signal id
233 /// @return The element found in the observations
234 [[nodiscard]] std::optional<std::reference_wrapper<const ObservationData>> operator()(const SatSigId& satSigId) const
235 {
236 auto iter = std::ranges::find_if(data, [&satSigId](const ObservationData& idData) {
237 return idData.satSigId == satSigId;
238 });
239
240 if (iter != data.end())
241 {
242 return *iter;
243 }
244 return std::nullopt;
245 }
246
247 /// @brief Useful information of the satellites
248 [[nodiscard]] const std::vector<SatelliteData>& getSatData() const { return _satData; }
249
250 /// @brief Returns a vector of data descriptors for the dynamic data
251 [[nodiscard]] std::vector<std::string> dynamicDataDescriptors() const override
252 {
253 std::vector<std::string> descriptors;
254 descriptors.reserve(data.size() * 7);
255
256 for (const auto& obsData : data)
257 {
258 descriptors.push_back(fmt::format("{} Pseudorange [m]", obsData.satSigId));
259 descriptors.push_back(fmt::format("{} Pseudorange SSI", obsData.satSigId));
260
261 descriptors.push_back(fmt::format("{} Carrier-phase [cycles]", obsData.satSigId));
262 descriptors.push_back(fmt::format("{} Carrier-phase [m]", obsData.satSigId));
263 descriptors.push_back(fmt::format("{} Carrier-phase SSI", obsData.satSigId));
264 descriptors.push_back(fmt::format("{} Carrier-phase LLI", obsData.satSigId));
265
266 descriptors.push_back(fmt::format("{} Doppler [Hz]", obsData.satSigId));
267 descriptors.push_back(fmt::format("{} Carrier-to-Noise density [dBHz]", obsData.satSigId));
268 }
269
270 return descriptors;
271 }
272
273 /// @brief Get the value for the descriptor
274 /// @return Value if in the observation
275 [[nodiscard]] std::optional<double> getDynamicDataAt(const std::string& descriptor) const override
276 {
277 for (const auto& obsData : data)
278 {
279 if (descriptor == fmt::format("{} Pseudorange [m]", obsData.satSigId) && obsData.pseudorange)
280 {
281 return obsData.pseudorange->value;
282 }
283 if (descriptor == fmt::format("{} Pseudorange SSI", obsData.satSigId) && obsData.pseudorange)
284 {
285 return obsData.pseudorange->SSI;
286 }
287 if (descriptor == fmt::format("{} Carrier-phase [cycles]", obsData.satSigId) && obsData.carrierPhase)
288 {
289 return obsData.carrierPhase->value;
290 }
291 if (descriptor == fmt::format("{} Carrier-phase [m]", obsData.satSigId) && obsData.carrierPhase)
292 {
293 auto wavelength = InsConst::C / obsData.satSigId.freq().getFrequency(0);
294 return obsData.carrierPhase->value * wavelength;
295 }
296 if (descriptor == fmt::format("{} Carrier-phase SSI", obsData.satSigId) && obsData.carrierPhase)
297 {
298 return obsData.carrierPhase->SSI;
299 }
300 if (descriptor == fmt::format("{} Carrier-phase LLI", obsData.satSigId) && obsData.carrierPhase)
301 {
302 return obsData.carrierPhase->LLI;
303 }
304 if (descriptor == fmt::format("{} Doppler [Hz]", obsData.satSigId))
305 {
306 return obsData.doppler;
307 }
308 if (descriptor == fmt::format("{} Carrier-to-Noise density [dBHz]", obsData.satSigId))
309 {
310 return obsData.CN0;
311 }
312 }
313 return std::nullopt;
314 }
315
316 /// @brief Returns a vector of data descriptors and values for the dynamic data
317 [[nodiscard]] std::vector<std::pair<std::string, double>> getDynamicData() const override
318 {
319 std::vector<std::pair<std::string, double>> dynData;
320 dynData.reserve(data.size() * 7);
321 for (const auto& obsData : data)
322 {
323 if (obsData.pseudorange) { dynData.emplace_back(fmt::format("{} Pseudorange [m]", obsData.satSigId), obsData.pseudorange->value); }
324 if (obsData.pseudorange) { dynData.emplace_back(fmt::format("{} Pseudorange SSI", obsData.satSigId), obsData.pseudorange->SSI); }
325
326 if (obsData.carrierPhase) { dynData.emplace_back(fmt::format("{} Carrier-phase [cycles]", obsData.satSigId), obsData.carrierPhase->value); }
327 if (obsData.carrierPhase)
328 {
329 auto wavelength = InsConst::C / obsData.satSigId.freq().getFrequency(0);
330 dynData.emplace_back(fmt::format("{} Carrier-phase [m]", obsData.satSigId), obsData.carrierPhase->value * wavelength);
331 }
332 if (obsData.carrierPhase) { dynData.emplace_back(fmt::format("{} Carrier-phase SSI", obsData.satSigId), obsData.carrierPhase->SSI); }
333 if (obsData.carrierPhase) { dynData.emplace_back(fmt::format("{} Carrier-phase LLI", obsData.satSigId), obsData.carrierPhase->LLI); }
334
335 if (obsData.doppler) { dynData.emplace_back(fmt::format("{} Doppler [Hz]", obsData.satSigId), obsData.doppler.value()); }
336
337 if (obsData.CN0) { dynData.emplace_back(fmt::format("{} Carrier-to-Noise density [dBHz]", obsData.satSigId), obsData.CN0.value()); }
338 }
339 return dynData;
340 }
341
342 /// Receiver Information, e.g. from RINEX header
344 {
345 ///< Approximate receiver position in [m], e.g. from RINEX header
346 std::optional<Eigen::Vector3d> e_approxPos;
347
348 /// Antenna Type. Empty if unknown
349 std::string antennaType;
350
351 /// @brief Antenna Delta (North, East, Up) in [m]
352 ///
353 /// - Horizontal eccentricity of ARP relative to the marker (north/east)
354 /// - Height of the antenna reference point (ARP) above the marker
355 Eigen::Vector3d antennaDeltaNEU = Eigen::Vector3d::Zero();
356 };
357
358 /// Optional Receiver Information, e.g. from RINEX header
359 std::optional<std::reference_wrapper<ReceiverInfo>> receiverInfo;
360
361 private:
362 /// @brief Useful information of the satellites
363 std::vector<SatelliteData> _satData;
364};
365
366/// @brief Converts the enum to a string
367/// @param[in] obsType Enum value to convert into text
368/// @return String representation of the enum
369constexpr const char* to_string(GnssObs::ObservationType obsType)
370{
371 switch (obsType)
372 {
374 return "Pseudorange";
375 case GnssObs::Carrier:
376 return "Carrier";
377 case GnssObs::Doppler:
378 return "Doppler";
380 return "COUNT";
381 }
382 return "";
383}
384
385} // namespace NAV
386
387#ifndef DOXYGEN_IGNORE
388
389template<>
390struct fmt::formatter<NAV::GnssObs::ObservationType> : fmt::formatter<const char*>
391{
392 /// @brief Defines how to format Frequency structs
393 /// @param[in] obsType Struct to format
394 /// @param[in, out] ctx Format context
395 /// @return Output iterator
396 template<typename FormatContext>
397 auto format(const NAV::GnssObs::ObservationType& obsType, FormatContext& ctx) const
398 {
399 return fmt::formatter<const char*>::format(to_string(obsType), ctx);
400 }
401};
402
403#endif
404
405/// @brief Stream insertion operator overload
406/// @param[in, out] os Output stream object to stream the time into
407/// @param[in] obj Object to print
408/// @return Returns the output stream object in order to chain stream insertions
409std::ostream& operator<<(std::ostream& os, const NAV::GnssObs::ObservationType& obj);
Assertion helpers.
Code definitions.
Holds all Constants.
std::ostream & operator<<(std::ostream &os, const NAV::GnssObs::ObservationType &obj)
Stream insertion operator overload.
Definition GnssObs.cpp:16
Abstract NodeData Class.
Structs identifying a unique satellite.
@ None
None.
Definition Code.hpp:94
Frequency definition for different satellite systems.
Definition Frequency.hpp:59
GNSS Observation message information.
Definition GnssObs.hpp:34
ObservationType
Observation types.
Definition GnssObs.hpp:38
@ Doppler
Doppler (Pseudorange rate)
Definition GnssObs.hpp:41
@ ObservationType_COUNT
Count.
Definition GnssObs.hpp:42
@ Carrier
Carrier-Phase.
Definition GnssObs.hpp:40
@ Pseudorange
Pseudorange.
Definition GnssObs.hpp:39
std::vector< std::string > dynamicDataDescriptors() const override
Returns a vector of data descriptors for the dynamic data.
Definition GnssObs.hpp:251
std::string getType() const override
Returns the type of the data class.
Definition GnssObs.hpp:158
std::vector< std::pair< std::string, double > > getDynamicData() const override
Returns a vector of data descriptors and values for the dynamic data.
Definition GnssObs.hpp:317
std::optional< double > getDynamicDataAt(const std::string &descriptor) const override
Get the value for the descriptor.
Definition GnssObs.hpp:275
static std::string type()
Returns the type of the data class.
Definition GnssObs.hpp:151
static std::vector< std::string > parentTypes()
Returns the parent types of the data class.
Definition GnssObs.hpp:162
std::optional< std::reference_wrapper< const SatelliteData > > satData(const SatId &satId) const
Access the satellite data.
Definition GnssObs.hpp:191
bool contains(const SatSigId &satSigId) const
Checks if an element with the identifier exists.
Definition GnssObs.hpp:206
std::optional< std::reference_wrapper< ReceiverInfo > > receiverInfo
Optional Receiver Information, e.g. from RINEX header.
Definition GnssObs.hpp:359
SatelliteData & satData(const SatId &satId)
Access or insert the satellite data.
Definition GnssObs.hpp:173
ObservationData & operator()(const SatSigId &satSigId)
Return the element with the identifier or a newly constructed one if it did not exist.
Definition GnssObs.hpp:217
std::vector< SatelliteData > _satData
Useful information of the satellites.
Definition GnssObs.hpp:363
const std::vector< SatelliteData > & getSatData() const
Useful information of the satellites.
Definition GnssObs.hpp:248
std::vector< ObservationData > data
Satellite observations.
Definition GnssObs.hpp:168
std::optional< std::reference_wrapper< const ObservationData > > operator()(const SatSigId &satSigId) const
Return the element with the identifier.
Definition GnssObs.hpp:234
static constexpr double C
Speed of light [m/s].
Definition Constants.hpp:34
The class is responsible for all time-related tasks.
Definition InsTime.hpp:710
NodeData()=default
Default constructor.
static std::string type()
Returns the type of the data class.
Definition NodeData.hpp:45
InsTime insTime
Time at which the message was received.
Definition NodeData.hpp:123
@ Freq_None
None.
Definition Frequency.hpp:27
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
void move(std::vector< T > &v, size_t sourceIdx, size_t targetIdx)
Moves an element within a vector to a new position.
Definition Vector.hpp:27
uint8_t LLI
Loss of Lock Indicator [0...6] (only associated with the phase observation)
Definition GnssObs.hpp:94
double value
Carrier phase measurement [cycles].
Definition GnssObs.hpp:75
uint8_t SSI
Signal Strength Indicator (SSI) projected into interval 1-9.
Definition GnssObs.hpp:91
uint8_t SSI
Signal Strength Indicator (SSI) projected into interval 1-9.
Definition GnssObs.hpp:68
double value
Pseudorange measurement [m].
Definition GnssObs.hpp:52
Stores the satellites observations.
Definition GnssObs.hpp:47
std::optional< Pseudorange > pseudorange
Pseudorange measurement [m].
Definition GnssObs.hpp:122
std::optional< CarrierPhase > carrierPhase
Carrier phase measurement [cycles].
Definition GnssObs.hpp:123
ObservationData(const SatSigId &satSigId)
Constructor.
Definition GnssObs.hpp:99
std::optional< double > CN0
Carrier-to-Noise density [dBHz].
Definition GnssObs.hpp:125
SatSigId satSigId
SignalId and satellite number.
Definition GnssObs.hpp:121
std::optional< double > doppler
Doppler measurement [Hz].
Definition GnssObs.hpp:124
Receiver Information, e.g. from RINEX header.
Definition GnssObs.hpp:344
Eigen::Vector3d antennaDeltaNEU
Antenna Delta (North, East, Up) in [m].
Definition GnssObs.hpp:355
std::optional< Eigen::Vector3d > e_approxPos
< Approximate receiver position in [m], e.g. from RINEX header
Definition GnssObs.hpp:346
std::string antennaType
Antenna Type. Empty if unknown.
Definition GnssObs.hpp:349
Useful information of the satellites.
Definition GnssObs.hpp:130
Frequency frequencies
Frequencies transmitted by this satellite.
Definition GnssObs.hpp:132
SatId satId
Satellite identifier.
Definition GnssObs.hpp:131
Identifies a satellite (satellite system and number)
Identifies a satellite signal (satellite frequency and number)