0.5.0
Loading...
Searching...
No Matches
VectorNavBinaryOutput.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 VectorNavBinaryOutput.hpp
10/// @brief Binary Outputs from VectorNav Sensors
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @date 2021-07-01
13
14#pragma once
15
16#include <cmath>
17#include <memory>
18
20#include "NodeData/NodeData.hpp"
22#include "util/Eigen.hpp"
24
31#include <fmt/core.h>
32#include <sys/types.h>
33#include <vn/types.h>
34
35namespace NAV
36{
37/// IMU Observation storage class
39{
40 public:
41 /// @brief Constructor
42 /// @param[in] imuPos Reference to the position and rotation info of the Imu
44 : imuPos(imuPos) {}
45
46 /// @brief Returns the type of the data class
47 /// @return The data type
48 [[nodiscard]] static std::string type()
49 {
50 return "VectorNavBinaryOutput";
51 }
52
53 /// @brief Returns the type of the data class
54 /// @return The data type
55 [[nodiscard]] std::string getType() const override { return type(); }
56
57 /// @brief Returns the parent types of the data class
58 /// @return The parent data types
59 [[nodiscard]] static std::vector<std::string> parentTypes()
60 {
61 return { NodeData::type() };
62 }
63
64 /// @brief Returns a vector of data descriptors
65 [[nodiscard]] static std::vector<std::string> GetStaticDataDescriptors()
66 {
67 return {};
68 }
69
70 /// @brief Get the amount of descriptors
71 [[nodiscard]] static constexpr size_t GetStaticDescriptorCount() { return 0; }
72
73 /// @brief Returns a vector of data descriptors
74 [[nodiscard]] std::vector<std::string> staticDataDescriptors() const override { return GetStaticDataDescriptors(); }
75
76 /// @brief Get the amount of descriptors
77 [[nodiscard]] size_t staticDescriptorCount() const override { return GetStaticDescriptorCount(); }
78
79 /// @brief Get the value at the index
80 /// @param idx Index corresponding to data descriptor order
81 /// @return Value if in the observation
82 [[nodiscard]] std::optional<double> getValueAt(size_t idx) const override
83 {
85 switch (idx)
86 {
87 // Group 2 (Time)
88 case 0: // Time::TimeStartup [ns]
89 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTARTUP)) { return static_cast<double>(timeOutputs->timeStartup); }
90 break;
91 case 1: // Time::TimeGps [ns]
92 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPS)) { return static_cast<double>(timeOutputs->timeGps); }
93 break;
94 case 2: // Time::GpsTow [ns]
95 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)) { return static_cast<double>(timeOutputs->gpsTow); }
96 break;
97 case 3: // Time::GpsWeek
98 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK)) { return static_cast<double>(timeOutputs->gpsWeek); }
99 break;
100 case 4: // Time::TimeSyncIn [ns]
101 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESYNCIN)) { return static_cast<double>(timeOutputs->timeSyncIn); }
102 break;
103 case 5: // Time::TimeGpsPps [ns]
104 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPSPPS)) { return static_cast<double>(timeOutputs->timePPS); }
105 break;
106 case 6: // Time::TimeUTC::year
107 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.year); }
108 break;
109 case 7: // Time::TimeUTC::month
110 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.month); }
111 break;
112 case 8: // Time::TimeUTC::day
113 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.day); }
114 break;
115 case 9: // Time::TimeUTC::hour
116 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.hour); }
117 break;
118 case 10: // Time::TimeUTC::min
119 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.min); }
120 break;
121 case 11: // Time::TimeUTC::sec
122 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.sec); }
123 break;
124 case 12: // Time::TimeUTC::ms
125 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)) { return static_cast<double>(timeOutputs->timeUtc.ms); }
126 break;
127 case 13: // Time::SyncInCnt
128 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCINCNT)) { return static_cast<double>(timeOutputs->syncInCnt); }
129 break;
130 case 14: // Time::SyncOutCnt
131 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCOUTCNT)) { return static_cast<double>(timeOutputs->syncOutCnt); }
132 break;
133 case 15: // Time::TimeStatus::timeOk
134 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)) { return static_cast<double>(timeOutputs->timeStatus.timeOk()); }
135 break;
136 case 16: // Time::TimeStatus::dateOk
137 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)) { return static_cast<double>(timeOutputs->timeStatus.dateOk()); }
138 break;
139 case 17: // Time::TimeStatus::utcTimeValid
140 if (timeOutputs && (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)) { return static_cast<double>(timeOutputs->timeStatus.utcTimeValid()); }
141 break;
142 // Group 3 (IMU)
143 case 18: // IMU::ImuStatus
144 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_IMUSTATUS)) { return static_cast<double>(imuOutputs->imuStatus); }
145 break;
146 case 19: // IMU::UncompMag::X [Gauss]
147 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)) { return static_cast<double>(imuOutputs->uncompMag(0)); }
148 break;
149 case 20: // IMU::UncompMag::Y [Gauss]
150 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)) { return static_cast<double>(imuOutputs->uncompMag(1)); }
151 break;
152 case 21: // IMU::UncompMag::Z [Gauss]
153 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)) { return static_cast<double>(imuOutputs->uncompMag(2)); }
154 break;
155 case 22: // IMU::UncompAccel::X [m/s^2]
156 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)) { return static_cast<double>(imuOutputs->uncompAccel(0)); }
157 break;
158 case 23: // IMU::UncompAccel::Y [m/s^2]
159 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)) { return static_cast<double>(imuOutputs->uncompAccel(1)); }
160 break;
161 case 24: // IMU::UncompAccel::Z [m/s^2]
162 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)) { return static_cast<double>(imuOutputs->uncompAccel(2)); }
163 break;
164 case 25: // IMU::UncompGyro::X [rad/s]
165 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)) { return static_cast<double>(imuOutputs->uncompGyro(0)); }
166 break;
167 case 26: // IMU::UncompGyro::Y [rad/s]
168 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)) { return static_cast<double>(imuOutputs->uncompGyro(1)); }
169 break;
170 case 27: // IMU::UncompGyro::Z [rad/s]
171 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)) { return static_cast<double>(imuOutputs->uncompGyro(2)); }
172 break;
173 case 28: // IMU::Temp [Celsius]
174 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)) { return static_cast<double>(imuOutputs->temp); }
175 break;
176 case 29: // IMU::Pres [kPa]
177 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)) { return static_cast<double>(imuOutputs->pres); }
178 break;
179 case 30: // IMU::DeltaTime [s]
180 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)) { return static_cast<double>(imuOutputs->deltaTime); }
181 break;
182 case 31: // IMU::DeltaTheta::X [deg]
183 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)) { return static_cast<double>(imuOutputs->deltaTheta(0)); }
184 break;
185 case 32: // IMU::DeltaTheta::Y [deg]
186 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)) { return static_cast<double>(imuOutputs->deltaTheta(1)); }
187 break;
188 case 33: // IMU::DeltaTheta::Z [deg]
189 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)) { return static_cast<double>(imuOutputs->deltaTheta(2)); }
190 break;
191 case 34: // IMU::DeltaVel::X [m/s]
192 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)) { return static_cast<double>(imuOutputs->deltaV(0)); }
193 break;
194 case 35: // IMU::DeltaVel::Y [m/s]
195 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)) { return static_cast<double>(imuOutputs->deltaV(1)); }
196 break;
197 case 36: // IMU::DeltaVel::Z [m/s]
198 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)) { return static_cast<double>(imuOutputs->deltaV(2)); }
199 break;
200 case 37: // IMU::Mag::X [Gauss]
201 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)) { return static_cast<double>(imuOutputs->mag(0)); }
202 break;
203 case 38: // IMU::Mag::Y [Gauss]
204 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)) { return static_cast<double>(imuOutputs->mag(1)); }
205 break;
206 case 39: // IMU::Mag::Z [Gauss]
207 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)) { return static_cast<double>(imuOutputs->mag(2)); }
208 break;
209 case 40: // IMU::Accel::X [m/s^2]
210 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)) { return static_cast<double>(imuOutputs->accel(0)); }
211 break;
212 case 41: // IMU::Accel::Y [m/s^2]
213 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)) { return static_cast<double>(imuOutputs->accel(1)); }
214 break;
215 case 42: // IMU::Accel::Z [m/s^2]
216 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)) { return static_cast<double>(imuOutputs->accel(2)); }
217 break;
218 case 43: // IMU::AngularRate::X [rad/s]
219 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)) { return static_cast<double>(imuOutputs->angularRate(0)); }
220 break;
221 case 44: // IMU::AngularRate::Y [rad/s]
222 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)) { return static_cast<double>(imuOutputs->angularRate(1)); }
223 break;
224 case 45: // IMU::AngularRate::Z [rad/s]
225 if (imuOutputs && (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)) { return static_cast<double>(imuOutputs->angularRate(2)); }
226 break;
227 // Group 4 (GNSS1)
228 case 46: // GNSS1::UTC::year
229 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.year); }
230 break;
231 case 47: // GNSS1::UTC::month
232 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.month); }
233 break;
234 case 48: // GNSS1::UTC::day
235 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.day); }
236 break;
237 case 49: // GNSS1::UTC::hour
238 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.hour); }
239 break;
240 case 50: // GNSS1::UTC::min
241 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.min); }
242 break;
243 case 51: // GNSS1::UTC::sec
244 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.sec); }
245 break;
246 case 52: // GNSS1::UTC::ms
247 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss1Outputs->timeUtc.ms); }
248 break;
249 case 53: // GNSS1::Tow [ns]
250 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)) { return static_cast<double>(gnss1Outputs->tow); }
251 break;
252 case 54: // GNSS1::Week
253 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)) { return static_cast<double>(gnss1Outputs->week); }
254 break;
255 case 55: // GNSS1::NumSats
256 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)) { return static_cast<double>(gnss1Outputs->numSats); }
257 break;
258 case 56: // GNSS1::Fix
259 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)) { return static_cast<double>(gnss1Outputs->fix); }
260 break;
261 case 57: // GNSS1::PosLla::latitude [deg]
262 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss1Outputs->posLla(0); }
263 break;
264 case 58: // GNSS1::PosLla::longitude [deg]
265 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss1Outputs->posLla(1); }
266 break;
267 case 59: // GNSS1::PosLla::altitude [m]
268 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss1Outputs->posLla(2); }
269 break;
270 case 60: // GNSS1::PosEcef::X [m]
271 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss1Outputs->posEcef(0); }
272 break;
273 case 61: // GNSS1::PosEcef::Y [m]
274 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss1Outputs->posEcef(1); }
275 break;
276 case 62: // GNSS1::PosEcef::Z [m]
277 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss1Outputs->posEcef(2); }
278 break;
279 case 63: // GNSS1::VelNed::N [m/s]
280 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss1Outputs->velNed(0)); }
281 break;
282 case 64: // GNSS1::VelNed::E [m/s]
283 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss1Outputs->velNed(1)); }
284 break;
285 case 65: // GNSS1::VelNed::D [m/s]
286 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss1Outputs->velNed(2)); }
287 break;
288 case 66: // GNSS1::VelEcef::X [m/s]
289 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss1Outputs->velEcef(0)); }
290 break;
291 case 67: // GNSS1::VelEcef::Y [m/s]
292 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss1Outputs->velEcef(1)); }
293 break;
294 case 68: // GNSS1::VelEcef::Z [m/s]
295 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss1Outputs->velEcef(2)); }
296 break;
297 case 69: // GNSS1::PosU::N [m]
298 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss1Outputs->posU(0)); }
299 break;
300 case 70: // GNSS1::PosU::E [m]
301 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss1Outputs->posU(1)); }
302 break;
303 case 71: // GNSS1::PosU::D [m]
304 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss1Outputs->posU(2)); }
305 break;
306 case 72: // GNSS1::VelU [m/s]
307 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)) { return static_cast<double>(gnss1Outputs->velU); }
308 break;
309 case 73: // GNSS1::TimeU [s]
310 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)) { return static_cast<double>(gnss1Outputs->timeU); }
311 break;
312 case 74: // GNSS1::TimeInfo::Status::timeOk
313 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss1Outputs->timeInfo.status.timeOk()); }
314 break;
315 case 75: // GNSS1::TimeInfo::Status::dateOk
316 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss1Outputs->timeInfo.status.dateOk()); }
317 break;
318 case 76: // GNSS1::TimeInfo::Status::utcTimeValid
319 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss1Outputs->timeInfo.status.utcTimeValid()); }
320 break;
321 case 77: // GNSS1::TimeInfo::LeapSeconds
322 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss1Outputs->timeInfo.leapSeconds); }
323 break;
324 case 78: // GNSS1::DOP::g
325 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.gDop); }
326 break;
327 case 79: // GNSS1::DOP::p
328 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.pDop); }
329 break;
330 case 80: // GNSS1::DOP::t
331 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.tDop); }
332 break;
333 case 81: // GNSS1::DOP::v
334 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.vDop); }
335 break;
336 case 82: // GNSS1::DOP::h
337 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.hDop); }
338 break;
339 case 83: // GNSS1::DOP::n
340 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.nDop); }
341 break;
342 case 84: // GNSS1::DOP::e
343 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss1Outputs->dop.eDop); }
344 break;
345 case 85: // GNSS1::SatInfo::NumSats
346 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)) { return static_cast<double>(gnss1Outputs->satInfo.numSats); }
347 break;
348 case 86: // GNSS1::RawMeas::Tow [s]
349 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return gnss1Outputs->raw.tow; }
350 break;
351 case 87: // GNSS1::RawMeas::Week
352 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return static_cast<double>(gnss1Outputs->raw.week); }
353 break;
354 case 88: // GNSS1::RawMeas::NumSats
355 if (gnss1Outputs && (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return static_cast<double>(gnss1Outputs->raw.numSats); }
356 break;
357 // Group 5 (Attitude)
358 case 89: // Att::VpeStatus::AttitudeQuality
359 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.attitudeQuality()); }
360 break;
361 case 90: // Att::VpeStatus::GyroSaturation
362 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturation()); }
363 break;
364 case 91: // Att::VpeStatus::GyroSaturationRecovery
365 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturationRecovery()); }
366 break;
367 case 92: // Att::VpeStatus::MagDisturbance
368 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.magDisturbance()); }
369 break;
370 case 93: // Att::VpeStatus::MagSaturation
371 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.magSaturation()); }
372 break;
373 case 94: // Att::VpeStatus::AccDisturbance
374 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.accDisturbance()); }
375 break;
376 case 95: // Att::VpeStatus::AccSaturation
377 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.accSaturation()); }
378 break;
379 case 96: // Att::VpeStatus::KnownMagDisturbance
380 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.knownMagDisturbance()); }
381 break;
382 case 97: // Att::VpeStatus::KnownAccelDisturbance
383 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)) { return static_cast<double>(attitudeOutputs->vpeStatus.knownAccelDisturbance()); }
384 break;
385 case 98: // Att::YawPitchRoll::Y [deg]
386 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)) { return static_cast<double>(attitudeOutputs->ypr(0)); }
387 break;
388 case 99: // Att::YawPitchRoll::P [deg]
389 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)) { return static_cast<double>(attitudeOutputs->ypr(1)); }
390 break;
391 case 100: // Att::YawPitchRoll::R [deg]
392 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)) { return static_cast<double>(attitudeOutputs->ypr(2)); }
393 break;
394 case 101: // Att::Quaternion::w
395 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)) { return static_cast<double>(attitudeOutputs->qtn.w()); }
396 break;
397 case 102: // Att::Quaternion::x
398 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)) { return static_cast<double>(attitudeOutputs->qtn.x()); }
399 break;
400 case 103: // Att::Quaternion::y
401 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)) { return static_cast<double>(attitudeOutputs->qtn.y()); }
402 break;
403 case 104: // Att::Quaternion::z
404 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)) { return static_cast<double>(attitudeOutputs->qtn.z()); }
405 break;
406 case 105: // Att::DCM::0-0
407 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(0, 0)); }
408 break;
409 case 106: // Att::DCM::0-1
410 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(0, 1)); }
411 break;
412 case 107: // Att::DCM::0-2
413 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(0, 2)); }
414 break;
415 case 108: // Att::DCM::1-0
416 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(1, 0)); }
417 break;
418 case 109: // Att::DCM::1-1
419 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(1, 1)); }
420 break;
421 case 110: // Att::DCM::1-2
422 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(1, 2)); }
423 break;
424 case 111: // Att::DCM::2-0
425 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(2, 0)); }
426 break;
427 case 112: // Att::DCM::2-1
428 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(2, 1)); }
429 break;
430 case 113: // Att::DCM::2-2
431 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)) { return static_cast<double>(attitudeOutputs->dcm(2, 2)); }
432 break;
433 case 114: // Att::MagNed::N [Gauss]
434 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)) { return static_cast<double>(attitudeOutputs->magNed(0)); }
435 break;
436 case 115: // Att::MagNed::E [Gauss]
437 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)) { return static_cast<double>(attitudeOutputs->magNed(1)); }
438 break;
439 case 116: // Att::MagNed::D [Gauss]
440 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)) { return static_cast<double>(attitudeOutputs->magNed(2)); }
441 break;
442 case 117: // Att::AccelNed::N [m/s^2]
443 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)) { return static_cast<double>(attitudeOutputs->accelNed(0)); }
444 break;
445 case 118: // Att::AccelNed::E [m/s^2]
446 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)) { return static_cast<double>(attitudeOutputs->accelNed(1)); }
447 break;
448 case 119: // Att::AccelNed::D [m/s^2]
449 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)) { return static_cast<double>(attitudeOutputs->accelNed(2)); }
450 break;
451 case 120: // Att::LinearAccelBody::X [m/s^2]
452 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)) { return static_cast<double>(attitudeOutputs->linearAccelBody(0)); }
453 break;
454 case 121: // Att::LinearAccelBody::Y [m/s^2]
455 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)) { return static_cast<double>(attitudeOutputs->linearAccelBody(1)); }
456 break;
457 case 122: // Att::LinearAccelBody::Z [m/s^2]
458 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)) { return static_cast<double>(attitudeOutputs->linearAccelBody(2)); }
459 break;
460 case 123: // Att::LinearAccelNed::N [m/s^2]
461 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)) { return static_cast<double>(attitudeOutputs->linearAccelNed(0)); }
462 break;
463 case 124: // Att::LinearAccelNed::E [m/s^2]
464 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)) { return static_cast<double>(attitudeOutputs->linearAccelNed(1)); }
465 break;
466 case 125: // Att::LinearAccelNed::D [m/s^2]
467 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)) { return static_cast<double>(attitudeOutputs->linearAccelNed(2)); }
468 break;
469 case 126: // Att::YprU::Y [deg]
470 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)) { return static_cast<double>(attitudeOutputs->yprU(0)); }
471 break;
472 case 127: // Att::YprU::P [deg]
473 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)) { return static_cast<double>(attitudeOutputs->yprU(1)); }
474 break;
475 case 128: // Att::YprU::R [deg]
476 if (attitudeOutputs && (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)) { return static_cast<double>(attitudeOutputs->yprU(2)); }
477 break;
478 // Group 6 (INS)
479 case 129: // INS::InsStatus::Mode
480 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.mode()); }
481 break;
482 case 130: // INS::InsStatus::GpsFix
483 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.gpsFix()); }
484 break;
485 case 131: // INS::InsStatus::Error::IMU
486 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.errorIMU()); }
487 break;
488 case 132: // INS::InsStatus::Error::MagPres
489 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.errorMagPres()); }
490 break;
491 case 133: // INS::InsStatus::Error::GNSS
492 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.errorGnss()); }
493 break;
494 case 134: // INS::InsStatus::GpsHeadingIns
495 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.gpsHeadingIns()); }
496 break;
497 case 135: // INS::InsStatus::GpsCompass
498 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)) { return static_cast<double>(insOutputs->insStatus.gpsCompass()); }
499 break;
500 case 136: // INS::PosLla::latitude [deg]
501 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)) { return insOutputs->posLla(0); }
502 break;
503 case 137: // INS::PosLla::longitude [deg]
504 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)) { return insOutputs->posLla(1); }
505 break;
506 case 138: // INS::PosLla::altitude [m]
507 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)) { return insOutputs->posLla(2); }
508 break;
509 case 139: // INS::PosEcef::X [m]
510 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)) { return insOutputs->posEcef(0); }
511 break;
512 case 140: // INS::PosEcef::Y [m]
513 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)) { return insOutputs->posEcef(1); }
514 break;
515 case 141: // INS::PosEcef::Z [m]
516 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)) { return insOutputs->posEcef(2); }
517 break;
518 case 142: // INS::VelBody::X [m/s]
519 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)) { return static_cast<double>(insOutputs->velBody(0)); }
520 break;
521 case 143: // INS::VelBody::Y [m/s]
522 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)) { return static_cast<double>(insOutputs->velBody(1)); }
523 break;
524 case 144: // INS::VelBody::Z [m/s]
525 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)) { return static_cast<double>(insOutputs->velBody(2)); }
526 break;
527 case 145: // INS::VelNed::N [m/s]
528 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)) { return static_cast<double>(insOutputs->velNed(0)); }
529 break;
530 case 146: // INS::VelNed::E [m/s]
531 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)) { return static_cast<double>(insOutputs->velNed(1)); }
532 break;
533 case 147: // INS::VelNed::D [m/s]
534 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)) { return static_cast<double>(insOutputs->velNed(2)); }
535 break;
536 case 148: // INS::VelEcef::X [m/s]
537 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)) { return static_cast<double>(insOutputs->velEcef(0)); }
538 break;
539 case 149: // INS::VelEcef::Y [m/s]
540 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)) { return static_cast<double>(insOutputs->velEcef(1)); }
541 break;
542 case 150: // INS::VelEcef::Z [m/s]
543 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)) { return static_cast<double>(insOutputs->velEcef(2)); }
544 break;
545 case 151: // INS::MagEcef::X [Gauss}
546 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)) { return static_cast<double>(insOutputs->magEcef(0)); }
547 break;
548 case 152: // INS::MagEcef::Y [Gauss}
549 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)) { return static_cast<double>(insOutputs->magEcef(1)); }
550 break;
551 case 153: // INS::MagEcef::Z [Gauss}
552 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)) { return static_cast<double>(insOutputs->magEcef(2)); }
553 break;
554 case 154: // INS::AccelEcef::X [m/s^2]
555 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)) { return static_cast<double>(insOutputs->accelEcef(0)); }
556 break;
557 case 155: // INS::AccelEcef::Y [m/s^2]
558 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)) { return static_cast<double>(insOutputs->accelEcef(1)); }
559 break;
560 case 156: // INS::AccelEcef::Z [m/s^2]
561 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)) { return static_cast<double>(insOutputs->accelEcef(2)); }
562 break;
563 case 157: // INS::LinearAccelEcef::X [m/s^2]
564 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)) { return static_cast<double>(insOutputs->linearAccelEcef(0)); }
565 break;
566 case 158: // INS::LinearAccelEcef::Y [m/s^2]
567 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)) { return static_cast<double>(insOutputs->linearAccelEcef(1)); }
568 break;
569 case 159: // INS::LinearAccelEcef::Z [m/s^2]
570 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)) { return static_cast<double>(insOutputs->linearAccelEcef(2)); }
571 break;
572 case 160: // INS::PosU [m]
573 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSU)) { return static_cast<double>(insOutputs->posU); }
574 break;
575 case 161: // INS::VelU [m/s]
576 if (insOutputs && (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELU)) { return static_cast<double>(insOutputs->velU); }
577 break;
578 // Group 7 (GNSS2)
579 case 162: // GNSS2::UTC::year
580 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.year); }
581 break;
582 case 163: // GNSS2::UTC::month
583 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.month); }
584 break;
585 case 164: // GNSS2::UTC::day
586 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.day); }
587 break;
588 case 165: // GNSS2::UTC::hour
589 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.hour); }
590 break;
591 case 166: // GNSS2::UTC::min
592 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.min); }
593 break;
594 case 167: // GNSS2::UTC::sec
595 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.sec); }
596 break;
597 case 168: // GNSS2::UTC::ms
598 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)) { return static_cast<double>(gnss2Outputs->timeUtc.ms); }
599 break;
600 case 169: // GNSS2::Tow [ns]
601 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)) { return static_cast<double>(gnss2Outputs->tow); }
602 break;
603 case 170: // GNSS2::Week
604 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)) { return static_cast<double>(gnss2Outputs->week); }
605 break;
606 case 171: // GNSS2::NumSats
607 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)) { return static_cast<double>(gnss2Outputs->numSats); }
608 break;
609 case 172: // GNSS2::Fix
610 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)) { return static_cast<double>(gnss2Outputs->fix); }
611 break;
612 case 173: // GNSS2::PosLla::latitude [deg]
613 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss2Outputs->posLla(0); }
614 break;
615 case 174: // GNSS2::PosLla::longitude [deg]
616 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss2Outputs->posLla(1); }
617 break;
618 case 175: // GNSS2::PosLla::altitude [m]
619 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)) { return gnss2Outputs->posLla(2); }
620 break;
621 case 176: // GNSS2::PosEcef::X [m]
622 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss2Outputs->posEcef(0); }
623 break;
624 case 177: // GNSS2::PosEcef::Y [m]
625 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss2Outputs->posEcef(1); }
626 break;
627 case 178: // GNSS2::PosEcef::Z [m]
628 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)) { return gnss2Outputs->posEcef(2); }
629 break;
630 case 179: // GNSS2::VelNed::N [m/s]
631 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss2Outputs->velNed(0)); }
632 break;
633 case 180: // GNSS2::VelNed::E [m/s]
634 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss2Outputs->velNed(1)); }
635 break;
636 case 181: // GNSS2::VelNed::D [m/s]
637 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)) { return static_cast<double>(gnss2Outputs->velNed(2)); }
638 break;
639 case 182: // GNSS2::VelEcef::X [m/s]
640 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss2Outputs->velEcef(0)); }
641 break;
642 case 183: // GNSS2::VelEcef::Y [m/s]
643 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss2Outputs->velEcef(1)); }
644 break;
645 case 184: // GNSS2::VelEcef::Z [m/s]
646 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)) { return static_cast<double>(gnss2Outputs->velEcef(2)); }
647 break;
648 case 185: // GNSS2::PosU::N [m]
649 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss2Outputs->posU(0)); }
650 break;
651 case 186: // GNSS2::PosU::E [m]
652 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss2Outputs->posU(1)); }
653 break;
654 case 187: // GNSS2::PosU::D [m]
655 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)) { return static_cast<double>(gnss2Outputs->posU(2)); }
656 break;
657 case 188: // GNSS2::VelU [m/s]
658 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)) { return static_cast<double>(gnss2Outputs->velU); }
659 break;
660 case 189: // GNSS2::TimeU [s]
661 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)) { return static_cast<double>(gnss2Outputs->timeU); }
662 break;
663 case 190: // GNSS2::TimeInfo::Status::timeOk
664 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss2Outputs->timeInfo.status.timeOk()); }
665 break;
666 case 191: // GNSS2::TimeInfo::Status::dateOk
667 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss2Outputs->timeInfo.status.dateOk()); }
668 break;
669 case 192: // GNSS2::TimeInfo::Status::utcTimeValid
670 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss2Outputs->timeInfo.status.utcTimeValid()); }
671 break;
672 case 193: // GNSS2::TimeInfo::LeapSeconds
673 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)) { return static_cast<double>(gnss2Outputs->timeInfo.leapSeconds); }
674 break;
675 case 194: // GNSS2::DOP::g
676 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.gDop); }
677 break;
678 case 195: // GNSS2::DOP::p
679 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.pDop); }
680 break;
681 case 196: // GNSS2::DOP::t
682 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.tDop); }
683 break;
684 case 197: // GNSS2::DOP::v
685 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.vDop); }
686 break;
687 case 198: // GNSS2::DOP::h
688 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.hDop); }
689 break;
690 case 199: // GNSS2::DOP::n
691 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.nDop); }
692 break;
693 case 200: // GNSS2::DOP::e
694 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)) { return static_cast<double>(gnss2Outputs->dop.eDop); }
695 break;
696 case 201: // GNSS2::SatInfo::NumSats
697 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)) { return static_cast<double>(gnss2Outputs->satInfo.numSats); }
698 break;
699 case 202: // GNSS2::RawMeas::Tow [s]
700 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return gnss2Outputs->raw.tow; }
701 break;
702 case 203: // GNSS2::RawMeas::Week
703 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return static_cast<double>(gnss2Outputs->raw.week); }
704 break;
705 case 204: // GNSS2::RawMeas::NumSats
706 if (gnss2Outputs && (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)) { return static_cast<double>(gnss2Outputs->raw.numSats); }
707 break;
708 default:
709 return std::nullopt;
710 }
711 return std::nullopt;
712 }
713
714 /// @brief Get the Sat Sys object in "INSTINCT" format
715 /// @param[in, out] sys VectorNav Satellite Constellation
716 /// @return Satellite System in "INSTINCT" format
718 {
720 }
721
722 /// @brief Returns a vector of data descriptors for the dynamic data
723 [[nodiscard]] std::vector<std::string> dynamicDataDescriptors() const override
724 {
725 std::vector<std::string> descriptors;
726
727 // Group 2 (Time)
728 if (timeOutputs)
729 {
730 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTARTUP)
731 {
732 descriptors.emplace_back("Time::TimeStartup [ns]");
733 }
734 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPS)
735 {
736 descriptors.emplace_back("Time::TimeGps [ns]");
737 }
738 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
739 {
740 descriptors.emplace_back("Time::GpsTow [ns]");
741 }
742 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK)
743 {
744 descriptors.emplace_back("Time::GpsWeek");
745 }
746 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESYNCIN)
747 {
748 descriptors.emplace_back("Time::TimeSyncIn [ns]");
749 }
750 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPSPPS)
751 {
752 descriptors.emplace_back("Time::TimeGpsPps [ns]");
753 }
754 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)
755 {
756 descriptors.emplace_back("Time::TimeUTC::year");
757 descriptors.emplace_back("Time::TimeUTC::month");
758 descriptors.emplace_back("Time::TimeUTC::day");
759 descriptors.emplace_back("Time::TimeUTC::hour");
760 descriptors.emplace_back("Time::TimeUTC::min");
761 descriptors.emplace_back("Time::TimeUTC::sec");
762 descriptors.emplace_back("Time::TimeUTC::ms");
763 }
764 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCINCNT)
765 {
766 descriptors.emplace_back("Time::SyncInCnt");
767 }
768 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCOUTCNT)
769 {
770 descriptors.emplace_back("Time::SyncOutCnt");
771 }
772 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
773 {
774 descriptors.emplace_back("Time::TimeStatus::timeOk");
775 descriptors.emplace_back("Time::TimeStatus::dateOk");
776 descriptors.emplace_back("Time::TimeStatus::utcTimeValid");
777 }
778 }
779 // Group 3 (IMU)
780 if (imuOutputs)
781 {
782 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_IMUSTATUS)
783 {
784 descriptors.emplace_back("IMU::ImuStatus");
785 }
786 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
787 {
788 descriptors.emplace_back("IMU::UncompMag::X [Gauss]");
789 descriptors.emplace_back("IMU::UncompMag::Y [Gauss]");
790 descriptors.emplace_back("IMU::UncompMag::Z [Gauss]");
791 }
792 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
793 {
794 descriptors.emplace_back("IMU::UncompAccel::X [m/s^2]");
795 descriptors.emplace_back("IMU::UncompAccel::Y [m/s^2]");
796 descriptors.emplace_back("IMU::UncompAccel::Z [m/s^2]");
797 }
798 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
799 {
800 descriptors.emplace_back("IMU::UncompGyro::X [rad/s]");
801 descriptors.emplace_back("IMU::UncompGyro::Y [rad/s]");
802 descriptors.emplace_back("IMU::UncompGyro::Z [rad/s]");
803 }
804 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
805 {
806 descriptors.emplace_back("IMU::Temp [Celsius]");
807 }
808 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)
809 {
810 descriptors.emplace_back("IMU::Pres [kPa]");
811 }
812 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)
813 {
814 descriptors.emplace_back("IMU::DeltaTime [s]");
815 descriptors.emplace_back("IMU::DeltaTheta::X [deg]");
816 descriptors.emplace_back("IMU::DeltaTheta::Y [deg]");
817 descriptors.emplace_back("IMU::DeltaTheta::Z [deg]");
818 }
819 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)
820 {
821 descriptors.emplace_back("IMU::DeltaVel::X [m/s]");
822 descriptors.emplace_back("IMU::DeltaVel::Y [m/s]");
823 descriptors.emplace_back("IMU::DeltaVel::Z [m/s]");
824 }
825 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
826 {
827 descriptors.emplace_back("IMU::Mag::X [Gauss]");
828 descriptors.emplace_back("IMU::Mag::Y [Gauss]");
829 descriptors.emplace_back("IMU::Mag::Z [Gauss]");
830 }
831 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
832 {
833 descriptors.emplace_back("IMU::Accel::X [m/s^2]");
834 descriptors.emplace_back("IMU::Accel::Y [m/s^2]");
835 descriptors.emplace_back("IMU::Accel::Z [m/s^2]");
836 }
837 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
838 {
839 descriptors.emplace_back("IMU::AngularRate::X [rad/s]");
840 descriptors.emplace_back("IMU::AngularRate::Y [rad/s]");
841 descriptors.emplace_back("IMU::AngularRate::Z [rad/s]");
842 }
843 }
844 // Group 4 (GNSS1)
845 if (gnss1Outputs)
846 {
847 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
848 {
849 descriptors.emplace_back("GNSS1::UTC::year");
850 descriptors.emplace_back("GNSS1::UTC::month");
851 descriptors.emplace_back("GNSS1::UTC::day");
852 descriptors.emplace_back("GNSS1::UTC::hour");
853 descriptors.emplace_back("GNSS1::UTC::min");
854 descriptors.emplace_back("GNSS1::UTC::sec");
855 descriptors.emplace_back("GNSS1::UTC::ms");
856 }
857 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
858 {
859 descriptors.emplace_back("GNSS1::Tow [ns]");
860 }
861 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
862 {
863 descriptors.emplace_back("GNSS1::Week");
864 }
865 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
866 {
867 descriptors.emplace_back("GNSS1::NumSats");
868 }
869 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
870 {
871 descriptors.emplace_back("GNSS1::Fix");
872 }
873 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
874 {
875 descriptors.emplace_back("GNSS1::PosLla::latitude [deg]");
876 descriptors.emplace_back("GNSS1::PosLla::longitude [deg]");
877 descriptors.emplace_back("GNSS1::PosLla::altitude [m]");
878 }
879 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
880 {
881 descriptors.emplace_back("GNSS1::PosEcef::X [m]");
882 descriptors.emplace_back("GNSS1::PosEcef::Y [m]");
883 descriptors.emplace_back("GNSS1::PosEcef::Z [m]");
884 }
885 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
886 {
887 descriptors.emplace_back("GNSS1::VelNed::N [m/s]");
888 descriptors.emplace_back("GNSS1::VelNed::E [m/s]");
889 descriptors.emplace_back("GNSS1::VelNed::D [m/s]");
890 }
891 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
892 {
893 descriptors.emplace_back("GNSS1::VelEcef::X [m/s]");
894 descriptors.emplace_back("GNSS1::VelEcef::Y [m/s]");
895 descriptors.emplace_back("GNSS1::VelEcef::Z [m/s]");
896 }
897 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
898 {
899 descriptors.emplace_back("GNSS1::PosU::N [m]");
900 descriptors.emplace_back("GNSS1::PosU::E [m]");
901 descriptors.emplace_back("GNSS1::PosU::D [m]");
902 }
903 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
904 {
905 descriptors.emplace_back("GNSS1::VelU [m/s]");
906 }
907 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
908 {
909 descriptors.emplace_back("GNSS1::TimeU [s]");
910 }
911 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
912 {
913 descriptors.emplace_back("GNSS1::TimeInfo::Status::timeOk");
914 descriptors.emplace_back("GNSS1::TimeInfo::Status::dateOk");
915 descriptors.emplace_back("GNSS1::TimeInfo::Status::utcTimeValid");
916 descriptors.emplace_back("GNSS1::TimeInfo::LeapSeconds");
917 }
918 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
919 {
920 descriptors.emplace_back("GNSS1::DOP::g");
921 descriptors.emplace_back("GNSS1::DOP::p");
922 descriptors.emplace_back("GNSS1::DOP::t");
923 descriptors.emplace_back("GNSS1::DOP::v");
924 descriptors.emplace_back("GNSS1::DOP::h");
925 descriptors.emplace_back("GNSS1::DOP::n");
926 descriptors.emplace_back("GNSS1::DOP::e");
927 }
928 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
929 {
930 descriptors.emplace_back("GNSS1::SatInfo::NumSats");
931 for (auto& satellite : gnss1Outputs->satInfo.satellites)
932 {
933 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
934 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Healthy", satId));
935 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Almanac", satId));
936 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Ephemeris", satId));
937 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag DifferentialCorrection", satId));
938 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForNavigation", satId));
939 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag AzimuthElevationValid", satId));
940 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForRTK", satId));
941 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - cno", satId));
942 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - qi", satId));
943 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - el", satId));
944 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - az", satId));
945 }
946 }
947 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
948 {
949 descriptors.emplace_back("GNSS1::RawMeas::Tow [s]");
950 descriptors.emplace_back("GNSS1::RawMeas::Week");
951 descriptors.emplace_back("GNSS1::RawMeas::NumSats");
952 for (auto& satellite : gnss1Outputs->raw.satellites)
953 {
954 SatSigId satSigId = satellite.toSatSigId();
955 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - freq", satSigId));
956 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - chan", satSigId));
957 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - slot", satSigId));
958 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - cno", satSigId));
959 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag Searching", satSigId));
960 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag Tracking", satSigId));
961 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag TimeValid", satSigId));
962 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag CodeLock", satSigId));
963 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseLock", satSigId));
964 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfAmbiguity", satSigId));
965 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfSub", satSigId));
966 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseSlip", satSigId));
967 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PseudorangeSmoothed", satSigId));
968 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - pr", satSigId));
969 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - cp", satSigId));
970 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - dp", satSigId));
971 }
972 }
973 }
974 // Group 5 (Attitude)
975 if (attitudeOutputs)
976 {
977 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)
978 {
979 descriptors.emplace_back("Att::VpeStatus::AttitudeQuality");
980 descriptors.emplace_back("Att::VpeStatus::GyroSaturation");
981 descriptors.emplace_back("Att::VpeStatus::GyroSaturationRecovery");
982 descriptors.emplace_back("Att::VpeStatus::MagDisturbance");
983 descriptors.emplace_back("Att::VpeStatus::MagSaturation");
984 descriptors.emplace_back("Att::VpeStatus::AccDisturbance");
985 descriptors.emplace_back("Att::VpeStatus::AccSaturation");
986 descriptors.emplace_back("Att::VpeStatus::KnownMagDisturbance");
987 descriptors.emplace_back("Att::VpeStatus::KnownAccelDisturbance");
988 }
989 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)
990 {
991 descriptors.emplace_back("Att::YawPitchRoll::Y [deg]");
992 descriptors.emplace_back("Att::YawPitchRoll::P [deg]");
993 descriptors.emplace_back("Att::YawPitchRoll::R [deg]");
994 }
995 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)
996 {
997 descriptors.emplace_back("Att::Quaternion::w");
998 descriptors.emplace_back("Att::Quaternion::x");
999 descriptors.emplace_back("Att::Quaternion::y");
1000 descriptors.emplace_back("Att::Quaternion::z");
1001 }
1002 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)
1003 {
1004 descriptors.emplace_back("Att::DCM::0-0,");
1005 descriptors.emplace_back("Att::DCM::0-1");
1006 descriptors.emplace_back("Att::DCM::0-2");
1007 descriptors.emplace_back("Att::DCM::1-0");
1008 descriptors.emplace_back("Att::DCM::1-1");
1009 descriptors.emplace_back("Att::DCM::1-2");
1010 descriptors.emplace_back("Att::DCM::2-0");
1011 descriptors.emplace_back("Att::DCM::2-1");
1012 descriptors.emplace_back("Att::DCM::2-2");
1013 }
1014 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)
1015 {
1016 descriptors.emplace_back("Att::MagNed::N [Gauss]");
1017 descriptors.emplace_back("Att::MagNed::E [Gauss]");
1018 descriptors.emplace_back("Att::MagNed::D [Gauss]");
1019 }
1020 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)
1021 {
1022 descriptors.emplace_back("Att::AccelNed::N [m/s^2]");
1023 descriptors.emplace_back("Att::AccelNed::E [m/s^2]");
1024 descriptors.emplace_back("Att::AccelNed::D [m/s^2]");
1025 }
1026 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)
1027 {
1028 descriptors.emplace_back("Att::LinearAccelBody::X [m/s^2]");
1029 descriptors.emplace_back("Att::LinearAccelBody::Y [m/s^2]");
1030 descriptors.emplace_back("Att::LinearAccelBody::Z [m/s^2]");
1031 }
1032 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)
1033 {
1034 descriptors.emplace_back("Att::LinearAccelNed::N [m/s^2]");
1035 descriptors.emplace_back("Att::LinearAccelNed::E [m/s^2]");
1036 descriptors.emplace_back("Att::LinearAccelNed::D [m/s^2]");
1037 }
1038 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)
1039 {
1040 descriptors.emplace_back("Att::YprU::Y [deg]");
1041 descriptors.emplace_back("Att::YprU::P [deg]");
1042 descriptors.emplace_back("Att::YprU::R [deg]");
1043 }
1044 }
1045 // Group 6 (INS)
1046 if (insOutputs)
1047 {
1048 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)
1049 {
1050 descriptors.emplace_back("INS::InsStatus::Mode");
1051 descriptors.emplace_back("INS::InsStatus::GpsFix");
1052 descriptors.emplace_back("INS::InsStatus::Error::IMU");
1053 descriptors.emplace_back("INS::InsStatus::Error::MagPres");
1054 descriptors.emplace_back("INS::InsStatus::Error::GNSS");
1055 descriptors.emplace_back("INS::InsStatus::GpsHeadingIns");
1056 descriptors.emplace_back("INS::InsStatus::GpsCompass");
1057 }
1058 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)
1059 {
1060 descriptors.emplace_back("INS::PosLla::latitude [deg]");
1061 descriptors.emplace_back("INS::PosLla::longitude [deg]");
1062 descriptors.emplace_back("INS::PosLla::altitude [m]");
1063 }
1064 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)
1065 {
1066 descriptors.emplace_back("INS::PosEcef::X [m]");
1067 descriptors.emplace_back("INS::PosEcef::Y [m]");
1068 descriptors.emplace_back("INS::PosEcef::Z [m]");
1069 }
1070 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)
1071 {
1072 descriptors.emplace_back("INS::VelBody::X [m/s]");
1073 descriptors.emplace_back("INS::VelBody::Y [m/s]");
1074 descriptors.emplace_back("INS::VelBody::Z [m/s]");
1075 }
1076 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)
1077 {
1078 descriptors.emplace_back("INS::VelNed::N [m/s]");
1079 descriptors.emplace_back("INS::VelNed::E [m/s]");
1080 descriptors.emplace_back("INS::VelNed::D [m/s]");
1081 }
1082 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)
1083 {
1084 descriptors.emplace_back("INS::VelEcef::X [m/s]");
1085 descriptors.emplace_back("INS::VelEcef::Y [m/s]");
1086 descriptors.emplace_back("INS::VelEcef::Z [m/s]");
1087 }
1088 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)
1089 {
1090 descriptors.emplace_back("INS::MagEcef::X [Gauss]");
1091 descriptors.emplace_back("INS::MagEcef::Y [Gauss]");
1092 descriptors.emplace_back("INS::MagEcef::Z [Gauss]");
1093 }
1094 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)
1095 {
1096 descriptors.emplace_back("INS::AccelEcef::X [m/s^2]");
1097 descriptors.emplace_back("INS::AccelEcef::Y [m/s^2]");
1098 descriptors.emplace_back("INS::AccelEcef::Z [m/s^2]");
1099 }
1100 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)
1101 {
1102 descriptors.emplace_back("INS::LinearAccelEcef::X [m/s^2]");
1103 descriptors.emplace_back("INS::LinearAccelEcef::Y [m/s^2]");
1104 descriptors.emplace_back("INS::LinearAccelEcef::Z [m/s^2]");
1105 }
1106 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSU)
1107 {
1108 descriptors.emplace_back("INS::PosU [m]");
1109 }
1110 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELU)
1111 {
1112 descriptors.emplace_back("INS::VelU [m/s]");
1113 }
1114 }
1115 // Group 7 (GNSS2)
1116 if (gnss2Outputs)
1117 {
1118 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1119 {
1120 descriptors.emplace_back("GNSS2::UTC::year");
1121 descriptors.emplace_back("GNSS2::UTC::month");
1122 descriptors.emplace_back("GNSS2::UTC::day");
1123 descriptors.emplace_back("GNSS2::UTC::hour");
1124 descriptors.emplace_back("GNSS2::UTC::min");
1125 descriptors.emplace_back("GNSS2::UTC::sec");
1126 descriptors.emplace_back("GNSS2::UTC::ms");
1127 }
1128 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1129 {
1130 descriptors.emplace_back("GNSS2::Tow [ns]");
1131 }
1132 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1133 {
1134 descriptors.emplace_back("GNSS2::Week");
1135 }
1136 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1137 {
1138 descriptors.emplace_back("GNSS2::NumSats");
1139 }
1140 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1141 {
1142 descriptors.emplace_back("GNSS2::Fix");
1143 }
1144 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1145 {
1146 descriptors.emplace_back("GNSS2::PosLla::latitude [deg]");
1147 descriptors.emplace_back("GNSS2::PosLla::longitude [deg]");
1148 descriptors.emplace_back("GNSS2::PosLla::altitude [m]");
1149 }
1150 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1151 {
1152 descriptors.emplace_back("GNSS2::PosEcef::X [m]");
1153 descriptors.emplace_back("GNSS2::PosEcef::Y [m]");
1154 descriptors.emplace_back("GNSS2::PosEcef::Z [m]");
1155 }
1156 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
1157 {
1158 descriptors.emplace_back("GNSS2::VelNed::N [m/s]");
1159 descriptors.emplace_back("GNSS2::VelNed::E [m/s]");
1160 descriptors.emplace_back("GNSS2::VelNed::D [m/s]");
1161 }
1162 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
1163 {
1164 descriptors.emplace_back("GNSS2::VelEcef::X [m/s]");
1165 descriptors.emplace_back("GNSS2::VelEcef::Y [m/s]");
1166 descriptors.emplace_back("GNSS2::VelEcef::Z [m/s]");
1167 }
1168 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
1169 {
1170 descriptors.emplace_back("GNSS2::PosU::N [m]");
1171 descriptors.emplace_back("GNSS2::PosU::E [m]");
1172 descriptors.emplace_back("GNSS2::PosU::D [m]");
1173 }
1174 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
1175 {
1176 descriptors.emplace_back("GNSS2::VelU [m/s]");
1177 }
1178 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
1179 {
1180 descriptors.emplace_back("GNSS2::TimeU [s]");
1181 }
1182 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
1183 {
1184 descriptors.emplace_back("GNSS2::TimeInfo::Status::timeOk");
1185 descriptors.emplace_back("GNSS2::TimeInfo::Status::dateOk");
1186 descriptors.emplace_back("GNSS2::TimeInfo::Status::utcTimeValid");
1187 descriptors.emplace_back("GNSS2::TimeInfo::LeapSeconds");
1188 }
1189 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
1190 {
1191 descriptors.emplace_back("GNSS2::DOP::g");
1192 descriptors.emplace_back("GNSS2::DOP::p");
1193 descriptors.emplace_back("GNSS2::DOP::t");
1194 descriptors.emplace_back("GNSS2::DOP::v");
1195 descriptors.emplace_back("GNSS2::DOP::h");
1196 descriptors.emplace_back("GNSS2::DOP::n");
1197 descriptors.emplace_back("GNSS2::DOP::e");
1198 }
1199 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
1200 {
1201 descriptors.emplace_back("GNSS2::SatInfo::NumSats");
1202 for (auto& satellite : gnss2Outputs->satInfo.satellites)
1203 {
1204 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1205 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Healthy", satId));
1206 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Almanac", satId));
1207 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Ephemeris", satId));
1208 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag DifferentialCorrection", satId));
1209 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForNavigation", satId));
1210 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag AzimuthElevationValid", satId));
1211 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForRTK", satId));
1212 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - cno", satId));
1213 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - qi", satId));
1214 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - el", satId));
1215 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - az", satId));
1216 }
1217 }
1218 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
1219 {
1220 descriptors.emplace_back("GNSS2::RawMeas::Tow [s]");
1221 descriptors.emplace_back("GNSS2::RawMeas::Week");
1222 descriptors.emplace_back("GNSS2::RawMeas::NumSats");
1223 for (auto& satellite : gnss2Outputs->raw.satellites)
1224 {
1225 SatSigId satSigId = satellite.toSatSigId();
1226 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - freq", satSigId));
1227 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - chan", satSigId));
1228 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - slot", satSigId));
1229 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - cno", satSigId));
1230 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag Searching", satSigId));
1231 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag Tracking", satSigId));
1232 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag TimeValid", satSigId));
1233 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag CodeLock", satSigId));
1234 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseLock", satSigId));
1235 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfAmbiguity", satSigId));
1236 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfSub", satSigId));
1237 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseSlip", satSigId));
1238 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PseudorangeSmoothed", satSigId));
1239 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - pr", satSigId));
1240 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - cp", satSigId));
1241 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - dp", satSigId));
1242 }
1243 }
1244 }
1245
1246 return descriptors;
1247 }
1248
1249 /// @brief Get the value for the descriptor
1250 /// @return Value if in the observation
1251 [[nodiscard]] std::optional<double> getDynamicDataAt(const std::string& descriptor) const override
1252 {
1253 // Group 2 (Time)
1254 if (timeOutputs)
1255 {
1256 if (descriptor == "Time::TimeStartup [ns]") { return static_cast<double>(timeOutputs->timeStartup); }
1257 if (descriptor == "Time::TimeGps [ns]") { return static_cast<double>(timeOutputs->timeGps); }
1258 if (descriptor == "Time::GpsTow [ns]") { return static_cast<double>(timeOutputs->gpsTow); }
1259 if (descriptor == "Time::GpsWeek") { return static_cast<double>(timeOutputs->gpsWeek); }
1260 if (descriptor == "Time::TimeSyncIn [ns]") { return static_cast<double>(timeOutputs->timeSyncIn); }
1261 if (descriptor == "Time::TimeGpsPps [ns]") { return static_cast<double>(timeOutputs->timePPS); }
1262 if (descriptor == "Time::TimeUTC::year") { return static_cast<double>(timeOutputs->timeUtc.year); }
1263 if (descriptor == "Time::TimeUTC::month") { return static_cast<double>(timeOutputs->timeUtc.month); }
1264 if (descriptor == "Time::TimeUTC::day") { return static_cast<double>(timeOutputs->timeUtc.day); }
1265 if (descriptor == "Time::TimeUTC::hour") { return static_cast<double>(timeOutputs->timeUtc.hour); }
1266 if (descriptor == "Time::TimeUTC::min") { return static_cast<double>(timeOutputs->timeUtc.min); }
1267 if (descriptor == "Time::TimeUTC::sec") { return static_cast<double>(timeOutputs->timeUtc.sec); }
1268 if (descriptor == "Time::TimeUTC::ms") { return static_cast<double>(timeOutputs->timeUtc.ms); }
1269 if (descriptor == "Time::SyncInCnt") { return static_cast<double>(timeOutputs->syncInCnt); }
1270 if (descriptor == "Time::SyncOutCnt") { return static_cast<double>(timeOutputs->syncOutCnt); }
1271 if (descriptor == "Time::TimeStatus::timeOk") { return static_cast<double>(timeOutputs->timeStatus.timeOk()); }
1272 if (descriptor == "Time::TimeStatus::dateOk") { return static_cast<double>(timeOutputs->timeStatus.dateOk()); }
1273 if (descriptor == "Time::TimeStatus::utcTimeValid") { return static_cast<double>(timeOutputs->timeStatus.utcTimeValid()); }
1274 }
1275 // Group 3 (IMU)
1276 if (imuOutputs)
1277 {
1278 if (descriptor == "IMU::ImuStatus") { return static_cast<double>(imuOutputs->imuStatus); }
1279 if (descriptor == "IMU::UncompMag::X [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(0)); }
1280 if (descriptor == "IMU::UncompMag::Y [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(1)); }
1281 if (descriptor == "IMU::UncompMag::Z [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(2)); }
1282 if (descriptor == "IMU::UncompAccel::X [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(0)); }
1283 if (descriptor == "IMU::UncompAccel::Y [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(1)); }
1284 if (descriptor == "IMU::UncompAccel::Z [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(2)); }
1285 if (descriptor == "IMU::UncompGyro::X [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(0)); }
1286 if (descriptor == "IMU::UncompGyro::Y [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(1)); }
1287 if (descriptor == "IMU::UncompGyro::Z [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(2)); }
1288 if (descriptor == "IMU::Temp [Celsius]") { return static_cast<double>(imuOutputs->temp); }
1289 if (descriptor == "IMU::Pres [kPa]") { return static_cast<double>(imuOutputs->pres); }
1290 if (descriptor == "IMU::DeltaTime [s]") { return static_cast<double>(imuOutputs->deltaTime); }
1291 if (descriptor == "IMU::DeltaTheta::X [deg]") { return static_cast<double>(imuOutputs->deltaTheta(0)); }
1292 if (descriptor == "IMU::DeltaTheta::Y [deg]") { return static_cast<double>(imuOutputs->deltaTheta(1)); }
1293 if (descriptor == "IMU::DeltaTheta::Z [deg]") { return static_cast<double>(imuOutputs->deltaTheta(2)); }
1294 if (descriptor == "IMU::DeltaVel::X [m/s]") { return static_cast<double>(imuOutputs->deltaV(0)); }
1295 if (descriptor == "IMU::DeltaVel::Y [m/s]") { return static_cast<double>(imuOutputs->deltaV(1)); }
1296 if (descriptor == "IMU::DeltaVel::Z [m/s]") { return static_cast<double>(imuOutputs->deltaV(2)); }
1297 if (descriptor == "IMU::Mag::X [Gauss]") { return static_cast<double>(imuOutputs->mag(0)); }
1298 if (descriptor == "IMU::Mag::Y [Gauss]") { return static_cast<double>(imuOutputs->mag(1)); }
1299 if (descriptor == "IMU::Mag::Z [Gauss]") { return static_cast<double>(imuOutputs->mag(2)); }
1300 if (descriptor == "IMU::Accel::X [m/s^2]") { return static_cast<double>(imuOutputs->accel(0)); }
1301 if (descriptor == "IMU::Accel::Y [m/s^2]") { return static_cast<double>(imuOutputs->accel(1)); }
1302 if (descriptor == "IMU::Accel::Z [m/s^2]") { return static_cast<double>(imuOutputs->accel(2)); }
1303 if (descriptor == "IMU::AngularRate::X [rad/s]") { return static_cast<double>(imuOutputs->angularRate(0)); }
1304 if (descriptor == "IMU::AngularRate::Y [rad/s]") { return static_cast<double>(imuOutputs->angularRate(1)); }
1305 if (descriptor == "IMU::AngularRate::Z [rad/s]") { return static_cast<double>(imuOutputs->angularRate(2)); }
1306 }
1307 // Group 4 (GNSS1)
1308 if (gnss1Outputs)
1309 {
1310 if (descriptor == "GNSS1::UTC::year") { return static_cast<double>(gnss1Outputs->timeUtc.year); }
1311 if (descriptor == "GNSS1::UTC::month") { return static_cast<double>(gnss1Outputs->timeUtc.month); }
1312 if (descriptor == "GNSS1::UTC::day") { return static_cast<double>(gnss1Outputs->timeUtc.day); }
1313 if (descriptor == "GNSS1::UTC::hour") { return static_cast<double>(gnss1Outputs->timeUtc.hour); }
1314 if (descriptor == "GNSS1::UTC::min") { return static_cast<double>(gnss1Outputs->timeUtc.min); }
1315 if (descriptor == "GNSS1::UTC::sec") { return static_cast<double>(gnss1Outputs->timeUtc.sec); }
1316 if (descriptor == "GNSS1::UTC::ms") { return static_cast<double>(gnss1Outputs->timeUtc.ms); }
1317 if (descriptor == "GNSS1::Tow [ns]") { return static_cast<double>(gnss1Outputs->tow); }
1318 if (descriptor == "GNSS1::Week") { return static_cast<double>(gnss1Outputs->week); }
1319 if (descriptor == "GNSS1::NumSats") { return static_cast<double>(gnss1Outputs->numSats); }
1320 if (descriptor == "GNSS1::Fix") { return static_cast<double>(gnss1Outputs->fix); }
1321 if (descriptor == "GNSS1::PosLla::latitude [deg]") { return static_cast<double>(gnss1Outputs->posLla(0)); }
1322 if (descriptor == "GNSS1::PosLla::longitude [deg]") { return static_cast<double>(gnss1Outputs->posLla(1)); }
1323 if (descriptor == "GNSS1::PosLla::altitude [m]") { return static_cast<double>(gnss1Outputs->posLla(2)); }
1324 if (descriptor == "GNSS1::PosEcef::X [m]") { return static_cast<double>(gnss1Outputs->posEcef(0)); }
1325 if (descriptor == "GNSS1::PosEcef::Y [m]") { return static_cast<double>(gnss1Outputs->posEcef(1)); }
1326 if (descriptor == "GNSS1::PosEcef::Z [m]") { return static_cast<double>(gnss1Outputs->posEcef(2)); }
1327 if (descriptor == "GNSS1::VelNed::N [m/s]") { return static_cast<double>(gnss1Outputs->velNed(0)); }
1328 if (descriptor == "GNSS1::VelNed::E [m/s]") { return static_cast<double>(gnss1Outputs->velNed(1)); }
1329 if (descriptor == "GNSS1::VelNed::D [m/s]") { return static_cast<double>(gnss1Outputs->velNed(2)); }
1330 if (descriptor == "GNSS1::VelEcef::X [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(0)); }
1331 if (descriptor == "GNSS1::VelEcef::Y [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(1)); }
1332 if (descriptor == "GNSS1::VelEcef::Z [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(2)); }
1333 if (descriptor == "GNSS1::PosU::N [m]") { return static_cast<double>(gnss1Outputs->posU(0)); }
1334 if (descriptor == "GNSS1::PosU::E [m]") { return static_cast<double>(gnss1Outputs->posU(1)); }
1335 if (descriptor == "GNSS1::PosU::D [m]") { return static_cast<double>(gnss1Outputs->posU(2)); }
1336 if (descriptor == "GNSS1::VelU [m/s]") { return static_cast<double>(gnss1Outputs->velU); }
1337 if (descriptor == "GNSS1::TimeU [s]") { return static_cast<double>(gnss1Outputs->timeU); }
1338 if (descriptor == "GNSS1::TimeInfo::Status::timeOk") { return static_cast<double>(gnss1Outputs->timeInfo.status.timeOk()); }
1339 if (descriptor == "GNSS1::TimeInfo::Status::dateOk") { return static_cast<double>(gnss1Outputs->timeInfo.status.dateOk()); }
1340 if (descriptor == "GNSS1::TimeInfo::Status::utcTimeValid") { return static_cast<double>(gnss1Outputs->timeInfo.status.utcTimeValid()); }
1341 if (descriptor == "GNSS1::TimeInfo::LeapSeconds") { return static_cast<double>(gnss1Outputs->timeInfo.leapSeconds); }
1342 if (descriptor == "GNSS1::DOP::g") { return static_cast<double>(gnss1Outputs->dop.gDop); }
1343 if (descriptor == "GNSS1::DOP::p") { return static_cast<double>(gnss1Outputs->dop.pDop); }
1344 if (descriptor == "GNSS1::DOP::t") { return static_cast<double>(gnss1Outputs->dop.tDop); }
1345 if (descriptor == "GNSS1::DOP::v") { return static_cast<double>(gnss1Outputs->dop.vDop); }
1346 if (descriptor == "GNSS1::DOP::h") { return static_cast<double>(gnss1Outputs->dop.hDop); }
1347 if (descriptor == "GNSS1::DOP::n") { return static_cast<double>(gnss1Outputs->dop.nDop); }
1348 if (descriptor == "GNSS1::DOP::e") { return static_cast<double>(gnss1Outputs->dop.eDop); }
1349 if (descriptor == "GNSS1::SatInfo::NumSats") { return static_cast<double>(gnss1Outputs->satInfo.numSats); }
1350 for (auto& satellite : gnss1Outputs->satInfo.satellites)
1351 {
1352 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1353 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag Healthy", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Healthy) ? 1 : 0); }
1354 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag Almanac", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Almanac) ? 1 : 0); }
1355 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag Ephemeris", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Ephemeris) ? 1 : 0); }
1356 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag DifferentialCorrection", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::DifferentialCorrection) ? 1 : 0); }
1357 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag UsedForNavigation", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForNavigation) ? 1 : 0); }
1358 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag AzimuthElevationValid", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::AzimuthElevationValid) ? 1 : 0); }
1359 if (descriptor == fmt::format("GNSS1::SatInfo::{} - flag UsedForRTK", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForRTK) ? 1 : 0); }
1360 if (descriptor == fmt::format("GNSS1::SatInfo::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1361 if (descriptor == fmt::format("GNSS1::SatInfo::{} - qi", satId)) { return static_cast<double>(satellite.qi); }
1362 if (descriptor == fmt::format("GNSS1::SatInfo::{} - el", satId)) { return static_cast<double>(satellite.el); }
1363 if (descriptor == fmt::format("GNSS1::SatInfo::{} - az", satId)) { return static_cast<double>(satellite.az); }
1364 }
1365 if (descriptor == "GNSS1::RawMeas::Tow [s]") { return gnss1Outputs->raw.tow; }
1366 if (descriptor == "GNSS1::RawMeas::Week") { return static_cast<double>(gnss1Outputs->raw.week); }
1367 if (descriptor == "GNSS1::RawMeas::NumSats") { return static_cast<double>(gnss1Outputs->raw.numSats); }
1368 for (auto& satellite : gnss1Outputs->raw.satellites)
1369 {
1370 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1371 if (descriptor == fmt::format("GNSS1::RawMeas::{} - freq", satId)) { return static_cast<double>(satellite.freq); }
1372 if (descriptor == fmt::format("GNSS1::RawMeas::{} - chan", satId)) { return static_cast<double>(satellite.chan); }
1373 if (descriptor == fmt::format("GNSS1::RawMeas::{} - slot", satId)) { return static_cast<double>(satellite.slot); }
1374 if (descriptor == fmt::format("GNSS1::RawMeas::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1375 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag Searching", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Searching) ? 1 : 0); }
1376 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag Tracking", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Tracking) ? 1 : 0); }
1377 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag TimeValid", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::TimeValid) ? 1 : 0); }
1378 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag CodeLock", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::CodeLock) ? 1 : 0); }
1379 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag PhaseLock", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseLock) ? 1 : 0); }
1380 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfAmbiguity", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfAmbiguity) ? 1 : 0); }
1381 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfSub", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfSub) ? 1 : 0); }
1382 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag PhaseSlip", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseSlip) ? 1 : 0); }
1383 if (descriptor == fmt::format("GNSS1::RawMeas::{} - flag PseudorangeSmoothed", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PseudorangeSmoothed) ? 1 : 0); }
1384 if (descriptor == fmt::format("GNSS1::RawMeas::{} - pr", satId)) { return satellite.pr; }
1385 if (descriptor == fmt::format("GNSS1::RawMeas::{} - cp", satId)) { return satellite.cp; }
1386 if (descriptor == fmt::format("GNSS1::RawMeas::{} - dp", satId)) { return static_cast<double>(satellite.dp); }
1387 }
1388 }
1389 // Group 5 (Attitude)
1390 if (attitudeOutputs)
1391 {
1392 if (descriptor == "Att::VpeStatus::AttitudeQuality") { return static_cast<double>(attitudeOutputs->vpeStatus.attitudeQuality()); }
1393 if (descriptor == "Att::VpeStatus::GyroSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturation()); }
1394 if (descriptor == "Att::VpeStatus::GyroSaturationRecovery") { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturationRecovery()); }
1395 if (descriptor == "Att::VpeStatus::MagDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.magDisturbance()); }
1396 if (descriptor == "Att::VpeStatus::MagSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.magSaturation()); }
1397 if (descriptor == "Att::VpeStatus::AccDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.accDisturbance()); }
1398 if (descriptor == "Att::VpeStatus::AccSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.accSaturation()); }
1399 if (descriptor == "Att::VpeStatus::KnownMagDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.knownMagDisturbance()); }
1400 if (descriptor == "Att::VpeStatus::KnownAccelDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.knownAccelDisturbance()); }
1401 if (descriptor == "Att::YawPitchRoll::Y [deg]") { return static_cast<double>(attitudeOutputs->ypr(0)); }
1402 if (descriptor == "Att::YawPitchRoll::P [deg]") { return static_cast<double>(attitudeOutputs->ypr(1)); }
1403 if (descriptor == "Att::YawPitchRoll::R [deg]") { return static_cast<double>(attitudeOutputs->ypr(2)); }
1404 if (descriptor == "Att::Quaternion::w") { return static_cast<double>(attitudeOutputs->qtn.w()); }
1405 if (descriptor == "Att::Quaternion::x") { return static_cast<double>(attitudeOutputs->qtn.x()); }
1406 if (descriptor == "Att::Quaternion::y") { return static_cast<double>(attitudeOutputs->qtn.y()); }
1407 if (descriptor == "Att::Quaternion::z") { return static_cast<double>(attitudeOutputs->qtn.z()); }
1408 if (descriptor == "Att::DCM::0-0") { return static_cast<double>(attitudeOutputs->dcm(0, 0)); }
1409 if (descriptor == "Att::DCM::0-1") { return static_cast<double>(attitudeOutputs->dcm(0, 1)); }
1410 if (descriptor == "Att::DCM::0-2") { return static_cast<double>(attitudeOutputs->dcm(0, 2)); }
1411 if (descriptor == "Att::DCM::1-0") { return static_cast<double>(attitudeOutputs->dcm(1, 0)); }
1412 if (descriptor == "Att::DCM::1-1") { return static_cast<double>(attitudeOutputs->dcm(1, 1)); }
1413 if (descriptor == "Att::DCM::1-2") { return static_cast<double>(attitudeOutputs->dcm(1, 2)); }
1414 if (descriptor == "Att::DCM::2-0") { return static_cast<double>(attitudeOutputs->dcm(2, 0)); }
1415 if (descriptor == "Att::DCM::2-1") { return static_cast<double>(attitudeOutputs->dcm(2, 1)); }
1416 if (descriptor == "Att::DCM::2-2") { return static_cast<double>(attitudeOutputs->dcm(2, 2)); }
1417 if (descriptor == "Att::MagNed::N [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(0)); }
1418 if (descriptor == "Att::MagNed::E [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(1)); }
1419 if (descriptor == "Att::MagNed::D [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(2)); }
1420 if (descriptor == "Att::AccelNed::N [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(0)); }
1421 if (descriptor == "Att::AccelNed::E [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(1)); }
1422 if (descriptor == "Att::AccelNed::D [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(2)); }
1423 if (descriptor == "Att::LinearAccelBody::X [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(0)); }
1424 if (descriptor == "Att::LinearAccelBody::Y [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(1)); }
1425 if (descriptor == "Att::LinearAccelBody::Z [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(2)); }
1426 if (descriptor == "Att::LinearAccelNed::N [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(0)); }
1427 if (descriptor == "Att::LinearAccelNed::E [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(1)); }
1428 if (descriptor == "Att::LinearAccelNed::D [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(2)); }
1429 if (descriptor == "Att::YprU::Y [deg]") { return static_cast<double>(attitudeOutputs->yprU(0)); }
1430 if (descriptor == "Att::YprU::P [deg]") { return static_cast<double>(attitudeOutputs->yprU(1)); }
1431 if (descriptor == "Att::YprU::R [deg]") { return static_cast<double>(attitudeOutputs->yprU(2)); }
1432 }
1433 // Group 6 (INS)
1434 if (insOutputs)
1435 {
1436 if (descriptor == "INS::InsStatus::Mode") { return static_cast<double>(insOutputs->insStatus.mode()); }
1437 if (descriptor == "INS::InsStatus::GpsFix") { return static_cast<double>(insOutputs->insStatus.gpsFix()); }
1438 if (descriptor == "INS::InsStatus::Error::IMU") { return static_cast<double>(insOutputs->insStatus.errorIMU()); }
1439 if (descriptor == "INS::InsStatus::Error::MagPres") { return static_cast<double>(insOutputs->insStatus.errorMagPres()); }
1440 if (descriptor == "INS::InsStatus::Error::GNSS") { return static_cast<double>(insOutputs->insStatus.errorGnss()); }
1441 if (descriptor == "INS::InsStatus::GpsHeadingIns") { return static_cast<double>(insOutputs->insStatus.gpsHeadingIns()); }
1442 if (descriptor == "INS::InsStatus::GpsCompass") { return static_cast<double>(insOutputs->insStatus.gpsCompass()); }
1443 if (descriptor == "INS::PosLla::latitude [deg]") { return static_cast<double>(insOutputs->posLla(0)); }
1444 if (descriptor == "INS::PosLla::longitude [deg]") { return static_cast<double>(insOutputs->posLla(1)); }
1445 if (descriptor == "INS::PosLla::altitude [m]") { return static_cast<double>(insOutputs->posLla(2)); }
1446 if (descriptor == "INS::PosEcef::X [m]") { return static_cast<double>(insOutputs->posEcef(0)); }
1447 if (descriptor == "INS::PosEcef::Y [m]") { return static_cast<double>(insOutputs->posEcef(1)); }
1448 if (descriptor == "INS::PosEcef::Z [m]") { return static_cast<double>(insOutputs->posEcef(2)); }
1449 if (descriptor == "INS::VelBody::X [m/s]") { return static_cast<double>(insOutputs->velBody(0)); }
1450 if (descriptor == "INS::VelBody::Y [m/s]") { return static_cast<double>(insOutputs->velBody(1)); }
1451 if (descriptor == "INS::VelBody::Z [m/s]") { return static_cast<double>(insOutputs->velBody(2)); }
1452 if (descriptor == "INS::VelNed::N [m/s]") { return static_cast<double>(insOutputs->velNed(0)); }
1453 if (descriptor == "INS::VelNed::E [m/s]") { return static_cast<double>(insOutputs->velNed(1)); }
1454 if (descriptor == "INS::VelNed::D [m/s]") { return static_cast<double>(insOutputs->velNed(2)); }
1455 if (descriptor == "INS::VelEcef::X [m/s]") { return static_cast<double>(insOutputs->velEcef(0)); }
1456 if (descriptor == "INS::VelEcef::Y [m/s]") { return static_cast<double>(insOutputs->velEcef(1)); }
1457 if (descriptor == "INS::VelEcef::Z [m/s]") { return static_cast<double>(insOutputs->velEcef(2)); }
1458 if (descriptor == "INS::MagEcef::X [Gauss]") { return static_cast<double>(insOutputs->magEcef(0)); }
1459 if (descriptor == "INS::MagEcef::Y [Gauss]") { return static_cast<double>(insOutputs->magEcef(1)); }
1460 if (descriptor == "INS::MagEcef::Z [Gauss]") { return static_cast<double>(insOutputs->magEcef(2)); }
1461 if (descriptor == "INS::AccelEcef::X [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(0)); }
1462 if (descriptor == "INS::AccelEcef::Y [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(1)); }
1463 if (descriptor == "INS::AccelEcef::Z [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(2)); }
1464 if (descriptor == "INS::LinearAccelEcef::X [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(0)); }
1465 if (descriptor == "INS::LinearAccelEcef::Y [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(1)); }
1466 if (descriptor == "INS::LinearAccelEcef::Z [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(2)); }
1467 if (descriptor == "INS::PosU [m]") { return static_cast<double>(insOutputs->posU); }
1468 if (descriptor == "INS::VelU [m/s]") { return static_cast<double>(insOutputs->velU); }
1469 }
1470 // Group 7 (GNSS2)
1471 if (gnss2Outputs)
1472 {
1473 if (descriptor == "GNSS2::UTC::year") { return static_cast<double>(gnss2Outputs->timeUtc.year); }
1474 if (descriptor == "GNSS2::UTC::month") { return static_cast<double>(gnss2Outputs->timeUtc.month); }
1475 if (descriptor == "GNSS2::UTC::day") { return static_cast<double>(gnss2Outputs->timeUtc.day); }
1476 if (descriptor == "GNSS2::UTC::hour") { return static_cast<double>(gnss2Outputs->timeUtc.hour); }
1477 if (descriptor == "GNSS2::UTC::min") { return static_cast<double>(gnss2Outputs->timeUtc.min); }
1478 if (descriptor == "GNSS2::UTC::sec") { return static_cast<double>(gnss2Outputs->timeUtc.sec); }
1479 if (descriptor == "GNSS2::UTC::ms") { return static_cast<double>(gnss2Outputs->timeUtc.ms); }
1480 if (descriptor == "GNSS2::Tow [ns]") { return static_cast<double>(gnss2Outputs->tow); }
1481 if (descriptor == "GNSS2::Week") { return static_cast<double>(gnss2Outputs->week); }
1482 if (descriptor == "GNSS2::NumSats") { return static_cast<double>(gnss2Outputs->numSats); }
1483 if (descriptor == "GNSS2::Fix") { return static_cast<double>(gnss2Outputs->fix); }
1484 if (descriptor == "GNSS2::PosLla::latitude [deg]") { return static_cast<double>(gnss2Outputs->posLla(0)); }
1485 if (descriptor == "GNSS2::PosLla::longitude [deg]") { return static_cast<double>(gnss2Outputs->posLla(1)); }
1486 if (descriptor == "GNSS2::PosLla::altitude [m]") { return static_cast<double>(gnss2Outputs->posLla(2)); }
1487 if (descriptor == "GNSS2::PosEcef::X [m]") { return static_cast<double>(gnss2Outputs->posEcef(0)); }
1488 if (descriptor == "GNSS2::PosEcef::Y [m]") { return static_cast<double>(gnss2Outputs->posEcef(1)); }
1489 if (descriptor == "GNSS2::PosEcef::Z [m]") { return static_cast<double>(gnss2Outputs->posEcef(2)); }
1490 if (descriptor == "GNSS2::VelNed::N [m/s]") { return static_cast<double>(gnss2Outputs->velNed(0)); }
1491 if (descriptor == "GNSS2::VelNed::E [m/s]") { return static_cast<double>(gnss2Outputs->velNed(1)); }
1492 if (descriptor == "GNSS2::VelNed::D [m/s]") { return static_cast<double>(gnss2Outputs->velNed(2)); }
1493 if (descriptor == "GNSS2::VelEcef::X [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(0)); }
1494 if (descriptor == "GNSS2::VelEcef::Y [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(1)); }
1495 if (descriptor == "GNSS2::VelEcef::Z [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(2)); }
1496 if (descriptor == "GNSS2::PosU::N [m]") { return static_cast<double>(gnss2Outputs->posU(0)); }
1497 if (descriptor == "GNSS2::PosU::E [m]") { return static_cast<double>(gnss2Outputs->posU(1)); }
1498 if (descriptor == "GNSS2::PosU::D [m]") { return static_cast<double>(gnss2Outputs->posU(2)); }
1499 if (descriptor == "GNSS2::VelU [m/s]") { return static_cast<double>(gnss2Outputs->velU); }
1500 if (descriptor == "GNSS2::TimeU [s]") { return static_cast<double>(gnss2Outputs->timeU); }
1501 if (descriptor == "GNSS2::TimeInfo::Status::timeOk") { return static_cast<double>(gnss2Outputs->timeInfo.status.timeOk()); }
1502 if (descriptor == "GNSS2::TimeInfo::Status::dateOk") { return static_cast<double>(gnss2Outputs->timeInfo.status.dateOk()); }
1503 if (descriptor == "GNSS2::TimeInfo::Status::utcTimeValid") { return static_cast<double>(gnss2Outputs->timeInfo.status.utcTimeValid()); }
1504 if (descriptor == "GNSS2::TimeInfo::LeapSeconds") { return static_cast<double>(gnss2Outputs->timeInfo.leapSeconds); }
1505 if (descriptor == "GNSS2::DOP::g") { return static_cast<double>(gnss2Outputs->dop.gDop); }
1506 if (descriptor == "GNSS2::DOP::p") { return static_cast<double>(gnss2Outputs->dop.pDop); }
1507 if (descriptor == "GNSS2::DOP::t") { return static_cast<double>(gnss2Outputs->dop.tDop); }
1508 if (descriptor == "GNSS2::DOP::v") { return static_cast<double>(gnss2Outputs->dop.vDop); }
1509 if (descriptor == "GNSS2::DOP::h") { return static_cast<double>(gnss2Outputs->dop.hDop); }
1510 if (descriptor == "GNSS2::DOP::n") { return static_cast<double>(gnss2Outputs->dop.nDop); }
1511 if (descriptor == "GNSS2::DOP::e") { return static_cast<double>(gnss2Outputs->dop.eDop); }
1512 if (descriptor == "GNSS2::SatInfo::NumSats") { return static_cast<double>(gnss2Outputs->satInfo.numSats); }
1513 for (auto& satellite : gnss2Outputs->satInfo.satellites)
1514 {
1515 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1516 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag Healthy", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Healthy) ? 1 : 0); }
1517 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag Almanac", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Almanac) ? 1 : 0); }
1518 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag Ephemeris", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Ephemeris) ? 1 : 0); }
1519 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag DifferentialCorrection", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::DifferentialCorrection) ? 1 : 0); }
1520 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag UsedForNavigation", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForNavigation) ? 1 : 0); }
1521 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag AzimuthElevationValid", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::AzimuthElevationValid) ? 1 : 0); }
1522 if (descriptor == fmt::format("GNSS2::SatInfo::{} - flag UsedForRTK", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForRTK) ? 1 : 0); }
1523 if (descriptor == fmt::format("GNSS2::SatInfo::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1524 if (descriptor == fmt::format("GNSS2::SatInfo::{} - qi", satId)) { return static_cast<double>(satellite.qi); }
1525 if (descriptor == fmt::format("GNSS2::SatInfo::{} - el", satId)) { return static_cast<double>(satellite.el); }
1526 if (descriptor == fmt::format("GNSS2::SatInfo::{} - az", satId)) { return static_cast<double>(satellite.az); }
1527 }
1528 if (descriptor == "GNSS2::RawMeas::Tow [s]") { return gnss2Outputs->raw.tow; }
1529 if (descriptor == "GNSS2::RawMeas::Week") { return static_cast<double>(gnss2Outputs->raw.week); }
1530 if (descriptor == "GNSS2::RawMeas::NumSats") { return static_cast<double>(gnss2Outputs->raw.numSats); }
1531 for (auto& satellite : gnss2Outputs->raw.satellites)
1532 {
1533 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1534 if (descriptor == fmt::format("GNSS2::RawMeas::{} - freq", satId)) { return static_cast<double>(satellite.freq); }
1535 if (descriptor == fmt::format("GNSS2::RawMeas::{} - chan", satId)) { return static_cast<double>(satellite.chan); }
1536 if (descriptor == fmt::format("GNSS2::RawMeas::{} - slot", satId)) { return static_cast<double>(satellite.slot); }
1537 if (descriptor == fmt::format("GNSS2::RawMeas::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1538 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag Searching", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Searching) ? 1 : 0); }
1539 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag Tracking", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Tracking) ? 1 : 0); }
1540 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag TimeValid", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::TimeValid) ? 1 : 0); }
1541 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag CodeLock", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::CodeLock) ? 1 : 0); }
1542 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag PhaseLock", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseLock) ? 1 : 0); }
1543 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfAmbiguity", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfAmbiguity) ? 1 : 0); }
1544 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfSub", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfSub) ? 1 : 0); }
1545 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag PhaseSlip", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseSlip) ? 1 : 0); }
1546 if (descriptor == fmt::format("GNSS2::RawMeas::{} - flag PseudorangeSmoothed", satId)) { return static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PseudorangeSmoothed) ? 1 : 0); }
1547 if (descriptor == fmt::format("GNSS2::RawMeas::{} - pr", satId)) { return satellite.pr; }
1548 if (descriptor == fmt::format("GNSS2::RawMeas::{} - cp", satId)) { return satellite.cp; }
1549 if (descriptor == fmt::format("GNSS2::RawMeas::{} - dp", satId)) { return static_cast<double>(satellite.dp); }
1550 }
1551 }
1552
1553 return std::nullopt;
1554 }
1555
1556 /// @brief Returns a vector of data descriptors and values for the dynamic data
1557 [[nodiscard]] std::vector<std::pair<std::string, double>> getDynamicData() const override
1558 {
1559 std::vector<std::pair<std::string, double>> dynData;
1560
1561 // Group 2 (Time)
1562 if (timeOutputs)
1563 {
1564 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTARTUP)
1565 {
1566 dynData.emplace_back("Time::TimeStartup [ns]", static_cast<double>(timeOutputs->timeStartup));
1567 }
1568 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPS)
1569 {
1570 dynData.emplace_back("Time::TimeGps [ns]", static_cast<double>(timeOutputs->timeGps));
1571 }
1572 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
1573 {
1574 dynData.emplace_back("Time::GpsTow [ns]", static_cast<double>(timeOutputs->gpsTow));
1575 }
1576 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK)
1577 {
1578 dynData.emplace_back("Time::GpsWeek", static_cast<double>(timeOutputs->gpsWeek));
1579 }
1580 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESYNCIN)
1581 {
1582 dynData.emplace_back("Time::TimeSyncIn [ns]", static_cast<double>(timeOutputs->timeSyncIn));
1583 }
1584 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPSPPS)
1585 {
1586 dynData.emplace_back("Time::TimeGpsPps [ns]", static_cast<double>(timeOutputs->timePPS));
1587 }
1588 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)
1589 {
1590 dynData.emplace_back("Time::TimeUTC::year", static_cast<double>(timeOutputs->timeUtc.year));
1591 dynData.emplace_back("Time::TimeUTC::month", static_cast<double>(timeOutputs->timeUtc.month));
1592 dynData.emplace_back("Time::TimeUTC::day", static_cast<double>(timeOutputs->timeUtc.day));
1593 dynData.emplace_back("Time::TimeUTC::hour", static_cast<double>(timeOutputs->timeUtc.hour));
1594 dynData.emplace_back("Time::TimeUTC::min", static_cast<double>(timeOutputs->timeUtc.min));
1595 dynData.emplace_back("Time::TimeUTC::sec", static_cast<double>(timeOutputs->timeUtc.sec));
1596 dynData.emplace_back("Time::TimeUTC::ms", static_cast<double>(timeOutputs->timeUtc.ms));
1597 }
1598 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCINCNT)
1599 {
1600 dynData.emplace_back("Time::SyncInCnt", static_cast<double>(timeOutputs->syncInCnt));
1601 }
1602 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCOUTCNT)
1603 {
1604 dynData.emplace_back("Time::SyncOutCnt", static_cast<double>(timeOutputs->syncOutCnt));
1605 }
1606 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
1607 {
1608 dynData.emplace_back("Time::TimeStatus::timeOk", static_cast<double>(timeOutputs->timeStatus.timeOk()));
1609 dynData.emplace_back("Time::TimeStatus::dateOk", static_cast<double>(timeOutputs->timeStatus.dateOk()));
1610 dynData.emplace_back("Time::TimeStatus::utcTimeValid", static_cast<double>(timeOutputs->timeStatus.utcTimeValid()));
1611 }
1612 }
1613 // Group 3 (IMU)
1614 if (imuOutputs)
1615 {
1616 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_IMUSTATUS)
1617 {
1618 dynData.emplace_back("IMU::ImuStatus", static_cast<double>(imuOutputs->imuStatus));
1619 }
1620 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
1621 {
1622 dynData.emplace_back("IMU::UncompMag::X [Gauss]", static_cast<double>(imuOutputs->uncompMag(0)));
1623 dynData.emplace_back("IMU::UncompMag::Y [Gauss]", static_cast<double>(imuOutputs->uncompMag(1)));
1624 dynData.emplace_back("IMU::UncompMag::Z [Gauss]", static_cast<double>(imuOutputs->uncompMag(2)));
1625 }
1626 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
1627 {
1628 dynData.emplace_back("IMU::UncompAccel::X [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(0)));
1629 dynData.emplace_back("IMU::UncompAccel::Y [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(1)));
1630 dynData.emplace_back("IMU::UncompAccel::Z [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(2)));
1631 }
1632 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
1633 {
1634 dynData.emplace_back("IMU::UncompGyro::X [rad/s]", static_cast<double>(imuOutputs->uncompGyro(0)));
1635 dynData.emplace_back("IMU::UncompGyro::Y [rad/s]", static_cast<double>(imuOutputs->uncompGyro(1)));
1636 dynData.emplace_back("IMU::UncompGyro::Z [rad/s]", static_cast<double>(imuOutputs->uncompGyro(2)));
1637 }
1638 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
1639 {
1640 dynData.emplace_back("IMU::Temp [Celsius]", static_cast<double>(imuOutputs->temp));
1641 }
1642 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)
1643 {
1644 dynData.emplace_back("IMU::Pres [kPa]", static_cast<double>(imuOutputs->pres));
1645 }
1646 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)
1647 {
1648 dynData.emplace_back("IMU::DeltaTime [s]", static_cast<double>(imuOutputs->deltaTime));
1649 dynData.emplace_back("IMU::DeltaTheta::X [deg]", static_cast<double>(imuOutputs->deltaTheta(0)));
1650 dynData.emplace_back("IMU::DeltaTheta::Y [deg]", static_cast<double>(imuOutputs->deltaTheta(1)));
1651 dynData.emplace_back("IMU::DeltaTheta::Z [deg]", static_cast<double>(imuOutputs->deltaTheta(2)));
1652 }
1653 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)
1654 {
1655 dynData.emplace_back("IMU::DeltaVel::X [m/s]", static_cast<double>(imuOutputs->deltaV(0)));
1656 dynData.emplace_back("IMU::DeltaVel::Y [m/s]", static_cast<double>(imuOutputs->deltaV(1)));
1657 dynData.emplace_back("IMU::DeltaVel::Z [m/s]", static_cast<double>(imuOutputs->deltaV(2)));
1658 }
1659 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
1660 {
1661 dynData.emplace_back("IMU::Mag::X [Gauss]", static_cast<double>(imuOutputs->mag(0)));
1662 dynData.emplace_back("IMU::Mag::Y [Gauss]", static_cast<double>(imuOutputs->mag(1)));
1663 dynData.emplace_back("IMU::Mag::Z [Gauss]", static_cast<double>(imuOutputs->mag(2)));
1664 }
1665 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
1666 {
1667 dynData.emplace_back("IMU::Accel::X [m/s^2]", static_cast<double>(imuOutputs->accel(0)));
1668 dynData.emplace_back("IMU::Accel::Y [m/s^2]", static_cast<double>(imuOutputs->accel(1)));
1669 dynData.emplace_back("IMU::Accel::Z [m/s^2]", static_cast<double>(imuOutputs->accel(2)));
1670 }
1671 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
1672 {
1673 dynData.emplace_back("IMU::AngularRate::X [rad/s]", static_cast<double>(imuOutputs->angularRate(0)));
1674 dynData.emplace_back("IMU::AngularRate::Y [rad/s]", static_cast<double>(imuOutputs->angularRate(1)));
1675 dynData.emplace_back("IMU::AngularRate::Z [rad/s]", static_cast<double>(imuOutputs->angularRate(2)));
1676 }
1677 }
1678
1679 // Group 4 (GNSS1)
1680 if (gnss1Outputs)
1681 {
1682 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1683 {
1684 dynData.emplace_back("GNSS1::UTC::year", static_cast<double>(gnss1Outputs->timeUtc.year));
1685 dynData.emplace_back("GNSS1::UTC::month", static_cast<double>(gnss1Outputs->timeUtc.month));
1686 dynData.emplace_back("GNSS1::UTC::day", static_cast<double>(gnss1Outputs->timeUtc.day));
1687 dynData.emplace_back("GNSS1::UTC::hour", static_cast<double>(gnss1Outputs->timeUtc.hour));
1688 dynData.emplace_back("GNSS1::UTC::min", static_cast<double>(gnss1Outputs->timeUtc.min));
1689 dynData.emplace_back("GNSS1::UTC::sec", static_cast<double>(gnss1Outputs->timeUtc.sec));
1690 dynData.emplace_back("GNSS1::UTC::ms", static_cast<double>(gnss1Outputs->timeUtc.ms));
1691 }
1692 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1693 {
1694 dynData.emplace_back("GNSS1::Tow [ns]", static_cast<double>(gnss1Outputs->tow));
1695 }
1696 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1697 {
1698 dynData.emplace_back("GNSS1::Week", static_cast<double>(gnss1Outputs->week));
1699 }
1700 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1701 {
1702 dynData.emplace_back("GNSS1::NumSats", static_cast<double>(gnss1Outputs->numSats));
1703 }
1704 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1705 {
1706 dynData.emplace_back("GNSS1::Fix", static_cast<double>(gnss1Outputs->fix));
1707 }
1708 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1709 {
1710 dynData.emplace_back("GNSS1::PosLla::latitude [deg]", static_cast<double>(gnss1Outputs->posLla(0)));
1711 dynData.emplace_back("GNSS1::PosLla::longitude [deg]", static_cast<double>(gnss1Outputs->posLla(1)));
1712 dynData.emplace_back("GNSS1::PosLla::altitude [m]", static_cast<double>(gnss1Outputs->posLla(2)));
1713 }
1714 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1715 {
1716 dynData.emplace_back("GNSS1::PosEcef::X [m]", static_cast<double>(gnss1Outputs->posEcef(0)));
1717 dynData.emplace_back("GNSS1::PosEcef::Y [m]", static_cast<double>(gnss1Outputs->posEcef(1)));
1718 dynData.emplace_back("GNSS1::PosEcef::Z [m]", static_cast<double>(gnss1Outputs->posEcef(2)));
1719 }
1720 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
1721 {
1722 dynData.emplace_back("GNSS1::VelNed::N [m/s]", static_cast<double>(gnss1Outputs->velNed(0)));
1723 dynData.emplace_back("GNSS1::VelNed::E [m/s]", static_cast<double>(gnss1Outputs->velNed(1)));
1724 dynData.emplace_back("GNSS1::VelNed::D [m/s]", static_cast<double>(gnss1Outputs->velNed(2)));
1725 }
1726 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
1727 {
1728 dynData.emplace_back("GNSS1::VelEcef::X [m/s]", static_cast<double>(gnss1Outputs->velEcef(0)));
1729 dynData.emplace_back("GNSS1::VelEcef::Y [m/s]", static_cast<double>(gnss1Outputs->velEcef(1)));
1730 dynData.emplace_back("GNSS1::VelEcef::Z [m/s]", static_cast<double>(gnss1Outputs->velEcef(2)));
1731 }
1732 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
1733 {
1734 dynData.emplace_back("GNSS1::PosU::N [m]", static_cast<double>(gnss1Outputs->posU(0)));
1735 dynData.emplace_back("GNSS1::PosU::E [m]", static_cast<double>(gnss1Outputs->posU(1)));
1736 dynData.emplace_back("GNSS1::PosU::D [m]", static_cast<double>(gnss1Outputs->posU(2)));
1737 }
1738 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
1739 {
1740 dynData.emplace_back("GNSS1::VelU [m/s]", static_cast<double>(gnss1Outputs->velU));
1741 }
1742 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
1743 {
1744 dynData.emplace_back("GNSS1::TimeU [s]", static_cast<double>(gnss1Outputs->timeU));
1745 }
1746 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
1747 {
1748 dynData.emplace_back("GNSS1::TimeInfo::Status::timeOk", static_cast<double>(gnss1Outputs->timeInfo.status.timeOk()));
1749 dynData.emplace_back("GNSS1::TimeInfo::Status::dateOk", static_cast<double>(gnss1Outputs->timeInfo.status.dateOk()));
1750 dynData.emplace_back("GNSS1::TimeInfo::Status::utcTimeValid", static_cast<double>(gnss1Outputs->timeInfo.status.utcTimeValid()));
1751 dynData.emplace_back("GNSS1::TimeInfo::LeapSeconds", static_cast<double>(gnss1Outputs->timeInfo.leapSeconds));
1752 }
1753 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
1754 {
1755 dynData.emplace_back("GNSS1::DOP::g", static_cast<double>(gnss1Outputs->dop.gDop));
1756 dynData.emplace_back("GNSS1::DOP::p", static_cast<double>(gnss1Outputs->dop.pDop));
1757 dynData.emplace_back("GNSS1::DOP::t", static_cast<double>(gnss1Outputs->dop.tDop));
1758 dynData.emplace_back("GNSS1::DOP::v", static_cast<double>(gnss1Outputs->dop.vDop));
1759 dynData.emplace_back("GNSS1::DOP::h", static_cast<double>(gnss1Outputs->dop.hDop));
1760 dynData.emplace_back("GNSS1::DOP::n", static_cast<double>(gnss1Outputs->dop.nDop));
1761 dynData.emplace_back("GNSS1::DOP::e", static_cast<double>(gnss1Outputs->dop.eDop));
1762 }
1763 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
1764 {
1765 dynData.emplace_back("GNSS1::SatInfo::NumSats", static_cast<double>(gnss1Outputs->satInfo.numSats));
1766 for (auto& satellite : gnss1Outputs->satInfo.satellites)
1767 {
1768 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1769 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag Healthy", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Healthy) ? 1 : 0));
1770 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag Almanac", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Almanac) ? 1 : 0));
1771 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag Ephemeris", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Ephemeris) ? 1 : 0));
1772 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag DifferentialCorrection", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::DifferentialCorrection) ? 1 : 0));
1773 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForNavigation", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForNavigation) ? 1 : 0));
1774 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag AzimuthElevationValid", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::AzimuthElevationValid) ? 1 : 0));
1775 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForRTK", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForRTK) ? 1 : 0));
1776 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - cno", satId), static_cast<double>(satellite.cno));
1777 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - qi", satId), static_cast<double>(satellite.qi));
1778 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - el", satId), static_cast<double>(satellite.el));
1779 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - az", satId), static_cast<double>(satellite.az));
1780 }
1781 }
1782 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
1783 {
1784 dynData.emplace_back("GNSS1::RawMeas::Tow [s]", gnss1Outputs->raw.tow);
1785 dynData.emplace_back("GNSS1::RawMeas::Week", static_cast<double>(gnss1Outputs->raw.week));
1786 dynData.emplace_back("GNSS1::RawMeas::NumSats", static_cast<double>(gnss1Outputs->raw.numSats));
1787 for (auto& satellite : gnss1Outputs->raw.satellites)
1788 {
1789 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1790 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - freq", satId), static_cast<double>(satellite.freq));
1791 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - chan", satId), static_cast<double>(satellite.chan));
1792 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - slot", satId), static_cast<double>(satellite.slot));
1793 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - cno", satId), static_cast<double>(satellite.cno));
1794 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag Searching", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Searching) ? 1 : 0));
1795 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag Tracking", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Tracking) ? 1 : 0));
1796 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag TimeValid", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::TimeValid) ? 1 : 0));
1797 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag CodeLock", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::CodeLock) ? 1 : 0));
1798 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseLock", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseLock) ? 1 : 0));
1799 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfAmbiguity", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfAmbiguity) ? 1 : 0));
1800 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfSub", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfSub) ? 1 : 0));
1801 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseSlip", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseSlip) ? 1 : 0));
1802 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - flag PseudorangeSmoothed", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PseudorangeSmoothed) ? 1 : 0));
1803 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - pr", satId), satellite.pr);
1804 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - cp", satId), satellite.cp);
1805 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - dp", satId), static_cast<double>(satellite.dp));
1806 }
1807 }
1808 }
1809
1810 // Group 5 (Attitude)
1811 if (attitudeOutputs)
1812 {
1813 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)
1814 {
1815 dynData.emplace_back("Att::VpeStatus::AttitudeQuality", static_cast<double>(attitudeOutputs->vpeStatus.attitudeQuality()));
1816 dynData.emplace_back("Att::VpeStatus::GyroSaturation", static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturation()));
1817 dynData.emplace_back("Att::VpeStatus::GyroSaturationRecovery", static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturationRecovery()));
1818 dynData.emplace_back("Att::VpeStatus::MagDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.magDisturbance()));
1819 dynData.emplace_back("Att::VpeStatus::MagSaturation", static_cast<double>(attitudeOutputs->vpeStatus.magSaturation()));
1820 dynData.emplace_back("Att::VpeStatus::AccDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.accDisturbance()));
1821 dynData.emplace_back("Att::VpeStatus::AccSaturation", static_cast<double>(attitudeOutputs->vpeStatus.accSaturation()));
1822 dynData.emplace_back("Att::VpeStatus::KnownMagDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.knownMagDisturbance()));
1823 dynData.emplace_back("Att::VpeStatus::KnownAccelDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.knownAccelDisturbance()));
1824 }
1825 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)
1826 {
1827 dynData.emplace_back("Att::YawPitchRoll::Y [deg]", static_cast<double>(attitudeOutputs->ypr(0)));
1828 dynData.emplace_back("Att::YawPitchRoll::P [deg]", static_cast<double>(attitudeOutputs->ypr(1)));
1829 dynData.emplace_back("Att::YawPitchRoll::R [deg]", static_cast<double>(attitudeOutputs->ypr(2)));
1830 }
1831 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)
1832 {
1833 dynData.emplace_back("Att::Quaternion::w", static_cast<double>(attitudeOutputs->qtn.w()));
1834 dynData.emplace_back("Att::Quaternion::x", static_cast<double>(attitudeOutputs->qtn.x()));
1835 dynData.emplace_back("Att::Quaternion::y", static_cast<double>(attitudeOutputs->qtn.y()));
1836 dynData.emplace_back("Att::Quaternion::z", static_cast<double>(attitudeOutputs->qtn.z()));
1837 }
1838 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)
1839 {
1840 dynData.emplace_back("Att::DCM::0-0", static_cast<double>(attitudeOutputs->dcm(0, 0)));
1841 dynData.emplace_back("Att::DCM::0-1", static_cast<double>(attitudeOutputs->dcm(0, 1)));
1842 dynData.emplace_back("Att::DCM::0-2", static_cast<double>(attitudeOutputs->dcm(0, 2)));
1843 dynData.emplace_back("Att::DCM::1-0", static_cast<double>(attitudeOutputs->dcm(1, 0)));
1844 dynData.emplace_back("Att::DCM::1-1", static_cast<double>(attitudeOutputs->dcm(1, 1)));
1845 dynData.emplace_back("Att::DCM::1-2", static_cast<double>(attitudeOutputs->dcm(1, 2)));
1846 dynData.emplace_back("Att::DCM::2-0", static_cast<double>(attitudeOutputs->dcm(2, 0)));
1847 dynData.emplace_back("Att::DCM::2-1", static_cast<double>(attitudeOutputs->dcm(2, 1)));
1848 dynData.emplace_back("Att::DCM::2-2", static_cast<double>(attitudeOutputs->dcm(2, 2)));
1849 }
1850 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)
1851 {
1852 dynData.emplace_back("Att::MagNed::N [Gauss]", static_cast<double>(attitudeOutputs->magNed(0)));
1853 dynData.emplace_back("Att::MagNed::E [Gauss]", static_cast<double>(attitudeOutputs->magNed(1)));
1854 dynData.emplace_back("Att::MagNed::D [Gauss]", static_cast<double>(attitudeOutputs->magNed(2)));
1855 }
1856 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)
1857 {
1858 dynData.emplace_back("Att::AccelNed::N [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(0)));
1859 dynData.emplace_back("Att::AccelNed::E [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(1)));
1860 dynData.emplace_back("Att::AccelNed::D [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(2)));
1861 }
1862 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)
1863 {
1864 dynData.emplace_back("Att::LinearAccelBody::X [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(0)));
1865 dynData.emplace_back("Att::LinearAccelBody::Y [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(1)));
1866 dynData.emplace_back("Att::LinearAccelBody::Z [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(2)));
1867 }
1868 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)
1869 {
1870 dynData.emplace_back("Att::LinearAccelNed::N [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(0)));
1871 dynData.emplace_back("Att::LinearAccelNed::E [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(1)));
1872 dynData.emplace_back("Att::LinearAccelNed::D [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(2)));
1873 }
1874 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)
1875 {
1876 dynData.emplace_back("Att::YprU::Y [deg]", static_cast<double>(attitudeOutputs->yprU(0)));
1877 dynData.emplace_back("Att::YprU::P [deg]", static_cast<double>(attitudeOutputs->yprU(1)));
1878 dynData.emplace_back("Att::YprU::R [deg]", static_cast<double>(attitudeOutputs->yprU(2)));
1879 }
1880 }
1881
1882 // Group 6 (INS)
1883 if (insOutputs)
1884 {
1885 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)
1886 {
1887 dynData.emplace_back("INS::InsStatus::Mode", static_cast<double>(insOutputs->insStatus.mode()));
1888 dynData.emplace_back("INS::InsStatus::GpsFix", static_cast<double>(insOutputs->insStatus.gpsFix()));
1889 dynData.emplace_back("INS::InsStatus::Error::IMU", static_cast<double>(insOutputs->insStatus.errorIMU()));
1890 dynData.emplace_back("INS::InsStatus::Error::MagPres", static_cast<double>(insOutputs->insStatus.errorMagPres()));
1891 dynData.emplace_back("INS::InsStatus::Error::GNSS", static_cast<double>(insOutputs->insStatus.errorGnss()));
1892 dynData.emplace_back("INS::InsStatus::GpsHeadingIns", static_cast<double>(insOutputs->insStatus.gpsHeadingIns()));
1893 dynData.emplace_back("INS::InsStatus::GpsCompass", static_cast<double>(insOutputs->insStatus.gpsCompass()));
1894 }
1895 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)
1896 {
1897 dynData.emplace_back("INS::PosLla::latitude [deg]", static_cast<double>(insOutputs->posLla(0)));
1898 dynData.emplace_back("INS::PosLla::longitude [deg]", static_cast<double>(insOutputs->posLla(1)));
1899 dynData.emplace_back("INS::PosLla::altitude [m]", static_cast<double>(insOutputs->posLla(2)));
1900 }
1901 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)
1902 {
1903 dynData.emplace_back("INS::PosEcef::X [m]", static_cast<double>(insOutputs->posEcef(0)));
1904 dynData.emplace_back("INS::PosEcef::Y [m]", static_cast<double>(insOutputs->posEcef(1)));
1905 dynData.emplace_back("INS::PosEcef::Z [m]", static_cast<double>(insOutputs->posEcef(2)));
1906 }
1907 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)
1908 {
1909 dynData.emplace_back("INS::VelBody::X [m/s]", static_cast<double>(insOutputs->velBody(0)));
1910 dynData.emplace_back("INS::VelBody::Y [m/s]", static_cast<double>(insOutputs->velBody(1)));
1911 dynData.emplace_back("INS::VelBody::Z [m/s]", static_cast<double>(insOutputs->velBody(2)));
1912 }
1913 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)
1914 {
1915 dynData.emplace_back("INS::VelNed::N [m/s]", static_cast<double>(insOutputs->velNed(0)));
1916 dynData.emplace_back("INS::VelNed::E [m/s]", static_cast<double>(insOutputs->velNed(1)));
1917 dynData.emplace_back("INS::VelNed::D [m/s]", static_cast<double>(insOutputs->velNed(2)));
1918 }
1919 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)
1920 {
1921 dynData.emplace_back("INS::VelEcef::X [m/s]", static_cast<double>(insOutputs->velEcef(0)));
1922 dynData.emplace_back("INS::VelEcef::Y [m/s]", static_cast<double>(insOutputs->velEcef(1)));
1923 dynData.emplace_back("INS::VelEcef::Z [m/s]", static_cast<double>(insOutputs->velEcef(2)));
1924 }
1925 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)
1926 {
1927 dynData.emplace_back("INS::MagEcef::X [Gauss]", static_cast<double>(insOutputs->magEcef(0)));
1928 dynData.emplace_back("INS::MagEcef::Y [Gauss]", static_cast<double>(insOutputs->magEcef(1)));
1929 dynData.emplace_back("INS::MagEcef::Z [Gauss]", static_cast<double>(insOutputs->magEcef(2)));
1930 }
1931 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)
1932 {
1933 dynData.emplace_back("INS::AccelEcef::X [m/s^2]", static_cast<double>(insOutputs->accelEcef(0)));
1934 dynData.emplace_back("INS::AccelEcef::Y [m/s^2]", static_cast<double>(insOutputs->accelEcef(1)));
1935 dynData.emplace_back("INS::AccelEcef::Z [m/s^2]", static_cast<double>(insOutputs->accelEcef(2)));
1936 }
1937 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)
1938 {
1939 dynData.emplace_back("INS::LinearAccelEcef::X [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(0)));
1940 dynData.emplace_back("INS::LinearAccelEcef::Y [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(1)));
1941 dynData.emplace_back("INS::LinearAccelEcef::Z [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(2)));
1942 }
1943 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSU)
1944 {
1945 dynData.emplace_back("INS::PosU [m]", static_cast<double>(insOutputs->posU));
1946 }
1947 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELU)
1948 {
1949 dynData.emplace_back("INS::VelU [m/s]", static_cast<double>(insOutputs->velU));
1950 }
1951 }
1952
1953 // Group 7 (GNSS2)
1954 if (gnss2Outputs)
1955 {
1956 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1957 {
1958 dynData.emplace_back("GNSS2::UTC::year", static_cast<double>(gnss2Outputs->timeUtc.year));
1959 dynData.emplace_back("GNSS2::UTC::month", static_cast<double>(gnss2Outputs->timeUtc.month));
1960 dynData.emplace_back("GNSS2::UTC::day", static_cast<double>(gnss2Outputs->timeUtc.day));
1961 dynData.emplace_back("GNSS2::UTC::hour", static_cast<double>(gnss2Outputs->timeUtc.hour));
1962 dynData.emplace_back("GNSS2::UTC::min", static_cast<double>(gnss2Outputs->timeUtc.min));
1963 dynData.emplace_back("GNSS2::UTC::sec", static_cast<double>(gnss2Outputs->timeUtc.sec));
1964 dynData.emplace_back("GNSS2::UTC::ms", static_cast<double>(gnss2Outputs->timeUtc.ms));
1965 }
1966 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1967 {
1968 dynData.emplace_back("GNSS2::Tow [ns]", static_cast<double>(gnss2Outputs->tow));
1969 }
1970 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1971 {
1972 dynData.emplace_back("GNSS2::Week", static_cast<double>(gnss2Outputs->week));
1973 }
1974 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1975 {
1976 dynData.emplace_back("GNSS2::NumSats", static_cast<double>(gnss2Outputs->numSats));
1977 }
1978 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1979 {
1980 dynData.emplace_back("GNSS2::Fix", static_cast<double>(gnss2Outputs->fix));
1981 }
1982 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1983 {
1984 dynData.emplace_back("GNSS2::PosLla::latitude [deg]", static_cast<double>(gnss2Outputs->posLla(0)));
1985 dynData.emplace_back("GNSS2::PosLla::longitude [deg]", static_cast<double>(gnss2Outputs->posLla(1)));
1986 dynData.emplace_back("GNSS2::PosLla::altitude [m]", static_cast<double>(gnss2Outputs->posLla(2)));
1987 }
1988 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1989 {
1990 dynData.emplace_back("GNSS2::PosEcef::X [m]", static_cast<double>(gnss2Outputs->posEcef(0)));
1991 dynData.emplace_back("GNSS2::PosEcef::Y [m]", static_cast<double>(gnss2Outputs->posEcef(1)));
1992 dynData.emplace_back("GNSS2::PosEcef::Z [m]", static_cast<double>(gnss2Outputs->posEcef(2)));
1993 }
1994 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
1995 {
1996 dynData.emplace_back("GNSS2::VelNed::N [m/s]", static_cast<double>(gnss2Outputs->velNed(0)));
1997 dynData.emplace_back("GNSS2::VelNed::E [m/s]", static_cast<double>(gnss2Outputs->velNed(1)));
1998 dynData.emplace_back("GNSS2::VelNed::D [m/s]", static_cast<double>(gnss2Outputs->velNed(2)));
1999 }
2000 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
2001 {
2002 dynData.emplace_back("GNSS2::VelEcef::X [m/s]", static_cast<double>(gnss2Outputs->velEcef(0)));
2003 dynData.emplace_back("GNSS2::VelEcef::Y [m/s]", static_cast<double>(gnss2Outputs->velEcef(1)));
2004 dynData.emplace_back("GNSS2::VelEcef::Z [m/s]", static_cast<double>(gnss2Outputs->velEcef(2)));
2005 }
2006 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
2007 {
2008 dynData.emplace_back("GNSS2::PosU::N [m]", static_cast<double>(gnss2Outputs->posU(0)));
2009 dynData.emplace_back("GNSS2::PosU::E [m]", static_cast<double>(gnss2Outputs->posU(1)));
2010 dynData.emplace_back("GNSS2::PosU::D [m]", static_cast<double>(gnss2Outputs->posU(2)));
2011 }
2012 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
2013 {
2014 dynData.emplace_back("GNSS2::VelU [m/s]", static_cast<double>(gnss2Outputs->velU));
2015 }
2016 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
2017 {
2018 dynData.emplace_back("GNSS2::TimeU [s]", static_cast<double>(gnss2Outputs->timeU));
2019 }
2020 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
2021 {
2022 dynData.emplace_back("GNSS2::TimeInfo::Status::timeOk", static_cast<double>(gnss2Outputs->timeInfo.status.timeOk()));
2023 dynData.emplace_back("GNSS2::TimeInfo::Status::dateOk", static_cast<double>(gnss2Outputs->timeInfo.status.dateOk()));
2024 dynData.emplace_back("GNSS2::TimeInfo::Status::utcTimeValid", static_cast<double>(gnss2Outputs->timeInfo.status.utcTimeValid()));
2025 dynData.emplace_back("GNSS2::TimeInfo::LeapSeconds", static_cast<double>(gnss2Outputs->timeInfo.leapSeconds));
2026 }
2027 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
2028 {
2029 dynData.emplace_back("GNSS2::DOP::g", static_cast<double>(gnss2Outputs->dop.gDop));
2030 dynData.emplace_back("GNSS2::DOP::p", static_cast<double>(gnss2Outputs->dop.pDop));
2031 dynData.emplace_back("GNSS2::DOP::t", static_cast<double>(gnss2Outputs->dop.tDop));
2032 dynData.emplace_back("GNSS2::DOP::v", static_cast<double>(gnss2Outputs->dop.vDop));
2033 dynData.emplace_back("GNSS2::DOP::h", static_cast<double>(gnss2Outputs->dop.hDop));
2034 dynData.emplace_back("GNSS2::DOP::n", static_cast<double>(gnss2Outputs->dop.nDop));
2035 dynData.emplace_back("GNSS2::DOP::e", static_cast<double>(gnss2Outputs->dop.eDop));
2036 }
2037 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
2038 {
2039 dynData.emplace_back("GNSS2::SatInfo::NumSats", static_cast<double>(gnss2Outputs->satInfo.numSats));
2040 for (auto& satellite : gnss2Outputs->satInfo.satellites)
2041 {
2042 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
2043 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag Healthy", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Healthy) ? 1 : 0));
2044 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag Almanac", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Almanac) ? 1 : 0));
2045 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag Ephemeris", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::Ephemeris) ? 1 : 0));
2046 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag DifferentialCorrection", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::DifferentialCorrection) ? 1 : 0));
2047 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForNavigation", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForNavigation) ? 1 : 0));
2048 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag AzimuthElevationValid", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::AzimuthElevationValid) ? 1 : 0));
2049 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForRTK", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::SatInfo::SatInfoElement::Flags::UsedForRTK) ? 1 : 0));
2050 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - cno", satId), static_cast<double>(satellite.cno));
2051 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - qi", satId), static_cast<double>(satellite.qi));
2052 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - el", satId), static_cast<double>(satellite.el));
2053 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - az", satId), static_cast<double>(satellite.az));
2054 }
2055 }
2056 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
2057 {
2058 dynData.emplace_back("GNSS2::RawMeas::Tow [s]", gnss2Outputs->raw.tow);
2059 dynData.emplace_back("GNSS2::RawMeas::Week", static_cast<double>(gnss2Outputs->raw.week));
2060 dynData.emplace_back("GNSS2::RawMeas::NumSats", static_cast<double>(gnss2Outputs->raw.numSats));
2061 for (auto& satellite : gnss2Outputs->raw.satellites)
2062 {
2063 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
2064 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - freq", satId), static_cast<double>(satellite.freq));
2065 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - chan", satId), static_cast<double>(satellite.chan));
2066 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - slot", satId), static_cast<double>(satellite.slot));
2067 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - cno", satId), static_cast<double>(satellite.cno));
2068 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag Searching", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Searching) ? 1 : 0));
2069 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag Tracking", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::Tracking) ? 1 : 0));
2070 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag TimeValid", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::TimeValid) ? 1 : 0));
2071 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag CodeLock", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::CodeLock) ? 1 : 0));
2072 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseLock", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseLock) ? 1 : 0));
2073 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfAmbiguity", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfAmbiguity) ? 1 : 0));
2074 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfSub", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseHalfSub) ? 1 : 0));
2075 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseSlip", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PhaseSlip) ? 1 : 0));
2076 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - flag PseudorangeSmoothed", satId), static_cast<double>(static_cast<unsigned int>(satellite.flags & NAV::vendor::vectornav::RawMeas::SatRawElement::Flags::PseudorangeSmoothed) ? 1 : 0));
2077 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - pr", satId), satellite.pr);
2078 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - cp", satId), satellite.cp);
2079 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - dp", satId), static_cast<double>(satellite.dp));
2080 }
2081 }
2082 }
2083
2084 return dynData;
2085 }
2086
2087 // ------------------------------------------ Public members ---------------------------------------------
2088
2089 /// @brief Binary Group 2 - Time Outputs
2090 std::shared_ptr<vendor::vectornav::TimeOutputs> timeOutputs = nullptr;
2091
2092 /// @brief Binary Group 3 - IMU Outputs
2093 std::shared_ptr<vendor::vectornav::ImuOutputs> imuOutputs = nullptr;
2094
2095 /// @brief Binary Group 4 - GNSS1 Outputs
2096 std::shared_ptr<vendor::vectornav::GnssOutputs> gnss1Outputs = nullptr;
2097
2098 /// @brief Binary Group 5 - Attitude Outputs
2099 std::shared_ptr<vendor::vectornav::AttitudeOutputs> attitudeOutputs = nullptr;
2100
2101 /// @brief Binary Group 6 - INS Outputs
2102 std::shared_ptr<vendor::vectornav::InsOutputs> insOutputs = nullptr;
2103
2104 /// @brief Binary Group 7 - GNSS2 Outputs
2105 std::shared_ptr<vendor::vectornav::GnssOutputs> gnss2Outputs = nullptr;
2106
2107 /// Position and rotation information for conversion from platform to body frame
2109};
2110
2111} // namespace NAV
#define INS_ASSERT(_EXPR)
Assert function wrapper.
Definition Assert.h:19
Vector space operations.
Imu Position Data.
Abstract NodeData Class.
Structs identifying a unique satellite.
GNSS Satellite System.
Binary Group 5 - Attitude Outputs.
Type Definitions for VectorNav messages.
IMU Position.
Definition ImuPos.hpp:26
NodeData()=default
Default constructor.
static std::string type()
Returns the type of the data class.
Definition NodeData.hpp:45
std::optional< double > getValueAt(size_t idx) const override
Get the value at the index.
std::shared_ptr< vendor::vectornav::TimeOutputs > timeOutputs
Binary Group 2 - Time Outputs.
std::string getType() const override
Returns the type of the data class.
VectorNavBinaryOutput(const ImuPos &imuPos)
Constructor.
std::shared_ptr< vendor::vectornav::ImuOutputs > imuOutputs
Binary Group 3 - IMU Outputs.
static constexpr size_t GetStaticDescriptorCount()
Get the amount of descriptors.
std::shared_ptr< vendor::vectornav::InsOutputs > insOutputs
Binary Group 6 - INS Outputs.
static std::vector< std::string > GetStaticDataDescriptors()
Returns a vector of data descriptors.
static std::string type()
Returns the type of the data class.
static SatelliteSystem getSatSys(vendor::vectornav::SatSys &sys)
Get the Sat Sys object in "INSTINCT" format.
static std::vector< std::string > parentTypes()
Returns the parent types of the data class.
std::vector< std::pair< std::string, double > > getDynamicData() const override
Returns a vector of data descriptors and values for the dynamic data.
std::vector< std::string > staticDataDescriptors() const override
Returns a vector of data descriptors.
std::vector< std::string > dynamicDataDescriptors() const override
Returns a vector of data descriptors for the dynamic data.
const ImuPos & imuPos
Position and rotation information for conversion from platform to body frame.
std::shared_ptr< vendor::vectornav::GnssOutputs > gnss2Outputs
Binary Group 7 - GNSS2 Outputs.
std::optional< double > getDynamicDataAt(const std::string &descriptor) const override
Get the value for the descriptor.
size_t staticDescriptorCount() const override
Get the amount of descriptors.
std::shared_ptr< vendor::vectornav::GnssOutputs > gnss1Outputs
Binary Group 4 - GNSS1 Outputs.
std::shared_ptr< vendor::vectornav::AttitudeOutputs > attitudeOutputs
Binary Group 5 - Attitude Outputs.
SatelliteSystem toSatelliteSystem(SatSys sys)
Converts the VectorNav satellite system to the INSTINCT representation.
SatSys
Satellite Constellation.
Identifies a satellite (satellite system and number)
Identifies a satellite signal (satellite frequency and number)
Satellite System type.