0.3.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
13
14#pragma once
15
16#include <cmath>
17#include <memory>
18
20#include "NodeData/NodeData.hpp"
22#include "util/Eigen.hpp"
24
26#include "util/Vendor/VectorNav/BinaryOutputs/ImuOutputs.hpp"
27#include "util/Vendor/VectorNav/BinaryOutputs/GnssOutputs.hpp"
28#include "util/Vendor/VectorNav/BinaryOutputs/AttitudeOutputs.hpp"
29#include "util/Vendor/VectorNav/BinaryOutputs/InsOutputs.hpp"
31#include <fmt/core.h>
32#include <sys/types.h>
33#include <vn/types.h>
34
35namespace NAV
36{
39{
40 public:
44 : imuPos(imuPos) {}
45
48 [[nodiscard]] static std::string type()
49 {
50 return "VectorNavBinaryOutput";
51 }
52
55 [[nodiscard]] std::string getType() const override { return type(); }
56
59 [[nodiscard]] static std::vector<std::string> parentTypes()
60 {
61 return { NodeData::type() };
62 }
63
65 [[nodiscard]] static std::vector<std::string> GetStaticDataDescriptors()
66 {
67 return {};
68 }
69
71 [[nodiscard]] static constexpr size_t GetStaticDescriptorCount() { return 0; }
72
74 [[nodiscard]] std::vector<std::string> staticDataDescriptors() const override { return GetStaticDataDescriptors(); }
75
77 [[nodiscard]] size_t staticDescriptorCount() const override { return GetStaticDescriptorCount(); }
78
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
718 {
720 switch (sys)
721 {
723 satSys = GPS;
724 break;
726 satSys = SBAS;
727 break;
729 satSys = GAL;
730 break;
732 satSys = BDS;
733 break;
735 LOG_TRACE("VectorNav SatInfoElement satellite system '{}' is not supported yet. Skipping measurement.", sys);
736 break;
738 satSys = QZSS;
739 break;
741 satSys = GLO;
742 break;
743 default: // IRNSS not in vectorNav
744 LOG_TRACE("VectorNav SatInfoElement satellite system '{}' is not supported yet. Skipping measurement.", sys);
745 break;
746 }
747 return satSys;
748 }
749
751 [[nodiscard]] std::vector<std::string> dynamicDataDescriptors() const override
752 {
753 std::vector<std::string> descriptors;
754
755 // Group 2 (Time)
756 if (timeOutputs)
757 {
758 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTARTUP)
759 {
760 descriptors.emplace_back("Time::TimeStartup [ns]");
761 }
762 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPS)
763 {
764 descriptors.emplace_back("Time::TimeGps [ns]");
765 }
766 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
767 {
768 descriptors.emplace_back("Time::GpsTow [ns]");
769 }
770 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK)
771 {
772 descriptors.emplace_back("Time::GpsWeek");
773 }
774 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESYNCIN)
775 {
776 descriptors.emplace_back("Time::TimeSyncIn [ns]");
777 }
778 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPSPPS)
779 {
780 descriptors.emplace_back("Time::TimeGpsPps [ns]");
781 }
782 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)
783 {
784 descriptors.emplace_back("Time::TimeUTC::year");
785 descriptors.emplace_back("Time::TimeUTC::month");
786 descriptors.emplace_back("Time::TimeUTC::day");
787 descriptors.emplace_back("Time::TimeUTC::hour");
788 descriptors.emplace_back("Time::TimeUTC::min");
789 descriptors.emplace_back("Time::TimeUTC::sec");
790 descriptors.emplace_back("Time::TimeUTC::ms");
791 }
792 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCINCNT)
793 {
794 descriptors.emplace_back("Time::SyncInCnt");
795 }
796 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCOUTCNT)
797 {
798 descriptors.emplace_back("Time::SyncOutCnt");
799 }
800 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
801 {
802 descriptors.emplace_back("Time::TimeStatus::timeOk");
803 descriptors.emplace_back("Time::TimeStatus::dateOk");
804 descriptors.emplace_back("Time::TimeStatus::utcTimeValid");
805 }
806 }
807 // Group 3 (IMU)
808 if (imuOutputs)
809 {
810 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_IMUSTATUS)
811 {
812 descriptors.emplace_back("IMU::ImuStatus");
813 }
814 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
815 {
816 descriptors.emplace_back("IMU::UncompMag::X [Gauss]");
817 descriptors.emplace_back("IMU::UncompMag::Y [Gauss]");
818 descriptors.emplace_back("IMU::UncompMag::Z [Gauss]");
819 }
820 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
821 {
822 descriptors.emplace_back("IMU::UncompAccel::X [m/s^2]");
823 descriptors.emplace_back("IMU::UncompAccel::Y [m/s^2]");
824 descriptors.emplace_back("IMU::UncompAccel::Z [m/s^2]");
825 }
826 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
827 {
828 descriptors.emplace_back("IMU::UncompGyro::X [rad/s]");
829 descriptors.emplace_back("IMU::UncompGyro::Y [rad/s]");
830 descriptors.emplace_back("IMU::UncompGyro::Z [rad/s]");
831 }
832 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
833 {
834 descriptors.emplace_back("IMU::Temp [Celsius]");
835 }
836 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)
837 {
838 descriptors.emplace_back("IMU::Pres [kPa]");
839 }
840 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)
841 {
842 descriptors.emplace_back("IMU::DeltaTime [s]");
843 descriptors.emplace_back("IMU::DeltaTheta::X [deg]");
844 descriptors.emplace_back("IMU::DeltaTheta::Y [deg]");
845 descriptors.emplace_back("IMU::DeltaTheta::Z [deg]");
846 }
847 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)
848 {
849 descriptors.emplace_back("IMU::DeltaVel::X [m/s]");
850 descriptors.emplace_back("IMU::DeltaVel::Y [m/s]");
851 descriptors.emplace_back("IMU::DeltaVel::Z [m/s]");
852 }
853 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
854 {
855 descriptors.emplace_back("IMU::Mag::X [Gauss]");
856 descriptors.emplace_back("IMU::Mag::Y [Gauss]");
857 descriptors.emplace_back("IMU::Mag::Z [Gauss]");
858 }
859 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
860 {
861 descriptors.emplace_back("IMU::Accel::X [m/s^2]");
862 descriptors.emplace_back("IMU::Accel::Y [m/s^2]");
863 descriptors.emplace_back("IMU::Accel::Z [m/s^2]");
864 }
865 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
866 {
867 descriptors.emplace_back("IMU::AngularRate::X [rad/s]");
868 descriptors.emplace_back("IMU::AngularRate::Y [rad/s]");
869 descriptors.emplace_back("IMU::AngularRate::Z [rad/s]");
870 }
871 }
872 // Group 4 (GNSS1)
873 if (gnss1Outputs)
874 {
875 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
876 {
877 descriptors.emplace_back("GNSS1::UTC::year");
878 descriptors.emplace_back("GNSS1::UTC::month");
879 descriptors.emplace_back("GNSS1::UTC::day");
880 descriptors.emplace_back("GNSS1::UTC::hour");
881 descriptors.emplace_back("GNSS1::UTC::min");
882 descriptors.emplace_back("GNSS1::UTC::sec");
883 descriptors.emplace_back("GNSS1::UTC::ms");
884 }
885 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
886 {
887 descriptors.emplace_back("GNSS1::Tow [ns]");
888 }
889 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
890 {
891 descriptors.emplace_back("GNSS1::Week");
892 }
893 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
894 {
895 descriptors.emplace_back("GNSS1::NumSats");
896 }
897 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
898 {
899 descriptors.emplace_back("GNSS1::Fix");
900 }
901 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
902 {
903 descriptors.emplace_back("GNSS1::PosLla::latitude [deg]");
904 descriptors.emplace_back("GNSS1::PosLla::longitude [deg]");
905 descriptors.emplace_back("GNSS1::PosLla::altitude [m]");
906 }
907 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
908 {
909 descriptors.emplace_back("GNSS1::PosEcef::X [m]");
910 descriptors.emplace_back("GNSS1::PosEcef::Y [m]");
911 descriptors.emplace_back("GNSS1::PosEcef::Z [m]");
912 }
913 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
914 {
915 descriptors.emplace_back("GNSS1::VelNed::N [m/s]");
916 descriptors.emplace_back("GNSS1::VelNed::E [m/s]");
917 descriptors.emplace_back("GNSS1::VelNed::D [m/s]");
918 }
919 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
920 {
921 descriptors.emplace_back("GNSS1::VelEcef::X [m/s]");
922 descriptors.emplace_back("GNSS1::VelEcef::Y [m/s]");
923 descriptors.emplace_back("GNSS1::VelEcef::Z [m/s]");
924 }
925 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
926 {
927 descriptors.emplace_back("GNSS1::PosU::N [m]");
928 descriptors.emplace_back("GNSS1::PosU::E [m]");
929 descriptors.emplace_back("GNSS1::PosU::D [m]");
930 }
931 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
932 {
933 descriptors.emplace_back("GNSS1::VelU [m/s]");
934 }
935 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
936 {
937 descriptors.emplace_back("GNSS1::TimeU [s]");
938 }
939 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
940 {
941 descriptors.emplace_back("GNSS1::TimeInfo::Status::timeOk");
942 descriptors.emplace_back("GNSS1::TimeInfo::Status::dateOk");
943 descriptors.emplace_back("GNSS1::TimeInfo::Status::utcTimeValid");
944 descriptors.emplace_back("GNSS1::TimeInfo::LeapSeconds");
945 }
946 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
947 {
948 descriptors.emplace_back("GNSS1::DOP::g");
949 descriptors.emplace_back("GNSS1::DOP::p");
950 descriptors.emplace_back("GNSS1::DOP::t");
951 descriptors.emplace_back("GNSS1::DOP::v");
952 descriptors.emplace_back("GNSS1::DOP::h");
953 descriptors.emplace_back("GNSS1::DOP::n");
954 descriptors.emplace_back("GNSS1::DOP::e");
955 }
956 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
957 {
958 descriptors.emplace_back("GNSS1::SatInfo::NumSats");
959 for (auto& satellite : gnss1Outputs->satInfo.satellites)
960 {
961 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
962 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Healthy", satId));
963 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Almanac", satId));
964 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag Ephemeris", satId));
965 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag DifferentialCorrection", satId));
966 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForNavigation", satId));
967 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag AzimuthElevationValid", satId));
968 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - flag UsedForRTK", satId));
969 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - cno", satId));
970 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - qi", satId));
971 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - el", satId));
972 descriptors.push_back(fmt::format("GNSS1::SatInfo::{} - az", satId));
973 }
974 }
975 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
976 {
977 descriptors.emplace_back("GNSS1::RawMeas::Tow [s]");
978 descriptors.emplace_back("GNSS1::RawMeas::Week");
979 descriptors.emplace_back("GNSS1::RawMeas::NumSats");
980 for (auto& satellite : gnss1Outputs->raw.satellites)
981 {
982 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
983 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - sys", satId));
984 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - svId", satId));
985 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - freq", satId));
986 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - chan", satId));
987 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - slot", satId));
988 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - cno", satId));
989 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag Searching", satId));
990 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag Tracking", satId));
991 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag TimeValid", satId));
992 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag CodeLock", satId));
993 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseLock", satId));
994 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfAmbiguity", satId));
995 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseHalfSub", satId));
996 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PhaseSlip", satId));
997 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - flag PseudorangeSmoothed", satId));
998 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - pr", satId));
999 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - cp", satId));
1000 descriptors.push_back(fmt::format("GNSS1::RawMeas::{} - dp", satId));
1001 }
1002 }
1003 }
1004 // Group 5 (Attitude)
1005 if (attitudeOutputs)
1006 {
1007 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)
1008 {
1009 descriptors.emplace_back("Att::VpeStatus::AttitudeQuality");
1010 descriptors.emplace_back("Att::VpeStatus::GyroSaturation");
1011 descriptors.emplace_back("Att::VpeStatus::GyroSaturationRecovery");
1012 descriptors.emplace_back("Att::VpeStatus::MagDisturbance");
1013 descriptors.emplace_back("Att::VpeStatus::MagSaturation");
1014 descriptors.emplace_back("Att::VpeStatus::AccDisturbance");
1015 descriptors.emplace_back("Att::VpeStatus::AccSaturation");
1016 descriptors.emplace_back("Att::VpeStatus::KnownMagDisturbance");
1017 descriptors.emplace_back("Att::VpeStatus::KnownAccelDisturbance");
1018 }
1019 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)
1020 {
1021 descriptors.emplace_back("Att::YawPitchRoll::Y [deg]");
1022 descriptors.emplace_back("Att::YawPitchRoll::P [deg]");
1023 descriptors.emplace_back("Att::YawPitchRoll::R [deg]");
1024 }
1025 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)
1026 {
1027 descriptors.emplace_back("Att::Quaternion::w");
1028 descriptors.emplace_back("Att::Quaternion::x");
1029 descriptors.emplace_back("Att::Quaternion::y");
1030 descriptors.emplace_back("Att::Quaternion::z");
1031 }
1032 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)
1033 {
1034 descriptors.emplace_back("Att::DCM::0-0,Att::DCM::0-1,Att::DCM::0-2");
1035 descriptors.emplace_back("Att::DCM::1-0,Att::DCM::1-1,Att::DCM::1-2");
1036 descriptors.emplace_back("Att::DCM::2-0,Att::DCM::2-1,Att::DCM::2-2");
1037 }
1038 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)
1039 {
1040 descriptors.emplace_back("Att::MagNed::N [Gauss]");
1041 descriptors.emplace_back("Att::MagNed::E [Gauss]");
1042 descriptors.emplace_back("Att::MagNed::D [Gauss]");
1043 }
1044 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)
1045 {
1046 descriptors.emplace_back("Att::AccelNed::N [m/s^2]");
1047 descriptors.emplace_back("Att::AccelNed::E [m/s^2]");
1048 descriptors.emplace_back("Att::AccelNed::D [m/s^2]");
1049 }
1050 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)
1051 {
1052 descriptors.emplace_back("Att::LinearAccelBody::X [m/s^2]");
1053 descriptors.emplace_back("Att::LinearAccelBody::Y [m/s^2]");
1054 descriptors.emplace_back("Att::LinearAccelBody::Z [m/s^2]");
1055 }
1056 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)
1057 {
1058 descriptors.emplace_back("Att::LinearAccelNed::N [m/s^2]");
1059 descriptors.emplace_back("Att::LinearAccelNed::E [m/s^2]");
1060 descriptors.emplace_back("Att::LinearAccelNed::D [m/s^2]");
1061 }
1062 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)
1063 {
1064 descriptors.emplace_back("Att::YprU::Y [deg]");
1065 descriptors.emplace_back("Att::YprU::P [deg]");
1066 descriptors.emplace_back("Att::YprU::R [deg]");
1067 }
1068 }
1069 // Group 6 (INS)
1070 if (insOutputs)
1071 {
1072 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)
1073 {
1074 descriptors.emplace_back("INS::InsStatus::Mode");
1075 descriptors.emplace_back("INS::InsStatus::GpsFix");
1076 descriptors.emplace_back("INS::InsStatus::Error::IMU");
1077 descriptors.emplace_back("INS::InsStatus::Error::MagPres");
1078 descriptors.emplace_back("INS::InsStatus::Error::GNSS");
1079 descriptors.emplace_back("INS::InsStatus::GpsHeadingIns");
1080 descriptors.emplace_back("INS::InsStatus::GpsCompass");
1081 }
1082 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)
1083 {
1084 descriptors.emplace_back("INS::PosLla::latitude [deg]");
1085 descriptors.emplace_back("INS::PosLla::longitude [deg]");
1086 descriptors.emplace_back("INS::PosLla::altitude [m]");
1087 }
1088 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)
1089 {
1090 descriptors.emplace_back("INS::PosEcef::X [m]");
1091 descriptors.emplace_back("INS::PosEcef::Y [m]");
1092 descriptors.emplace_back("INS::PosEcef::Z [m]");
1093 }
1094 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)
1095 {
1096 descriptors.emplace_back("INS::VelBody::X [m/s]");
1097 descriptors.emplace_back("INS::VelBody::Y [m/s]");
1098 descriptors.emplace_back("INS::VelBody::Z [m/s]");
1099 }
1100 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)
1101 {
1102 descriptors.emplace_back("INS::VelNed::N [m/s]");
1103 descriptors.emplace_back("INS::VelNed::E [m/s]");
1104 descriptors.emplace_back("INS::VelNed::D [m/s]");
1105 }
1106 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)
1107 {
1108 descriptors.emplace_back("INS::VelEcef::X [m/s]");
1109 descriptors.emplace_back("INS::VelEcef::Y [m/s]");
1110 descriptors.emplace_back("INS::VelEcef::Z [m/s]");
1111 }
1112 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)
1113 {
1114 descriptors.emplace_back("INS::MagEcef::X [Gauss]");
1115 descriptors.emplace_back("INS::MagEcef::Y [Gauss]");
1116 descriptors.emplace_back("INS::MagEcef::Z [Gauss]");
1117 }
1118 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)
1119 {
1120 descriptors.emplace_back("INS::AccelEcef::X [m/s^2]");
1121 descriptors.emplace_back("INS::AccelEcef::Y [m/s^2]");
1122 descriptors.emplace_back("INS::AccelEcef::Z [m/s^2]");
1123 }
1124 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)
1125 {
1126 descriptors.emplace_back("INS::LinearAccelEcef::X [m/s^2]");
1127 descriptors.emplace_back("INS::LinearAccelEcef::Y [m/s^2]");
1128 descriptors.emplace_back("INS::LinearAccelEcef::Z [m/s^2]");
1129 }
1130 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSU)
1131 {
1132 descriptors.emplace_back("INS::PosU [m]");
1133 }
1134 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELU)
1135 {
1136 descriptors.emplace_back("INS::VelU [m/s]");
1137 }
1138 }
1139 // Group 7 (GNSS2)
1140 if (gnss2Outputs)
1141 {
1142 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1143 {
1144 descriptors.emplace_back("GNSS2::UTC::year");
1145 descriptors.emplace_back("GNSS2::UTC::month");
1146 descriptors.emplace_back("GNSS2::UTC::day");
1147 descriptors.emplace_back("GNSS2::UTC::hour");
1148 descriptors.emplace_back("GNSS2::UTC::min");
1149 descriptors.emplace_back("GNSS2::UTC::sec");
1150 descriptors.emplace_back("GNSS2::UTC::ms");
1151 }
1152 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1153 {
1154 descriptors.emplace_back("GNSS2::Tow [ns]");
1155 }
1156 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1157 {
1158 descriptors.emplace_back("GNSS2::Week");
1159 }
1160 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1161 {
1162 descriptors.emplace_back("GNSS2::NumSats");
1163 }
1164 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1165 {
1166 descriptors.emplace_back("GNSS2::Fix");
1167 }
1168 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1169 {
1170 descriptors.emplace_back("GNSS2::PosLla::latitude [deg]");
1171 descriptors.emplace_back("GNSS2::PosLla::longitude [deg]");
1172 descriptors.emplace_back("GNSS2::PosLla::altitude [m]");
1173 }
1174 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1175 {
1176 descriptors.emplace_back("GNSS2::PosEcef::X [m]");
1177 descriptors.emplace_back("GNSS2::PosEcef::Y [m]");
1178 descriptors.emplace_back("GNSS2::PosEcef::Z [m]");
1179 }
1180 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
1181 {
1182 descriptors.emplace_back("GNSS2::VelNed::N [m/s]");
1183 descriptors.emplace_back("GNSS2::VelNed::E [m/s]");
1184 descriptors.emplace_back("GNSS2::VelNed::D [m/s]");
1185 }
1186 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
1187 {
1188 descriptors.emplace_back("GNSS2::VelEcef::X [m/s]");
1189 descriptors.emplace_back("GNSS2::VelEcef::Y [m/s]");
1190 descriptors.emplace_back("GNSS2::VelEcef::Z [m/s]");
1191 }
1192 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
1193 {
1194 descriptors.emplace_back("GNSS2::PosU::N [m]");
1195 descriptors.emplace_back("GNSS2::PosU::E [m]");
1196 descriptors.emplace_back("GNSS2::PosU::D [m]");
1197 }
1198 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
1199 {
1200 descriptors.emplace_back("GNSS2::VelU [m/s]");
1201 }
1202 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
1203 {
1204 descriptors.emplace_back("GNSS2::TimeU [s]");
1205 }
1206 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
1207 {
1208 descriptors.emplace_back("GNSS2::TimeInfo::Status::timeOk");
1209 descriptors.emplace_back("GNSS2::TimeInfo::Status::dateOk");
1210 descriptors.emplace_back("GNSS2::TimeInfo::Status::utcTimeValid");
1211 descriptors.emplace_back("GNSS2::TimeInfo::LeapSeconds");
1212 }
1213 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
1214 {
1215 descriptors.emplace_back("GNSS2::DOP::g");
1216 descriptors.emplace_back("GNSS2::DOP::p");
1217 descriptors.emplace_back("GNSS2::DOP::t");
1218 descriptors.emplace_back("GNSS2::DOP::v");
1219 descriptors.emplace_back("GNSS2::DOP::h");
1220 descriptors.emplace_back("GNSS2::DOP::n");
1221 descriptors.emplace_back("GNSS2::DOP::e");
1222 }
1223 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
1224 {
1225 descriptors.emplace_back("GNSS2::SatInfo::NumSats");
1226 for (auto& satellite : gnss2Outputs->satInfo.satellites)
1227 {
1228 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1229 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Healthy", satId));
1230 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Almanac", satId));
1231 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag Ephemeris", satId));
1232 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag DifferentialCorrection", satId));
1233 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForNavigation", satId));
1234 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag AzimuthElevationValid", satId));
1235 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - flag UsedForRTK", satId));
1236 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - cno", satId));
1237 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - qi", satId));
1238 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - el", satId));
1239 descriptors.push_back(fmt::format("GNSS2::SatInfo::{} - az", satId));
1240 }
1241 }
1242 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
1243 {
1244 descriptors.emplace_back("GNSS2::RawMeas::Tow [s]");
1245 descriptors.emplace_back("GNSS2::RawMeas::Week");
1246 descriptors.emplace_back("GNSS2::RawMeas::NumSats");
1247 for (auto& satellite : gnss2Outputs->raw.satellites)
1248 {
1249 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1250 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - sys", satId));
1251 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - svId", satId));
1252 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - freq", satId));
1253 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - chan", satId));
1254 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - slot", satId));
1255 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - cno", satId));
1256 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag Searching", satId));
1257 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag Tracking", satId));
1258 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag TimeValid", satId));
1259 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag CodeLock", satId));
1260 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseLock", satId));
1261 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfAmbiguity", satId));
1262 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseHalfSub", satId));
1263 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PhaseSlip", satId));
1264 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - flag PseudorangeSmoothed", satId));
1265 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - pr", satId));
1266 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - cp", satId));
1267 descriptors.push_back(fmt::format("GNSS2::RawMeas::{} - dp", satId));
1268 }
1269 }
1270 }
1271
1272 return descriptors;
1273 }
1274
1277 [[nodiscard]] std::optional<double> getDynamicDataAt(const std::string& descriptor) const override
1278 {
1279 // Group 2 (Time)
1280 if (descriptor == "Time::TimeStartup [ns]") { return static_cast<double>(timeOutputs->timeStartup); }
1281 if (descriptor == "Time::TimeGps [ns]") { return static_cast<double>(timeOutputs->timeGps); }
1282 if (descriptor == "Time::GpsTow [ns]") { return static_cast<double>(timeOutputs->gpsTow); }
1283 if (descriptor == "Time::GpsWeek") { return static_cast<double>(timeOutputs->gpsWeek); }
1284 if (descriptor == "Time::TimeSyncIn [ns]") { return static_cast<double>(timeOutputs->timeSyncIn); }
1285 if (descriptor == "Time::TimeGpsPps [ns]") { return static_cast<double>(timeOutputs->timePPS); }
1286 if (descriptor == "Time::TimeUTC::year") { return static_cast<double>(timeOutputs->timeUtc.year); }
1287 if (descriptor == "Time::TimeUTC::month") { return static_cast<double>(timeOutputs->timeUtc.month); }
1288 if (descriptor == "Time::TimeUTC::day") { return static_cast<double>(timeOutputs->timeUtc.day); }
1289 if (descriptor == "Time::TimeUTC::hour") { return static_cast<double>(timeOutputs->timeUtc.hour); }
1290 if (descriptor == "Time::TimeUTC::min") { return static_cast<double>(timeOutputs->timeUtc.min); }
1291 if (descriptor == "Time::TimeUTC::sec") { return static_cast<double>(timeOutputs->timeUtc.sec); }
1292 if (descriptor == "Time::TimeUTC::ms") { return static_cast<double>(timeOutputs->timeUtc.ms); }
1293 if (descriptor == "Time::SyncInCnt") { return static_cast<double>(timeOutputs->syncInCnt); }
1294 if (descriptor == "Time::SyncOutCnt") { return static_cast<double>(timeOutputs->syncOutCnt); }
1295 if (descriptor == "Time::TimeStatus::timeOk") { return static_cast<double>(timeOutputs->timeStatus.timeOk()); }
1296 if (descriptor == "Time::TimeStatus::dateOk") { return static_cast<double>(timeOutputs->timeStatus.dateOk()); }
1297 if (descriptor == "Time::TimeStatus::utcTimeValid") { return static_cast<double>(timeOutputs->timeStatus.utcTimeValid()); }
1298 // Group 3 (IMU)
1299 if (descriptor == "IMU::ImuStatus") { return static_cast<double>(imuOutputs->imuStatus); }
1300 if (descriptor == "IMU::UncompMag::X [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(0)); }
1301 if (descriptor == "IMU::UncompMag::Y [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(1)); }
1302 if (descriptor == "IMU::UncompMag::Z [Gauss]") { return static_cast<double>(imuOutputs->uncompMag(2)); }
1303 if (descriptor == "IMU::UncompAccel::X [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(0)); }
1304 if (descriptor == "IMU::UncompAccel::Y [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(1)); }
1305 if (descriptor == "IMU::UncompAccel::Z [m/s^2]") { return static_cast<double>(imuOutputs->uncompAccel(2)); }
1306 if (descriptor == "IMU::UncompGyro::X [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(0)); }
1307 if (descriptor == "IMU::UncompGyro::Y [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(1)); }
1308 if (descriptor == "IMU::UncompGyro::Z [rad/s]") { return static_cast<double>(imuOutputs->uncompGyro(2)); }
1309 if (descriptor == "IMU::Temp [Celsius]") { return static_cast<double>(imuOutputs->temp); }
1310 if (descriptor == "IMU::Pres [kPa]") { return static_cast<double>(imuOutputs->pres); }
1311 if (descriptor == "IMU::DeltaTime [s]") { return static_cast<double>(imuOutputs->deltaTime); }
1312 if (descriptor == "IMU::DeltaTheta::X [deg]") { return static_cast<double>(imuOutputs->deltaTheta(0)); }
1313 if (descriptor == "IMU::DeltaTheta::Y [deg]") { return static_cast<double>(imuOutputs->deltaTheta(1)); }
1314 if (descriptor == "IMU::DeltaTheta::Z [deg]") { return static_cast<double>(imuOutputs->deltaTheta(2)); }
1315 if (descriptor == "IMU::DeltaVel::X [m/s]") { return static_cast<double>(imuOutputs->deltaV(0)); }
1316 if (descriptor == "IMU::DeltaVel::Y [m/s]") { return static_cast<double>(imuOutputs->deltaV(1)); }
1317 if (descriptor == "IMU::DeltaVel::Z [m/s]") { return static_cast<double>(imuOutputs->deltaV(2)); }
1318 if (descriptor == "IMU::Mag::X [Gauss]") { return static_cast<double>(imuOutputs->mag(0)); }
1319 if (descriptor == "IMU::Mag::Y [Gauss]") { return static_cast<double>(imuOutputs->mag(1)); }
1320 if (descriptor == "IMU::Mag::Z [Gauss]") { return static_cast<double>(imuOutputs->mag(2)); }
1321 if (descriptor == "IMU::Accel::X [m/s^2]") { return static_cast<double>(imuOutputs->accel(0)); }
1322 if (descriptor == "IMU::Accel::Y [m/s^2]") { return static_cast<double>(imuOutputs->accel(1)); }
1323 if (descriptor == "IMU::Accel::Z [m/s^2]") { return static_cast<double>(imuOutputs->accel(2)); }
1324 if (descriptor == "IMU::AngularRate::X [rad/s]") { return static_cast<double>(imuOutputs->angularRate(0)); }
1325 if (descriptor == "IMU::AngularRate::Y [rad/s]") { return static_cast<double>(imuOutputs->angularRate(1)); }
1326 if (descriptor == "IMU::AngularRate::Z [rad/s]") { return static_cast<double>(imuOutputs->angularRate(2)); }
1327 // Group 4 (GNSS1)
1328 if (descriptor == "GNSS1::UTC::year") { return static_cast<double>(gnss1Outputs->timeUtc.year); }
1329 if (descriptor == "GNSS1::UTC::month") { return static_cast<double>(gnss1Outputs->timeUtc.month); }
1330 if (descriptor == "GNSS1::UTC::day") { return static_cast<double>(gnss1Outputs->timeUtc.day); }
1331 if (descriptor == "GNSS1::UTC::hour") { return static_cast<double>(gnss1Outputs->timeUtc.hour); }
1332 if (descriptor == "GNSS1::UTC::min") { return static_cast<double>(gnss1Outputs->timeUtc.min); }
1333 if (descriptor == "GNSS1::UTC::sec") { return static_cast<double>(gnss1Outputs->timeUtc.sec); }
1334 if (descriptor == "GNSS1::UTC::ms") { return static_cast<double>(gnss1Outputs->timeUtc.ms); }
1335 if (descriptor == "GNSS1::Tow [ns]") { return static_cast<double>(gnss1Outputs->tow); }
1336 if (descriptor == "GNSS1::Week") { return static_cast<double>(gnss1Outputs->week); }
1337 if (descriptor == "GNSS1::NumSats") { return static_cast<double>(gnss1Outputs->numSats); }
1338 if (descriptor == "GNSS1::Fix") { return static_cast<double>(gnss1Outputs->fix); }
1339 if (descriptor == "GNSS1::PosLla::latitude [deg]") { return static_cast<double>(gnss1Outputs->posLla(0)); }
1340 if (descriptor == "GNSS1::PosLla::longitude [deg]") { return static_cast<double>(gnss1Outputs->posLla(1)); }
1341 if (descriptor == "GNSS1::PosLla::altitude [m]") { return static_cast<double>(gnss1Outputs->posLla(2)); }
1342 if (descriptor == "GNSS1::PosEcef::X [m]") { return static_cast<double>(gnss1Outputs->posEcef(0)); }
1343 if (descriptor == "GNSS1::PosEcef::Y [m]") { return static_cast<double>(gnss1Outputs->posEcef(1)); }
1344 if (descriptor == "GNSS1::PosEcef::Z [m]") { return static_cast<double>(gnss1Outputs->posEcef(2)); }
1345 if (descriptor == "GNSS1::VelNed::N [m/s]") { return static_cast<double>(gnss1Outputs->velNed(0)); }
1346 if (descriptor == "GNSS1::VelNed::E [m/s]") { return static_cast<double>(gnss1Outputs->velNed(1)); }
1347 if (descriptor == "GNSS1::VelNed::D [m/s]") { return static_cast<double>(gnss1Outputs->velNed(2)); }
1348 if (descriptor == "GNSS1::VelEcef::X [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(0)); }
1349 if (descriptor == "GNSS1::VelEcef::Y [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(1)); }
1350 if (descriptor == "GNSS1::VelEcef::Z [m/s]") { return static_cast<double>(gnss1Outputs->velEcef(2)); }
1351 if (descriptor == "GNSS1::PosU::N [m]") { return static_cast<double>(gnss1Outputs->posU(0)); }
1352 if (descriptor == "GNSS1::PosU::E [m]") { return static_cast<double>(gnss1Outputs->posU(1)); }
1353 if (descriptor == "GNSS1::PosU::D [m]") { return static_cast<double>(gnss1Outputs->posU(2)); }
1354 if (descriptor == "GNSS1::VelU [m/s]") { return static_cast<double>(gnss1Outputs->velU); }
1355 if (descriptor == "GNSS1::TimeU [s]") { return static_cast<double>(gnss1Outputs->timeU); }
1356 if (descriptor == "GNSS1::TimeInfo::Status::timeOk") { return static_cast<double>(gnss1Outputs->timeInfo.status.timeOk()); }
1357 if (descriptor == "GNSS1::TimeInfo::Status::dateOk") { return static_cast<double>(gnss1Outputs->timeInfo.status.dateOk()); }
1358 if (descriptor == "GNSS1::TimeInfo::Status::utcTimeValid") { return static_cast<double>(gnss1Outputs->timeInfo.status.utcTimeValid()); }
1359 if (descriptor == "GNSS1::TimeInfo::LeapSeconds") { return static_cast<double>(gnss1Outputs->timeInfo.leapSeconds); }
1360 if (descriptor == "GNSS1::DOP::g") { return static_cast<double>(gnss1Outputs->dop.gDop); }
1361 if (descriptor == "GNSS1::DOP::p") { return static_cast<double>(gnss1Outputs->dop.pDop); }
1362 if (descriptor == "GNSS1::DOP::t") { return static_cast<double>(gnss1Outputs->dop.tDop); }
1363 if (descriptor == "GNSS1::DOP::v") { return static_cast<double>(gnss1Outputs->dop.vDop); }
1364 if (descriptor == "GNSS1::DOP::h") { return static_cast<double>(gnss1Outputs->dop.hDop); }
1365 if (descriptor == "GNSS1::DOP::n") { return static_cast<double>(gnss1Outputs->dop.nDop); }
1366 if (descriptor == "GNSS1::DOP::e") { return static_cast<double>(gnss1Outputs->dop.eDop); }
1367 if (descriptor == "GNSS1::SatInfo::NumSats") { return static_cast<double>(gnss1Outputs->satInfo.numSats); }
1368 for (auto& satellite : gnss1Outputs->satInfo.satellites)
1369 {
1370 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1371 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); }
1372 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); }
1373 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); }
1374 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); }
1375 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); }
1376 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); }
1377 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); }
1378 if (descriptor == fmt::format("GNSS1::SatInfo::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1379 if (descriptor == fmt::format("GNSS1::SatInfo::{} - qi", satId)) { return static_cast<double>(satellite.qi); }
1380 if (descriptor == fmt::format("GNSS1::SatInfo::{} - el", satId)) { return static_cast<double>(satellite.el); }
1381 if (descriptor == fmt::format("GNSS1::SatInfo::{} - az", satId)) { return static_cast<double>(satellite.az); }
1382 }
1383 if (descriptor == "GNSS1::RawMeas::Tow [s]") { return gnss1Outputs->raw.tow; }
1384 if (descriptor == "GNSS1::RawMeas::Week") { return static_cast<double>(gnss1Outputs->raw.week); }
1385 if (descriptor == "GNSS1::RawMeas::NumSats") { return static_cast<double>(gnss1Outputs->raw.numSats); }
1386 for (auto& satellite : gnss1Outputs->raw.satellites)
1387 {
1388 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1389 if (descriptor == fmt::format("GNSS1::RawMeas::{} - freq", satId)) { return static_cast<double>(satellite.freq); }
1390 if (descriptor == fmt::format("GNSS1::RawMeas::{} - chan", satId)) { return static_cast<double>(satellite.chan); }
1391 if (descriptor == fmt::format("GNSS1::RawMeas::{} - slot", satId)) { return static_cast<double>(satellite.slot); }
1392 if (descriptor == fmt::format("GNSS1::RawMeas::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1393 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); }
1394 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); }
1395 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); }
1396 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); }
1397 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); }
1398 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); }
1399 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); }
1400 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); }
1401 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); }
1402 if (descriptor == fmt::format("GNSS1::RawMeas::{} - pr", satId)) { return satellite.pr; }
1403 if (descriptor == fmt::format("GNSS1::RawMeas::{} - cp", satId)) { return satellite.cp; }
1404 if (descriptor == fmt::format("GNSS1::RawMeas::{} - dp", satId)) { return static_cast<double>(satellite.dp); }
1405 }
1406 // Group 5 (Attitude)
1407 if (descriptor == "Att::VpeStatus::AttitudeQuality") { return static_cast<double>(attitudeOutputs->vpeStatus.attitudeQuality()); }
1408 if (descriptor == "Att::VpeStatus::GyroSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturation()); }
1409 if (descriptor == "Att::VpeStatus::GyroSaturationRecovery") { return static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturationRecovery()); }
1410 if (descriptor == "Att::VpeStatus::MagDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.magDisturbance()); }
1411 if (descriptor == "Att::VpeStatus::MagSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.magSaturation()); }
1412 if (descriptor == "Att::VpeStatus::AccDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.accDisturbance()); }
1413 if (descriptor == "Att::VpeStatus::AccSaturation") { return static_cast<double>(attitudeOutputs->vpeStatus.accSaturation()); }
1414 if (descriptor == "Att::VpeStatus::KnownMagDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.knownMagDisturbance()); }
1415 if (descriptor == "Att::VpeStatus::KnownAccelDisturbance") { return static_cast<double>(attitudeOutputs->vpeStatus.knownAccelDisturbance()); }
1416 if (descriptor == "Att::YawPitchRoll::Y [deg]") { return static_cast<double>(attitudeOutputs->ypr(0)); }
1417 if (descriptor == "Att::YawPitchRoll::P [deg]") { return static_cast<double>(attitudeOutputs->ypr(1)); }
1418 if (descriptor == "Att::YawPitchRoll::R [deg]") { return static_cast<double>(attitudeOutputs->ypr(2)); }
1419 if (descriptor == "Att::Quaternion::w") { return static_cast<double>(attitudeOutputs->qtn.w()); }
1420 if (descriptor == "Att::Quaternion::x") { return static_cast<double>(attitudeOutputs->qtn.x()); }
1421 if (descriptor == "Att::Quaternion::y") { return static_cast<double>(attitudeOutputs->qtn.y()); }
1422 if (descriptor == "Att::Quaternion::z") { return static_cast<double>(attitudeOutputs->qtn.z()); }
1423 if (descriptor == "Att::DCM::0-0") { return static_cast<double>(attitudeOutputs->dcm(0, 0)); }
1424 if (descriptor == "Att::DCM::0-1") { return static_cast<double>(attitudeOutputs->dcm(0, 1)); }
1425 if (descriptor == "Att::DCM::0-2") { return static_cast<double>(attitudeOutputs->dcm(0, 2)); }
1426 if (descriptor == "Att::DCM::1-0") { return static_cast<double>(attitudeOutputs->dcm(1, 0)); }
1427 if (descriptor == "Att::DCM::1-1") { return static_cast<double>(attitudeOutputs->dcm(1, 1)); }
1428 if (descriptor == "Att::DCM::1-2") { return static_cast<double>(attitudeOutputs->dcm(1, 2)); }
1429 if (descriptor == "Att::DCM::2-0") { return static_cast<double>(attitudeOutputs->dcm(2, 0)); }
1430 if (descriptor == "Att::DCM::2-1") { return static_cast<double>(attitudeOutputs->dcm(2, 1)); }
1431 if (descriptor == "Att::DCM::2-2") { return static_cast<double>(attitudeOutputs->dcm(2, 2)); }
1432 if (descriptor == "Att::MagNed::N [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(0)); }
1433 if (descriptor == "Att::MagNed::E [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(1)); }
1434 if (descriptor == "Att::MagNed::D [Gauss]") { return static_cast<double>(attitudeOutputs->magNed(2)); }
1435 if (descriptor == "Att::AccelNed::N [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(0)); }
1436 if (descriptor == "Att::AccelNed::E [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(1)); }
1437 if (descriptor == "Att::AccelNed::D [m/s^2]") { return static_cast<double>(attitudeOutputs->accelNed(2)); }
1438 if (descriptor == "Att::LinearAccelBody::X [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(0)); }
1439 if (descriptor == "Att::LinearAccelBody::Y [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(1)); }
1440 if (descriptor == "Att::LinearAccelBody::Z [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelBody(2)); }
1441 if (descriptor == "Att::LinearAccelNed::N [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(0)); }
1442 if (descriptor == "Att::LinearAccelNed::E [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(1)); }
1443 if (descriptor == "Att::LinearAccelNed::D [m/s^2]") { return static_cast<double>(attitudeOutputs->linearAccelNed(2)); }
1444 if (descriptor == "Att::YprU::Y [deg]") { return static_cast<double>(attitudeOutputs->yprU(0)); }
1445 if (descriptor == "Att::YprU::P [deg]") { return static_cast<double>(attitudeOutputs->yprU(1)); }
1446 if (descriptor == "Att::YprU::R [deg]") { return static_cast<double>(attitudeOutputs->yprU(2)); }
1447
1448 // Group 6 (INS)
1449 if (descriptor == "INS::InsStatus::Mode") { return static_cast<double>(insOutputs->insStatus.mode()); }
1450 if (descriptor == "INS::InsStatus::GpsFix") { return static_cast<double>(insOutputs->insStatus.gpsFix()); }
1451 if (descriptor == "INS::InsStatus::Error::IMU") { return static_cast<double>(insOutputs->insStatus.errorIMU()); }
1452 if (descriptor == "INS::InsStatus::Error::MagPres") { return static_cast<double>(insOutputs->insStatus.errorMagPres()); }
1453 if (descriptor == "INS::InsStatus::Error::GNSS") { return static_cast<double>(insOutputs->insStatus.errorGnss()); }
1454 if (descriptor == "INS::InsStatus::GpsHeadingIns") { return static_cast<double>(insOutputs->insStatus.gpsHeadingIns()); }
1455 if (descriptor == "INS::InsStatus::GpsCompass") { return static_cast<double>(insOutputs->insStatus.gpsCompass()); }
1456 if (descriptor == "INS::PosLla::latitude [deg]") { return static_cast<double>(insOutputs->posLla(0)); }
1457 if (descriptor == "INS::PosLla::longitude [deg]") { return static_cast<double>(insOutputs->posLla(1)); }
1458 if (descriptor == "INS::PosLla::altitude [m]") { return static_cast<double>(insOutputs->posLla(2)); }
1459 if (descriptor == "INS::PosEcef::X [m]") { return static_cast<double>(insOutputs->posEcef(0)); }
1460 if (descriptor == "INS::PosEcef::Y [m]") { return static_cast<double>(insOutputs->posEcef(1)); }
1461 if (descriptor == "INS::PosEcef::Z [m]") { return static_cast<double>(insOutputs->posEcef(2)); }
1462 if (descriptor == "INS::VelBody::X [m/s]") { return static_cast<double>(insOutputs->velBody(0)); }
1463 if (descriptor == "INS::VelBody::Y [m/s]") { return static_cast<double>(insOutputs->velBody(1)); }
1464 if (descriptor == "INS::VelBody::Z [m/s]") { return static_cast<double>(insOutputs->velBody(2)); }
1465 if (descriptor == "INS::VelNed::N [m/s]") { return static_cast<double>(insOutputs->velNed(0)); }
1466 if (descriptor == "INS::VelNed::E [m/s]") { return static_cast<double>(insOutputs->velNed(1)); }
1467 if (descriptor == "INS::VelNed::D [m/s]") { return static_cast<double>(insOutputs->velNed(2)); }
1468 if (descriptor == "INS::VelEcef::X [m/s]") { return static_cast<double>(insOutputs->velEcef(0)); }
1469 if (descriptor == "INS::VelEcef::Y [m/s]") { return static_cast<double>(insOutputs->velEcef(1)); }
1470 if (descriptor == "INS::VelEcef::Z [m/s]") { return static_cast<double>(insOutputs->velEcef(2)); }
1471 if (descriptor == "INS::MagEcef::X [Gauss]") { return static_cast<double>(insOutputs->magEcef(0)); }
1472 if (descriptor == "INS::MagEcef::Y [Gauss]") { return static_cast<double>(insOutputs->magEcef(1)); }
1473 if (descriptor == "INS::MagEcef::Z [Gauss]") { return static_cast<double>(insOutputs->magEcef(2)); }
1474 if (descriptor == "INS::AccelEcef::X [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(0)); }
1475 if (descriptor == "INS::AccelEcef::Y [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(1)); }
1476 if (descriptor == "INS::AccelEcef::Z [m/s^2]") { return static_cast<double>(insOutputs->accelEcef(2)); }
1477 if (descriptor == "INS::LinearAccelEcef::X [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(0)); }
1478 if (descriptor == "INS::LinearAccelEcef::Y [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(1)); }
1479 if (descriptor == "INS::LinearAccelEcef::Z [m/s^2]") { return static_cast<double>(insOutputs->linearAccelEcef(2)); }
1480 if (descriptor == "INS::PosU [m]") { return static_cast<double>(insOutputs->posU); }
1481 if (descriptor == "INS::VelU [m/s]") { return static_cast<double>(insOutputs->velU); }
1482
1483 // Group 7 (GNSS2)
1484 if (descriptor == "GNSS2::UTC::year") { return static_cast<double>(gnss2Outputs->timeUtc.year); }
1485 if (descriptor == "GNSS2::UTC::month") { return static_cast<double>(gnss2Outputs->timeUtc.month); }
1486 if (descriptor == "GNSS2::UTC::day") { return static_cast<double>(gnss2Outputs->timeUtc.day); }
1487 if (descriptor == "GNSS2::UTC::hour") { return static_cast<double>(gnss2Outputs->timeUtc.hour); }
1488 if (descriptor == "GNSS2::UTC::min") { return static_cast<double>(gnss2Outputs->timeUtc.min); }
1489 if (descriptor == "GNSS2::UTC::sec") { return static_cast<double>(gnss2Outputs->timeUtc.sec); }
1490 if (descriptor == "GNSS2::UTC::ms") { return static_cast<double>(gnss2Outputs->timeUtc.ms); }
1491 if (descriptor == "GNSS2::Tow [ns]") { return static_cast<double>(gnss2Outputs->tow); }
1492 if (descriptor == "GNSS2::Week") { return static_cast<double>(gnss2Outputs->week); }
1493 if (descriptor == "GNSS2::NumSats") { return static_cast<double>(gnss2Outputs->numSats); }
1494 if (descriptor == "GNSS2::Fix") { return static_cast<double>(gnss2Outputs->fix); }
1495 if (descriptor == "GNSS2::PosLla::latitude [deg]") { return static_cast<double>(gnss2Outputs->posLla(0)); }
1496 if (descriptor == "GNSS2::PosLla::longitude [deg]") { return static_cast<double>(gnss2Outputs->posLla(1)); }
1497 if (descriptor == "GNSS2::PosLla::altitude [m]") { return static_cast<double>(gnss2Outputs->posLla(2)); }
1498 if (descriptor == "GNSS2::PosEcef::X [m]") { return static_cast<double>(gnss2Outputs->posEcef(0)); }
1499 if (descriptor == "GNSS2::PosEcef::Y [m]") { return static_cast<double>(gnss2Outputs->posEcef(1)); }
1500 if (descriptor == "GNSS2::PosEcef::Z [m]") { return static_cast<double>(gnss2Outputs->posEcef(2)); }
1501 if (descriptor == "GNSS2::VelNed::N [m/s]") { return static_cast<double>(gnss2Outputs->velNed(0)); }
1502 if (descriptor == "GNSS2::VelNed::E [m/s]") { return static_cast<double>(gnss2Outputs->velNed(1)); }
1503 if (descriptor == "GNSS2::VelNed::D [m/s]") { return static_cast<double>(gnss2Outputs->velNed(2)); }
1504 if (descriptor == "GNSS2::VelEcef::X [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(0)); }
1505 if (descriptor == "GNSS2::VelEcef::Y [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(1)); }
1506 if (descriptor == "GNSS2::VelEcef::Z [m/s]") { return static_cast<double>(gnss2Outputs->velEcef(2)); }
1507 if (descriptor == "GNSS2::PosU::N [m]") { return static_cast<double>(gnss2Outputs->posU(0)); }
1508 if (descriptor == "GNSS2::PosU::E [m]") { return static_cast<double>(gnss2Outputs->posU(1)); }
1509 if (descriptor == "GNSS2::PosU::D [m]") { return static_cast<double>(gnss2Outputs->posU(2)); }
1510 if (descriptor == "GNSS2::VelU [m/s]") { return static_cast<double>(gnss2Outputs->velU); }
1511 if (descriptor == "GNSS2::TimeU [s]") { return static_cast<double>(gnss2Outputs->timeU); }
1512 if (descriptor == "GNSS2::TimeInfo::Status::timeOk") { return static_cast<double>(gnss2Outputs->timeInfo.status.timeOk()); }
1513 if (descriptor == "GNSS2::TimeInfo::Status::dateOk") { return static_cast<double>(gnss2Outputs->timeInfo.status.dateOk()); }
1514 if (descriptor == "GNSS2::TimeInfo::Status::utcTimeValid") { return static_cast<double>(gnss2Outputs->timeInfo.status.utcTimeValid()); }
1515 if (descriptor == "GNSS2::TimeInfo::LeapSeconds") { return static_cast<double>(gnss2Outputs->timeInfo.leapSeconds); }
1516 if (descriptor == "GNSS2::DOP::g") { return static_cast<double>(gnss2Outputs->dop.gDop); }
1517 if (descriptor == "GNSS2::DOP::p") { return static_cast<double>(gnss2Outputs->dop.pDop); }
1518 if (descriptor == "GNSS2::DOP::t") { return static_cast<double>(gnss2Outputs->dop.tDop); }
1519 if (descriptor == "GNSS2::DOP::v") { return static_cast<double>(gnss2Outputs->dop.vDop); }
1520 if (descriptor == "GNSS2::DOP::h") { return static_cast<double>(gnss2Outputs->dop.hDop); }
1521 if (descriptor == "GNSS2::DOP::n") { return static_cast<double>(gnss2Outputs->dop.nDop); }
1522 if (descriptor == "GNSS2::DOP::e") { return static_cast<double>(gnss2Outputs->dop.eDop); }
1523 if (descriptor == "GNSS2::SatInfo::NumSats") { return static_cast<double>(gnss2Outputs->satInfo.numSats); }
1524 for (auto& satellite : gnss2Outputs->satInfo.satellites)
1525 {
1526 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1527 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); }
1528 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); }
1529 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); }
1530 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); }
1531 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); }
1532 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); }
1533 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); }
1534 if (descriptor == fmt::format("GNSS2::SatInfo::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1535 if (descriptor == fmt::format("GNSS2::SatInfo::{} - qi", satId)) { return static_cast<double>(satellite.qi); }
1536 if (descriptor == fmt::format("GNSS2::SatInfo::{} - el", satId)) { return static_cast<double>(satellite.el); }
1537 if (descriptor == fmt::format("GNSS2::SatInfo::{} - az", satId)) { return static_cast<double>(satellite.az); }
1538 }
1539 if (descriptor == "GNSS2::RawMeas::Tow [s]") { return gnss2Outputs->raw.tow; }
1540 if (descriptor == "GNSS2::RawMeas::Week") { return static_cast<double>(gnss2Outputs->raw.week); }
1541 if (descriptor == "GNSS2::RawMeas::NumSats") { return static_cast<double>(gnss2Outputs->raw.numSats); }
1542 for (auto& satellite : gnss2Outputs->raw.satellites)
1543 {
1544 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1545 if (descriptor == fmt::format("GNSS2::RawMeas::{} - freq", satId)) { return static_cast<double>(satellite.freq); }
1546 if (descriptor == fmt::format("GNSS2::RawMeas::{} - chan", satId)) { return static_cast<double>(satellite.chan); }
1547 if (descriptor == fmt::format("GNSS2::RawMeas::{} - slot", satId)) { return static_cast<double>(satellite.slot); }
1548 if (descriptor == fmt::format("GNSS2::RawMeas::{} - cno", satId)) { return static_cast<double>(satellite.cno); }
1549 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); }
1550 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); }
1551 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); }
1552 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); }
1553 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); }
1554 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); }
1555 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); }
1556 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); }
1557 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); }
1558 if (descriptor == fmt::format("GNSS2::RawMeas::{} - pr", satId)) { return satellite.pr; }
1559 if (descriptor == fmt::format("GNSS2::RawMeas::{} - cp", satId)) { return satellite.cp; }
1560 if (descriptor == fmt::format("GNSS2::RawMeas::{} - dp", satId)) { return static_cast<double>(satellite.dp); }
1561 }
1562
1563 return std::nullopt;
1564 }
1565
1567 [[nodiscard]] std::vector<std::pair<std::string, double>> getDynamicData() const override
1568 {
1569 std::vector<std::pair<std::string, double>> dynData;
1570
1571 // Group 2 (Time)
1572 if (timeOutputs)
1573 {
1574 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTARTUP)
1575 {
1576 dynData.emplace_back("Time::TimeStartup [ns]", static_cast<double>(timeOutputs->timeStartup));
1577 }
1578 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPS)
1579 {
1580 dynData.emplace_back("Time::TimeGps [ns]", static_cast<double>(timeOutputs->timeGps));
1581 }
1582 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
1583 {
1584 dynData.emplace_back("Time::GpsTow [ns]", static_cast<double>(timeOutputs->gpsTow));
1585 }
1586 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK)
1587 {
1588 dynData.emplace_back("Time::GpsWeek", static_cast<double>(timeOutputs->gpsWeek));
1589 }
1590 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESYNCIN)
1591 {
1592 dynData.emplace_back("Time::TimeSyncIn [ns]", static_cast<double>(timeOutputs->timeSyncIn));
1593 }
1594 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEGPSPPS)
1595 {
1596 dynData.emplace_back("Time::TimeGpsPps [ns]", static_cast<double>(timeOutputs->timePPS));
1597 }
1598 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMEUTC)
1599 {
1600 dynData.emplace_back("Time::TimeUTC::year", static_cast<double>(timeOutputs->timeUtc.year));
1601 dynData.emplace_back("Time::TimeUTC::month", static_cast<double>(timeOutputs->timeUtc.month));
1602 dynData.emplace_back("Time::TimeUTC::day", static_cast<double>(timeOutputs->timeUtc.day));
1603 dynData.emplace_back("Time::TimeUTC::hour", static_cast<double>(timeOutputs->timeUtc.hour));
1604 dynData.emplace_back("Time::TimeUTC::min", static_cast<double>(timeOutputs->timeUtc.min));
1605 dynData.emplace_back("Time::TimeUTC::sec", static_cast<double>(timeOutputs->timeUtc.sec));
1606 dynData.emplace_back("Time::TimeUTC::ms", static_cast<double>(timeOutputs->timeUtc.ms));
1607 }
1608 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCINCNT)
1609 {
1610 dynData.emplace_back("Time::SyncInCnt", static_cast<double>(timeOutputs->syncInCnt));
1611 }
1612 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_SYNCOUTCNT)
1613 {
1614 dynData.emplace_back("Time::SyncOutCnt", static_cast<double>(timeOutputs->syncOutCnt));
1615 }
1616 if (timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
1617 {
1618 dynData.emplace_back("Time::TimeStatus::timeOk", static_cast<double>(timeOutputs->timeStatus.timeOk()));
1619 dynData.emplace_back("Time::TimeStatus::dateOk", static_cast<double>(timeOutputs->timeStatus.dateOk()));
1620 dynData.emplace_back("Time::TimeStatus::utcTimeValid", static_cast<double>(timeOutputs->timeStatus.utcTimeValid()));
1621 }
1622 }
1623 // Group 3 (IMU)
1624 if (imuOutputs)
1625 {
1626 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_IMUSTATUS)
1627 {
1628 dynData.emplace_back("IMU::ImuStatus", static_cast<double>(imuOutputs->imuStatus));
1629 }
1630 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
1631 {
1632 dynData.emplace_back("IMU::UncompMag::X [Gauss]", static_cast<double>(imuOutputs->uncompMag(0)));
1633 dynData.emplace_back("IMU::UncompMag::Y [Gauss]", static_cast<double>(imuOutputs->uncompMag(1)));
1634 dynData.emplace_back("IMU::UncompMag::Z [Gauss]", static_cast<double>(imuOutputs->uncompMag(2)));
1635 }
1636 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
1637 {
1638 dynData.emplace_back("IMU::UncompAccel::X [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(0)));
1639 dynData.emplace_back("IMU::UncompAccel::Y [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(1)));
1640 dynData.emplace_back("IMU::UncompAccel::Z [m/s^2]", static_cast<double>(imuOutputs->uncompAccel(2)));
1641 }
1642 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
1643 {
1644 dynData.emplace_back("IMU::UncompGyro::X [rad/s]", static_cast<double>(imuOutputs->uncompGyro(0)));
1645 dynData.emplace_back("IMU::UncompGyro::Y [rad/s]", static_cast<double>(imuOutputs->uncompGyro(1)));
1646 dynData.emplace_back("IMU::UncompGyro::Z [rad/s]", static_cast<double>(imuOutputs->uncompGyro(2)));
1647 }
1648 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
1649 {
1650 dynData.emplace_back("IMU::Temp [Celsius]", static_cast<double>(imuOutputs->temp));
1651 }
1652 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)
1653 {
1654 dynData.emplace_back("IMU::Pres [kPa]", static_cast<double>(imuOutputs->pres));
1655 }
1656 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)
1657 {
1658 dynData.emplace_back("IMU::DeltaTime [s]", static_cast<double>(imuOutputs->deltaTime));
1659 dynData.emplace_back("IMU::DeltaTheta::X [deg]", static_cast<double>(imuOutputs->deltaTheta(0)));
1660 dynData.emplace_back("IMU::DeltaTheta::Y [deg]", static_cast<double>(imuOutputs->deltaTheta(1)));
1661 dynData.emplace_back("IMU::DeltaTheta::Z [deg]", static_cast<double>(imuOutputs->deltaTheta(2)));
1662 }
1663 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)
1664 {
1665 dynData.emplace_back("IMU::DeltaVel::X [m/s]", static_cast<double>(imuOutputs->deltaV(0)));
1666 dynData.emplace_back("IMU::DeltaVel::Y [m/s]", static_cast<double>(imuOutputs->deltaV(1)));
1667 dynData.emplace_back("IMU::DeltaVel::Z [m/s]", static_cast<double>(imuOutputs->deltaV(2)));
1668 }
1669 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
1670 {
1671 dynData.emplace_back("IMU::Mag::X [Gauss]", static_cast<double>(imuOutputs->mag(0)));
1672 dynData.emplace_back("IMU::Mag::Y [Gauss]", static_cast<double>(imuOutputs->mag(1)));
1673 dynData.emplace_back("IMU::Mag::Z [Gauss]", static_cast<double>(imuOutputs->mag(2)));
1674 }
1675 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
1676 {
1677 dynData.emplace_back("IMU::Accel::X [m/s^2]", static_cast<double>(imuOutputs->accel(0)));
1678 dynData.emplace_back("IMU::Accel::Y [m/s^2]", static_cast<double>(imuOutputs->accel(1)));
1679 dynData.emplace_back("IMU::Accel::Z [m/s^2]", static_cast<double>(imuOutputs->accel(2)));
1680 }
1681 if (imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
1682 {
1683 dynData.emplace_back("IMU::AngularRate::X [rad/s]", static_cast<double>(imuOutputs->angularRate(0)));
1684 dynData.emplace_back("IMU::AngularRate::Y [rad/s]", static_cast<double>(imuOutputs->angularRate(1)));
1685 dynData.emplace_back("IMU::AngularRate::Z [rad/s]", static_cast<double>(imuOutputs->angularRate(2)));
1686 }
1687 }
1688
1689 // Group 4 (GNSS1)
1690 if (gnss1Outputs)
1691 {
1692 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1693 {
1694 dynData.emplace_back("GNSS1::UTC::year", static_cast<double>(gnss1Outputs->timeUtc.year));
1695 dynData.emplace_back("GNSS1::UTC::month", static_cast<double>(gnss1Outputs->timeUtc.month));
1696 dynData.emplace_back("GNSS1::UTC::day", static_cast<double>(gnss1Outputs->timeUtc.day));
1697 dynData.emplace_back("GNSS1::UTC::hour", static_cast<double>(gnss1Outputs->timeUtc.hour));
1698 dynData.emplace_back("GNSS1::UTC::min", static_cast<double>(gnss1Outputs->timeUtc.min));
1699 dynData.emplace_back("GNSS1::UTC::sec", static_cast<double>(gnss1Outputs->timeUtc.sec));
1700 dynData.emplace_back("GNSS1::UTC::ms", static_cast<double>(gnss1Outputs->timeUtc.ms));
1701 }
1702 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1703 {
1704 dynData.emplace_back("GNSS1::Tow [ns]", static_cast<double>(gnss1Outputs->tow));
1705 }
1706 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1707 {
1708 dynData.emplace_back("GNSS1::Week", static_cast<double>(gnss1Outputs->week));
1709 }
1710 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1711 {
1712 dynData.emplace_back("GNSS1::NumSats", static_cast<double>(gnss1Outputs->numSats));
1713 }
1714 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1715 {
1716 dynData.emplace_back("GNSS1::Fix", static_cast<double>(gnss1Outputs->fix));
1717 }
1718 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1719 {
1720 dynData.emplace_back("GNSS1::PosLla::latitude [deg]", static_cast<double>(gnss1Outputs->posLla(0)));
1721 dynData.emplace_back("GNSS1::PosLla::longitude [deg]", static_cast<double>(gnss1Outputs->posLla(1)));
1722 dynData.emplace_back("GNSS1::PosLla::altitude [m]", static_cast<double>(gnss1Outputs->posLla(2)));
1723 }
1724 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1725 {
1726 dynData.emplace_back("GNSS1::PosEcef::X [m]", static_cast<double>(gnss1Outputs->posEcef(0)));
1727 dynData.emplace_back("GNSS1::PosEcef::Y [m]", static_cast<double>(gnss1Outputs->posEcef(1)));
1728 dynData.emplace_back("GNSS1::PosEcef::Z [m]", static_cast<double>(gnss1Outputs->posEcef(2)));
1729 }
1730 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
1731 {
1732 dynData.emplace_back("GNSS1::VelNed::N [m/s]", static_cast<double>(gnss1Outputs->velNed(0)));
1733 dynData.emplace_back("GNSS1::VelNed::E [m/s]", static_cast<double>(gnss1Outputs->velNed(1)));
1734 dynData.emplace_back("GNSS1::VelNed::D [m/s]", static_cast<double>(gnss1Outputs->velNed(2)));
1735 }
1736 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
1737 {
1738 dynData.emplace_back("GNSS1::VelEcef::X [m/s]", static_cast<double>(gnss1Outputs->velEcef(0)));
1739 dynData.emplace_back("GNSS1::VelEcef::Y [m/s]", static_cast<double>(gnss1Outputs->velEcef(1)));
1740 dynData.emplace_back("GNSS1::VelEcef::Z [m/s]", static_cast<double>(gnss1Outputs->velEcef(2)));
1741 }
1742 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
1743 {
1744 dynData.emplace_back("GNSS1::PosU::N [m]", static_cast<double>(gnss1Outputs->posU(0)));
1745 dynData.emplace_back("GNSS1::PosU::E [m]", static_cast<double>(gnss1Outputs->posU(1)));
1746 dynData.emplace_back("GNSS1::PosU::D [m]", static_cast<double>(gnss1Outputs->posU(2)));
1747 }
1748 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
1749 {
1750 dynData.emplace_back("GNSS1::VelU [m/s]", static_cast<double>(gnss1Outputs->velU));
1751 }
1752 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
1753 {
1754 dynData.emplace_back("GNSS1::TimeU [s]", static_cast<double>(gnss1Outputs->timeU));
1755 }
1756 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
1757 {
1758 dynData.emplace_back("GNSS1::TimeInfo::Status::timeOk", static_cast<double>(gnss1Outputs->timeInfo.status.timeOk()));
1759 dynData.emplace_back("GNSS1::TimeInfo::Status::dateOk", static_cast<double>(gnss1Outputs->timeInfo.status.dateOk()));
1760 dynData.emplace_back("GNSS1::TimeInfo::Status::utcTimeValid", static_cast<double>(gnss1Outputs->timeInfo.status.utcTimeValid()));
1761 dynData.emplace_back("GNSS1::TimeInfo::LeapSeconds", static_cast<double>(gnss1Outputs->timeInfo.leapSeconds));
1762 }
1763 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
1764 {
1765 dynData.emplace_back("GNSS1::DOP::g", static_cast<double>(gnss1Outputs->dop.gDop));
1766 dynData.emplace_back("GNSS1::DOP::p", static_cast<double>(gnss1Outputs->dop.pDop));
1767 dynData.emplace_back("GNSS1::DOP::t", static_cast<double>(gnss1Outputs->dop.tDop));
1768 dynData.emplace_back("GNSS1::DOP::v", static_cast<double>(gnss1Outputs->dop.vDop));
1769 dynData.emplace_back("GNSS1::DOP::h", static_cast<double>(gnss1Outputs->dop.hDop));
1770 dynData.emplace_back("GNSS1::DOP::n", static_cast<double>(gnss1Outputs->dop.nDop));
1771 dynData.emplace_back("GNSS1::DOP::e", static_cast<double>(gnss1Outputs->dop.eDop));
1772 }
1773 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
1774 {
1775 dynData.emplace_back("GNSS1::SatInfo::NumSats", static_cast<double>(gnss1Outputs->satInfo.numSats));
1776 for (auto& satellite : gnss1Outputs->satInfo.satellites)
1777 {
1778 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1779 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));
1780 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));
1781 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));
1782 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));
1783 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));
1784 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));
1785 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));
1786 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - cno", satId), static_cast<double>(satellite.cno));
1787 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - qi", satId), static_cast<double>(satellite.qi));
1788 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - el", satId), static_cast<double>(satellite.el));
1789 dynData.emplace_back(fmt::format("GNSS1::SatInfo::{} - az", satId), static_cast<double>(satellite.az));
1790 }
1791 }
1792 if (gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
1793 {
1794 dynData.emplace_back("GNSS1::RawMeas::Tow [s]", gnss1Outputs->raw.tow);
1795 dynData.emplace_back("GNSS1::RawMeas::Week", static_cast<double>(gnss1Outputs->raw.week));
1796 dynData.emplace_back("GNSS1::RawMeas::NumSats", static_cast<double>(gnss1Outputs->raw.numSats));
1797 for (auto& satellite : gnss1Outputs->raw.satellites)
1798 {
1799 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
1800 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - freq", satId), static_cast<double>(satellite.freq));
1801 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - chan", satId), static_cast<double>(satellite.chan));
1802 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - slot", satId), static_cast<double>(satellite.slot));
1803 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - cno", satId), static_cast<double>(satellite.cno));
1804 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));
1805 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));
1806 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));
1807 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));
1808 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));
1809 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));
1810 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));
1811 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));
1812 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));
1813 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - pr", satId), satellite.pr);
1814 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - cp", satId), satellite.cp);
1815 dynData.emplace_back(fmt::format("GNSS1::RawMeas::{} - dp", satId), static_cast<double>(satellite.dp));
1816 }
1817 }
1818 }
1819
1820 // Group 5 (Attitude)
1821 if (attitudeOutputs)
1822 {
1823 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_VPESTATUS)
1824 {
1825 dynData.emplace_back("Att::VpeStatus::AttitudeQuality", static_cast<double>(attitudeOutputs->vpeStatus.attitudeQuality()));
1826 dynData.emplace_back("Att::VpeStatus::GyroSaturation", static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturation()));
1827 dynData.emplace_back("Att::VpeStatus::GyroSaturationRecovery", static_cast<double>(attitudeOutputs->vpeStatus.gyroSaturationRecovery()));
1828 dynData.emplace_back("Att::VpeStatus::MagDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.magDisturbance()));
1829 dynData.emplace_back("Att::VpeStatus::MagSaturation", static_cast<double>(attitudeOutputs->vpeStatus.magSaturation()));
1830 dynData.emplace_back("Att::VpeStatus::AccDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.accDisturbance()));
1831 dynData.emplace_back("Att::VpeStatus::AccSaturation", static_cast<double>(attitudeOutputs->vpeStatus.accSaturation()));
1832 dynData.emplace_back("Att::VpeStatus::KnownMagDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.knownMagDisturbance()));
1833 dynData.emplace_back("Att::VpeStatus::KnownAccelDisturbance", static_cast<double>(attitudeOutputs->vpeStatus.knownAccelDisturbance()));
1834 }
1835 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)
1836 {
1837 dynData.emplace_back("Att::YawPitchRoll::Y [deg]", static_cast<double>(attitudeOutputs->ypr(0)));
1838 dynData.emplace_back("Att::YawPitchRoll::P [deg]", static_cast<double>(attitudeOutputs->ypr(1)));
1839 dynData.emplace_back("Att::YawPitchRoll::R [deg]", static_cast<double>(attitudeOutputs->ypr(2)));
1840 }
1841 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)
1842 {
1843 dynData.emplace_back("Att::Quaternion::w", static_cast<double>(attitudeOutputs->qtn.w()));
1844 dynData.emplace_back("Att::Quaternion::x", static_cast<double>(attitudeOutputs->qtn.x()));
1845 dynData.emplace_back("Att::Quaternion::y", static_cast<double>(attitudeOutputs->qtn.y()));
1846 dynData.emplace_back("Att::Quaternion::z", static_cast<double>(attitudeOutputs->qtn.z()));
1847 }
1848 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)
1849 {
1850 dynData.emplace_back("Att::DCM::0-0", static_cast<double>(attitudeOutputs->dcm(0, 0)));
1851 dynData.emplace_back("Att::DCM::0-1", static_cast<double>(attitudeOutputs->dcm(0, 1)));
1852 dynData.emplace_back("Att::DCM::0-2", static_cast<double>(attitudeOutputs->dcm(0, 2)));
1853 dynData.emplace_back("Att::DCM::1-0", static_cast<double>(attitudeOutputs->dcm(1, 0)));
1854 dynData.emplace_back("Att::DCM::1-1", static_cast<double>(attitudeOutputs->dcm(1, 1)));
1855 dynData.emplace_back("Att::DCM::1-2", static_cast<double>(attitudeOutputs->dcm(1, 2)));
1856 dynData.emplace_back("Att::DCM::2-0", static_cast<double>(attitudeOutputs->dcm(2, 0)));
1857 dynData.emplace_back("Att::DCM::2-1", static_cast<double>(attitudeOutputs->dcm(2, 1)));
1858 dynData.emplace_back("Att::DCM::2-2", static_cast<double>(attitudeOutputs->dcm(2, 2)));
1859 }
1860 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_MAGNED)
1861 {
1862 dynData.emplace_back("Att::MagNed::N [Gauss]", static_cast<double>(attitudeOutputs->magNed(0)));
1863 dynData.emplace_back("Att::MagNed::E [Gauss]", static_cast<double>(attitudeOutputs->magNed(1)));
1864 dynData.emplace_back("Att::MagNed::D [Gauss]", static_cast<double>(attitudeOutputs->magNed(2)));
1865 }
1866 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_ACCELNED)
1867 {
1868 dynData.emplace_back("Att::AccelNed::N [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(0)));
1869 dynData.emplace_back("Att::AccelNed::E [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(1)));
1870 dynData.emplace_back("Att::AccelNed::D [m/s^2]", static_cast<double>(attitudeOutputs->accelNed(2)));
1871 }
1872 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELBODY)
1873 {
1874 dynData.emplace_back("Att::LinearAccelBody::X [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(0)));
1875 dynData.emplace_back("Att::LinearAccelBody::Y [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(1)));
1876 dynData.emplace_back("Att::LinearAccelBody::Z [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelBody(2)));
1877 }
1878 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_LINEARACCELNED)
1879 {
1880 dynData.emplace_back("Att::LinearAccelNed::N [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(0)));
1881 dynData.emplace_back("Att::LinearAccelNed::E [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(1)));
1882 dynData.emplace_back("Att::LinearAccelNed::D [m/s^2]", static_cast<double>(attitudeOutputs->linearAccelNed(2)));
1883 }
1884 if (attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YPRU)
1885 {
1886 dynData.emplace_back("Att::YprU::Y [deg]", static_cast<double>(attitudeOutputs->yprU(0)));
1887 dynData.emplace_back("Att::YprU::P [deg]", static_cast<double>(attitudeOutputs->yprU(1)));
1888 dynData.emplace_back("Att::YprU::R [deg]", static_cast<double>(attitudeOutputs->yprU(2)));
1889 }
1890 }
1891
1892 // Group 6 (INS)
1893 if (insOutputs)
1894 {
1895 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_INSSTATUS)
1896 {
1897 dynData.emplace_back("INS::InsStatus::Mode", static_cast<double>(insOutputs->insStatus.mode()));
1898 dynData.emplace_back("INS::InsStatus::GpsFix", static_cast<double>(insOutputs->insStatus.gpsFix()));
1899 dynData.emplace_back("INS::InsStatus::Error::IMU", static_cast<double>(insOutputs->insStatus.errorIMU()));
1900 dynData.emplace_back("INS::InsStatus::Error::MagPres", static_cast<double>(insOutputs->insStatus.errorMagPres()));
1901 dynData.emplace_back("INS::InsStatus::Error::GNSS", static_cast<double>(insOutputs->insStatus.errorGnss()));
1902 dynData.emplace_back("INS::InsStatus::GpsHeadingIns", static_cast<double>(insOutputs->insStatus.gpsHeadingIns()));
1903 dynData.emplace_back("INS::InsStatus::GpsCompass", static_cast<double>(insOutputs->insStatus.gpsCompass()));
1904 }
1905 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)
1906 {
1907 dynData.emplace_back("INS::PosLla::latitude [deg]", static_cast<double>(insOutputs->posLla(0)));
1908 dynData.emplace_back("INS::PosLla::longitude [deg]", static_cast<double>(insOutputs->posLla(1)));
1909 dynData.emplace_back("INS::PosLla::altitude [m]", static_cast<double>(insOutputs->posLla(2)));
1910 }
1911 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)
1912 {
1913 dynData.emplace_back("INS::PosEcef::X [m]", static_cast<double>(insOutputs->posEcef(0)));
1914 dynData.emplace_back("INS::PosEcef::Y [m]", static_cast<double>(insOutputs->posEcef(1)));
1915 dynData.emplace_back("INS::PosEcef::Z [m]", static_cast<double>(insOutputs->posEcef(2)));
1916 }
1917 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)
1918 {
1919 dynData.emplace_back("INS::VelBody::X [m/s]", static_cast<double>(insOutputs->velBody(0)));
1920 dynData.emplace_back("INS::VelBody::Y [m/s]", static_cast<double>(insOutputs->velBody(1)));
1921 dynData.emplace_back("INS::VelBody::Z [m/s]", static_cast<double>(insOutputs->velBody(2)));
1922 }
1923 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)
1924 {
1925 dynData.emplace_back("INS::VelNed::N [m/s]", static_cast<double>(insOutputs->velNed(0)));
1926 dynData.emplace_back("INS::VelNed::E [m/s]", static_cast<double>(insOutputs->velNed(1)));
1927 dynData.emplace_back("INS::VelNed::D [m/s]", static_cast<double>(insOutputs->velNed(2)));
1928 }
1929 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)
1930 {
1931 dynData.emplace_back("INS::VelEcef::X [m/s]", static_cast<double>(insOutputs->velEcef(0)));
1932 dynData.emplace_back("INS::VelEcef::Y [m/s]", static_cast<double>(insOutputs->velEcef(1)));
1933 dynData.emplace_back("INS::VelEcef::Z [m/s]", static_cast<double>(insOutputs->velEcef(2)));
1934 }
1935 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_MAGECEF)
1936 {
1937 dynData.emplace_back("INS::MagEcef::X [Gauss]", static_cast<double>(insOutputs->magEcef(0)));
1938 dynData.emplace_back("INS::MagEcef::Y [Gauss]", static_cast<double>(insOutputs->magEcef(1)));
1939 dynData.emplace_back("INS::MagEcef::Z [Gauss]", static_cast<double>(insOutputs->magEcef(2)));
1940 }
1941 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_ACCELECEF)
1942 {
1943 dynData.emplace_back("INS::AccelEcef::X [m/s^2]", static_cast<double>(insOutputs->accelEcef(0)));
1944 dynData.emplace_back("INS::AccelEcef::Y [m/s^2]", static_cast<double>(insOutputs->accelEcef(1)));
1945 dynData.emplace_back("INS::AccelEcef::Z [m/s^2]", static_cast<double>(insOutputs->accelEcef(2)));
1946 }
1947 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_LINEARACCELECEF)
1948 {
1949 dynData.emplace_back("INS::LinearAccelEcef::X [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(0)));
1950 dynData.emplace_back("INS::LinearAccelEcef::Y [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(1)));
1951 dynData.emplace_back("INS::LinearAccelEcef::Z [m/s^2]", static_cast<double>(insOutputs->linearAccelEcef(2)));
1952 }
1953 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSU)
1954 {
1955 dynData.emplace_back("INS::PosU [m]", static_cast<double>(insOutputs->posU));
1956 }
1957 if (insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELU)
1958 {
1959 dynData.emplace_back("INS::VelU [m/s]", static_cast<double>(insOutputs->velU));
1960 }
1961 }
1962
1963 // Group 7 (GNSS2)
1964 if (gnss2Outputs)
1965 {
1966 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_UTC)
1967 {
1968 dynData.emplace_back("GNSS2::UTC::year", static_cast<double>(gnss2Outputs->timeUtc.year));
1969 dynData.emplace_back("GNSS2::UTC::month", static_cast<double>(gnss2Outputs->timeUtc.month));
1970 dynData.emplace_back("GNSS2::UTC::day", static_cast<double>(gnss2Outputs->timeUtc.day));
1971 dynData.emplace_back("GNSS2::UTC::hour", static_cast<double>(gnss2Outputs->timeUtc.hour));
1972 dynData.emplace_back("GNSS2::UTC::min", static_cast<double>(gnss2Outputs->timeUtc.min));
1973 dynData.emplace_back("GNSS2::UTC::sec", static_cast<double>(gnss2Outputs->timeUtc.sec));
1974 dynData.emplace_back("GNSS2::UTC::ms", static_cast<double>(gnss2Outputs->timeUtc.ms));
1975 }
1976 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TOW)
1977 {
1978 dynData.emplace_back("GNSS2::Tow [ns]", static_cast<double>(gnss2Outputs->tow));
1979 }
1980 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_WEEK)
1981 {
1982 dynData.emplace_back("GNSS2::Week", static_cast<double>(gnss2Outputs->week));
1983 }
1984 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_NUMSATS)
1985 {
1986 dynData.emplace_back("GNSS2::NumSats", static_cast<double>(gnss2Outputs->numSats));
1987 }
1988 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_FIX)
1989 {
1990 dynData.emplace_back("GNSS2::Fix", static_cast<double>(gnss2Outputs->fix));
1991 }
1992 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
1993 {
1994 dynData.emplace_back("GNSS2::PosLla::latitude [deg]", static_cast<double>(gnss2Outputs->posLla(0)));
1995 dynData.emplace_back("GNSS2::PosLla::longitude [deg]", static_cast<double>(gnss2Outputs->posLla(1)));
1996 dynData.emplace_back("GNSS2::PosLla::altitude [m]", static_cast<double>(gnss2Outputs->posLla(2)));
1997 }
1998 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
1999 {
2000 dynData.emplace_back("GNSS2::PosEcef::X [m]", static_cast<double>(gnss2Outputs->posEcef(0)));
2001 dynData.emplace_back("GNSS2::PosEcef::Y [m]", static_cast<double>(gnss2Outputs->posEcef(1)));
2002 dynData.emplace_back("GNSS2::PosEcef::Z [m]", static_cast<double>(gnss2Outputs->posEcef(2)));
2003 }
2004 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
2005 {
2006 dynData.emplace_back("GNSS2::VelNed::N [m/s]", static_cast<double>(gnss2Outputs->velNed(0)));
2007 dynData.emplace_back("GNSS2::VelNed::E [m/s]", static_cast<double>(gnss2Outputs->velNed(1)));
2008 dynData.emplace_back("GNSS2::VelNed::D [m/s]", static_cast<double>(gnss2Outputs->velNed(2)));
2009 }
2010 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
2011 {
2012 dynData.emplace_back("GNSS2::VelEcef::X [m/s]", static_cast<double>(gnss2Outputs->velEcef(0)));
2013 dynData.emplace_back("GNSS2::VelEcef::Y [m/s]", static_cast<double>(gnss2Outputs->velEcef(1)));
2014 dynData.emplace_back("GNSS2::VelEcef::Z [m/s]", static_cast<double>(gnss2Outputs->velEcef(2)));
2015 }
2016 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSU)
2017 {
2018 dynData.emplace_back("GNSS2::PosU::N [m]", static_cast<double>(gnss2Outputs->posU(0)));
2019 dynData.emplace_back("GNSS2::PosU::E [m]", static_cast<double>(gnss2Outputs->posU(1)));
2020 dynData.emplace_back("GNSS2::PosU::D [m]", static_cast<double>(gnss2Outputs->posU(2)));
2021 }
2022 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELU)
2023 {
2024 dynData.emplace_back("GNSS2::VelU [m/s]", static_cast<double>(gnss2Outputs->velU));
2025 }
2026 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEU)
2027 {
2028 dynData.emplace_back("GNSS2::TimeU [s]", static_cast<double>(gnss2Outputs->timeU));
2029 }
2030 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_TIMEINFO)
2031 {
2032 dynData.emplace_back("GNSS2::TimeInfo::Status::timeOk", static_cast<double>(gnss2Outputs->timeInfo.status.timeOk()));
2033 dynData.emplace_back("GNSS2::TimeInfo::Status::dateOk", static_cast<double>(gnss2Outputs->timeInfo.status.dateOk()));
2034 dynData.emplace_back("GNSS2::TimeInfo::Status::utcTimeValid", static_cast<double>(gnss2Outputs->timeInfo.status.utcTimeValid()));
2035 dynData.emplace_back("GNSS2::TimeInfo::LeapSeconds", static_cast<double>(gnss2Outputs->timeInfo.leapSeconds));
2036 }
2037 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_DOP)
2038 {
2039 dynData.emplace_back("GNSS2::DOP::g", static_cast<double>(gnss2Outputs->dop.gDop));
2040 dynData.emplace_back("GNSS2::DOP::p", static_cast<double>(gnss2Outputs->dop.pDop));
2041 dynData.emplace_back("GNSS2::DOP::t", static_cast<double>(gnss2Outputs->dop.tDop));
2042 dynData.emplace_back("GNSS2::DOP::v", static_cast<double>(gnss2Outputs->dop.vDop));
2043 dynData.emplace_back("GNSS2::DOP::h", static_cast<double>(gnss2Outputs->dop.hDop));
2044 dynData.emplace_back("GNSS2::DOP::n", static_cast<double>(gnss2Outputs->dop.nDop));
2045 dynData.emplace_back("GNSS2::DOP::e", static_cast<double>(gnss2Outputs->dop.eDop));
2046 }
2047 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_SATINFO)
2048 {
2049 dynData.emplace_back("GNSS2::SatInfo::NumSats", static_cast<double>(gnss2Outputs->satInfo.numSats));
2050 for (auto& satellite : gnss2Outputs->satInfo.satellites)
2051 {
2052 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
2053 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));
2054 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));
2055 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));
2056 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));
2057 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));
2058 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));
2059 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));
2060 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - cno", satId), static_cast<double>(satellite.cno));
2061 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - qi", satId), static_cast<double>(satellite.qi));
2062 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - el", satId), static_cast<double>(satellite.el));
2063 dynData.emplace_back(fmt::format("GNSS2::SatInfo::{} - az", satId), static_cast<double>(satellite.az));
2064 }
2065 }
2066 if (gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
2067 {
2068 dynData.emplace_back("GNSS2::RawMeas::Tow [s]", gnss2Outputs->raw.tow);
2069 dynData.emplace_back("GNSS2::RawMeas::Week", static_cast<double>(gnss2Outputs->raw.week));
2070 dynData.emplace_back("GNSS2::RawMeas::NumSats", static_cast<double>(gnss2Outputs->raw.numSats));
2071 for (auto& satellite : gnss2Outputs->raw.satellites)
2072 {
2073 SatId satId(getSatSys(satellite.sys), static_cast<uint16_t>(satellite.svId));
2074 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - freq", satId), static_cast<double>(satellite.freq));
2075 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - chan", satId), static_cast<double>(satellite.chan));
2076 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - slot", satId), static_cast<double>(satellite.slot));
2077 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - cno", satId), static_cast<double>(satellite.cno));
2078 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));
2079 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));
2080 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));
2081 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));
2082 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));
2083 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));
2084 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));
2085 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));
2086 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));
2087 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - pr", satId), satellite.pr);
2088 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - cp", satId), satellite.cp);
2089 dynData.emplace_back(fmt::format("GNSS2::RawMeas::{} - dp", satId), static_cast<double>(satellite.dp));
2090 }
2091 }
2092 }
2093
2094 return dynData;
2095 }
2096
2097 // ------------------------------------------ Public members ---------------------------------------------
2098
2100 std::shared_ptr<vendor::vectornav::TimeOutputs> timeOutputs = nullptr;
2101
2103 std::shared_ptr<vendor::vectornav::ImuOutputs> imuOutputs = nullptr;
2104
2106 std::shared_ptr<vendor::vectornav::GnssOutputs> gnss1Outputs = nullptr;
2107
2109 std::shared_ptr<vendor::vectornav::AttitudeOutputs> attitudeOutputs = nullptr;
2110
2112 std::shared_ptr<vendor::vectornav::InsOutputs> insOutputs = nullptr;
2113
2115 std::shared_ptr<vendor::vectornav::GnssOutputs> gnss2Outputs = nullptr;
2116
2119};
2120
2121} // namespace NAV
#define INS_ASSERT(_EXPR)
Assert function wrapper.
Definition Assert.h:19
Vector space operations.
Imu Position Data.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Abstract NodeData Class.
Structs identifying a unique satellite.
GNSS Satellite System.
@ GPS
Global Positioning System.
Definition SatelliteSystem.hpp:33
@ QZSS
Quasi-Zenith Satellite System.
Definition SatelliteSystem.hpp:37
@ GLO
Globalnaja nawigazionnaja sputnikowaja sistema (GLONASS)
Definition SatelliteSystem.hpp:35
@ GAL
Galileo.
Definition SatelliteSystem.hpp:34
@ SBAS
Satellite Based Augmentation System.
Definition SatelliteSystem.hpp:39
@ BDS
Beidou.
Definition SatelliteSystem.hpp:36
@ SatSys_None
No Satellite system.
Definition SatelliteSystem.hpp:32
Binary Group 5 - Attitude Outputs.
Type Definitions for VectorNav messages.
SatSys
Satellite Constellation.
Definition VectorNavTypes.hpp:142
@ QZSS
QZSS.
Definition VectorNavTypes.hpp:148
@ SBAS
SBAS.
Definition VectorNavTypes.hpp:144
@ Galileo
Galileo.
Definition VectorNavTypes.hpp:145
@ GLONASS
GLONASS.
Definition VectorNavTypes.hpp:149
@ BeiDou
BeiDou.
Definition VectorNavTypes.hpp:146
@ GPS
GPS.
Definition VectorNavTypes.hpp:143
@ IMES
IMES.
Definition VectorNavTypes.hpp:147
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.
Definition VectorNavBinaryOutput.hpp:82
std::shared_ptr< vendor::vectornav::TimeOutputs > timeOutputs
Binary Group 2 - Time Outputs.
Definition VectorNavBinaryOutput.hpp:2100
std::string getType() const override
Returns the type of the data class.
Definition VectorNavBinaryOutput.hpp:55
VectorNavBinaryOutput(const ImuPos &imuPos)
Constructor.
Definition VectorNavBinaryOutput.hpp:43
std::shared_ptr< vendor::vectornav::ImuOutputs > imuOutputs
Binary Group 3 - IMU Outputs.
Definition VectorNavBinaryOutput.hpp:2103
static constexpr size_t GetStaticDescriptorCount()
Get the amount of descriptors.
Definition VectorNavBinaryOutput.hpp:71
std::shared_ptr< vendor::vectornav::InsOutputs > insOutputs
Binary Group 6 - INS Outputs.
Definition VectorNavBinaryOutput.hpp:2112
static std::vector< std::string > GetStaticDataDescriptors()
Returns a vector of data descriptors.
Definition VectorNavBinaryOutput.hpp:65
static std::string type()
Returns the type of the data class.
Definition VectorNavBinaryOutput.hpp:48
static SatelliteSystem getSatSys(vendor::vectornav::SatSys &sys)
Get the Sat Sys object in "INSTINCT" format.
Definition VectorNavBinaryOutput.hpp:717
static std::vector< std::string > parentTypes()
Returns the parent types of the data class.
Definition VectorNavBinaryOutput.hpp:59
std::vector< std::pair< std::string, double > > getDynamicData() const override
Returns a vector of data descriptors and values for the dynamic data.
Definition VectorNavBinaryOutput.hpp:1567
std::vector< std::string > staticDataDescriptors() const override
Returns a vector of data descriptors.
Definition VectorNavBinaryOutput.hpp:74
std::vector< std::string > dynamicDataDescriptors() const override
Returns a vector of data descriptors for the dynamic data.
Definition VectorNavBinaryOutput.hpp:751
const ImuPos & imuPos
Position and rotation information for conversion from platform to body frame.
Definition VectorNavBinaryOutput.hpp:2118
std::shared_ptr< vendor::vectornav::GnssOutputs > gnss2Outputs
Binary Group 7 - GNSS2 Outputs.
Definition VectorNavBinaryOutput.hpp:2115
std::optional< double > getDynamicDataAt(const std::string &descriptor) const override
Get the value for the descriptor.
Definition VectorNavBinaryOutput.hpp:1277
size_t staticDescriptorCount() const override
Get the amount of descriptors.
Definition VectorNavBinaryOutput.hpp:77
std::shared_ptr< vendor::vectornav::GnssOutputs > gnss1Outputs
Binary Group 4 - GNSS1 Outputs.
Definition VectorNavBinaryOutput.hpp:2106
std::shared_ptr< vendor::vectornav::AttitudeOutputs > attitudeOutputs
Binary Group 5 - Attitude Outputs.
Definition VectorNavBinaryOutput.hpp:2109
Identifies a satellite (satellite system and number)
Definition SatelliteIdentifier.hpp:34
Satellite System type.
Definition SatelliteSystem.hpp:44
@ PseudorangeSmoothed
Pseudorange Smoothed.
Definition VectorNavTypes.hpp:280
@ Tracking
Tracking.
Definition VectorNavTypes.hpp:273
@ TimeValid
Time Valid.
Definition VectorNavTypes.hpp:274
@ PhaseHalfAmbiguity
Phase Half Ambiguity.
Definition VectorNavTypes.hpp:277
@ PhaseLock
Phase Lock.
Definition VectorNavTypes.hpp:276
@ Searching
Searching.
Definition VectorNavTypes.hpp:272
@ PhaseHalfSub
Phase Half Sub.
Definition VectorNavTypes.hpp:278
@ CodeLock
Code Lock.
Definition VectorNavTypes.hpp:275
@ PhaseSlip
Phase Slip.
Definition VectorNavTypes.hpp:279
@ UsedForRTK
Used for RTK.
Definition VectorNavTypes.hpp:179
@ Healthy
Healthy.
Definition VectorNavTypes.hpp:173
@ DifferentialCorrection
Differential Correction.
Definition VectorNavTypes.hpp:176
@ Ephemeris
Ephemeris.
Definition VectorNavTypes.hpp:175
@ UsedForNavigation
Used for Navigation.
Definition VectorNavTypes.hpp:177
@ AzimuthElevationValid
Azimuth / Elevation Valid.
Definition VectorNavTypes.hpp:178
@ Almanac
Almanac.
Definition VectorNavTypes.hpp:174