INSTINCT Code Coverage Report


Directory: src/
File: Nodes/Converter/IMU/VectorNavBinaryConverter.cpp
Date: 2025-11-25 23:34:18
Exec Total Coverage
Lines: 123 759 16.2%
Functions: 9 16 56.2%
Branches: 146 1175 12.4%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "VectorNavBinaryConverter.hpp"
10
11 #include <cmath>
12
13 #include "Navigation/Time/InsTime.hpp"
14 #include "NodeData/Baro/BaroPressObs.hpp"
15 #include "util/Logger.hpp"
16
17 #include "internal/FlowManager.hpp"
18
19 #include "internal/gui/widgets/EnumCombo.hpp"
20
21 #include "Navigation/Transformations/CoordinateFrames.hpp"
22 #include "Navigation/Transformations/Units.hpp"
23
24 /// @brief Scale factor to kPa to hPa
25 constexpr double SCALE_FACTOR_KILO2HECTOPASCAL = 10;
26
27 146 NAV::VectorNavBinaryConverter::VectorNavBinaryConverter()
28
2/4
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 146 times.
✗ Branch 5 not taken.
146 : Node(typeStatic())
29 {
30 LOG_TRACE("{}: called", name);
31 146 _hasConfig = true;
32 146 _guiConfigDefaultWindowSize = { 350, 123 };
33
34
4/8
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 146 times.
✓ Branch 10 taken 146 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
584 CreateOutputPin("ImuObs", Pin::Type::Flow, { NAV::ImuObsWDelta::type() });
35
36
4/8
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 146 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 146 times.
✓ Branch 9 taken 146 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
438 CreateInputPin("BinaryOutput", Pin::Type::Flow, { NAV::VectorNavBinaryOutput::type() }, &VectorNavBinaryConverter::receiveObs);
37 438 }
38
39 356 NAV::VectorNavBinaryConverter::~VectorNavBinaryConverter()
40 {
41 LOG_TRACE("{}: called", nameId());
42 356 }
43
44 260 std::string NAV::VectorNavBinaryConverter::typeStatic()
45 {
46
1/2
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
520 return "VectorNavBinaryConverter";
47 }
48
49 std::string NAV::VectorNavBinaryConverter::type() const
50 {
51 return typeStatic();
52 }
53
54 114 std::string NAV::VectorNavBinaryConverter::category()
55 {
56
1/2
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
228 return "Converter";
57 }
58
59 void NAV::VectorNavBinaryConverter::guiConfig()
60 {
61 if (gui::widgets::EnumCombo(fmt::format("Output Type##{}", size_t(id)).c_str(), _outputType))
62 {
63 LOG_DEBUG("{}: Output Type changed to {}", nameId(), to_string(_outputType));
64 if (_outputType == OutputType::ImuObs)
65 {
66 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::ImuObs::type() };
67 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::ImuObs::type();
68 }
69 else if (_outputType == OutputType::ImuObsWDelta)
70 {
71 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::ImuObsWDelta::type() };
72 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::ImuObsWDelta::type();
73 }
74 else if (_outputType == OutputType::BaroPressObs)
75 {
76 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::BaroPressObs::type() };
77 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::BaroPressObs::type();
78 }
79 else if (_outputType == OutputType::PosVelAtt)
80 {
81 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::PosVelAtt::type() };
82 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::PosVelAtt::type();
83 }
84 else if (_outputType == OutputType::GnssObs)
85 {
86 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::GnssObs::type() };
87 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::GnssObs::type();
88 }
89
90 for (auto& link : outputPins.front().links)
91 {
92 if (auto* connectedPin = link.getConnectedPin())
93 {
94 outputPins.front().recreateLink(*connectedPin);
95 }
96 }
97
98 flow::ApplyChanges();
99 }
100 if (_outputType == OutputType::ImuObsWDelta || _outputType == OutputType::ImuObs)
101 {
102 if (ImGui::Checkbox(fmt::format("Use compensated data##{}", size_t(id)).c_str(), &_useCompensatedData))
103 {
104 LOG_DEBUG("{}: _useCompensatedData changed to {}", nameId(), _useCompensatedData);
105 flow::ApplyChanges();
106 }
107 }
108 else if (_outputType == OutputType::PosVelAtt)
109 {
110 if (auto posVelSource = static_cast<int>(_posVelSource);
111 ImGui::Combo(fmt::format("Data Source##{}", size_t(id)).c_str(), &posVelSource, "Best\0INS\0GNSS 1\0GNSS 2\0\0"))
112 {
113 _posVelSource = static_cast<decltype(_posVelSource)>(posVelSource);
114 LOG_DEBUG("{}: _posVelSource changed to {}", nameId(), fmt::underlying(_posVelSource));
115 flow::ApplyChanges();
116 }
117 if (ImGui::Checkbox(fmt::format("Force static##{}", size_t(id)).c_str(), &_forceStatic))
118 {
119 LOG_DEBUG("{}: _forceStatic changed to {}", nameId(), _forceStatic);
120 flow::ApplyChanges();
121 }
122 }
123 }
124
125 [[nodiscard]] json NAV::VectorNavBinaryConverter::save() const
126 {
127 LOG_TRACE("{}: called", nameId());
128
129 json j;
130
131 j["outputType"] = _outputType;
132 j["posVelSource"] = _posVelSource;
133 j["forceStatic"] = _forceStatic;
134 j["useCompensatedData"] = _useCompensatedData;
135
136 return j;
137 }
138
139 32 void NAV::VectorNavBinaryConverter::restore(json const& j)
140 {
141 LOG_TRACE("{}: called", nameId());
142
143
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (j.contains("outputType"))
144 {
145 32 j.at("outputType").get_to(_outputType);
146
147
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (!outputPins.empty())
148 {
149
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (_outputType == OutputType::ImuObsWDelta)
150 {
151
3/6
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 16 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
32 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::ImuObsWDelta::type() };
152
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::ImuObsWDelta::type();
153 }
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 else if (_outputType == OutputType::ImuObs)
155 {
156 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::ImuObs::type() };
157 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::ImuObs::type();
158 }
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 else if (_outputType == OutputType::BaroPressObs)
160 {
161 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::BaroPressObs::type() };
162 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::BaroPressObs::type();
163 }
164
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 else if (_outputType == OutputType::PosVelAtt)
165 {
166
3/6
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 16 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
32 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::PosVelAtt::type() };
167
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::PosVelAtt::type();
168 }
169 else if (_outputType == OutputType::GnssObs)
170 {
171 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).dataIdentifier = { NAV::GnssObs::type() };
172 outputPins.at(OUTPUT_PORT_INDEX_CONVERTED).name = NAV::GnssObs::type();
173 }
174 }
175 }
176
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (j.contains("posVelSource"))
177 {
178 32 j.at("posVelSource").get_to(_posVelSource);
179 }
180
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (j.contains("forceStatic"))
181 {
182 32 _forceStatic = j.at("forceStatic");
183 }
184
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (j.contains("useCompensatedData"))
185 {
186 32 _useCompensatedData = j.at("useCompensatedData");
187 }
188 64 }
189
190 96 bool NAV::VectorNavBinaryConverter::initialize()
191 {
192 LOG_TRACE("{}: called", nameId());
193
194 96 _posVelAtt__init = nullptr;
195
196 96 return true;
197 }
198
199 28384 void NAV::VectorNavBinaryConverter::receiveObs(NAV::InputPin::NodeDataQueue& queue, size_t /* pinIdx */)
200 {
201
1/2
✓ Branch 1 taken 28384 times.
✗ Branch 2 not taken.
28384 auto vnObs = std::static_pointer_cast<const VectorNavBinaryOutput>(queue.extract_front());
202
203 28384 std::shared_ptr<const NodeData> convertedData = nullptr;
204
205
2/2
✓ Branch 0 taken 25776 times.
✓ Branch 1 taken 2608 times.
28384 if (_outputType == OutputType::ImuObsWDelta)
206 {
207
1/2
✓ Branch 1 taken 25776 times.
✗ Branch 2 not taken.
25776 convertedData = convert2ImuObsWDelta(vnObs);
208 }
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
2608 else if (_outputType == OutputType::ImuObs)
210 {
211 convertedData = convert2ImuObs(vnObs);
212 }
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
2608 else if (_outputType == OutputType::BaroPressObs)
214 {
215 convertedData = convert2BaroPressObs(vnObs);
216 }
217
1/2
✓ Branch 0 taken 2608 times.
✗ Branch 1 not taken.
2608 else if (_outputType == OutputType::PosVelAtt)
218 {
219
1/2
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
2608 convertedData = convert2PosVelAtt(vnObs);
220 }
221 else if (_outputType == OutputType::GnssObs)
222 {
223 convertedData = convert2GnssObs(vnObs);
224 }
225
226
1/2
✓ Branch 1 taken 28384 times.
✗ Branch 2 not taken.
28384 if (convertedData)
227 {
228
1/2
✓ Branch 1 taken 28384 times.
✗ Branch 2 not taken.
28384 invokeCallbacks(OUTPUT_PORT_INDEX_CONVERTED, convertedData);
229 }
230 28384 }
231
232 25776 std::shared_ptr<const NAV::ImuObsWDelta> NAV::VectorNavBinaryConverter::convert2ImuObsWDelta(const std::shared_ptr<const VectorNavBinaryOutput>& vnObs) const // NOLINT(readability-convert-member-functions-to-static)
233 {
234
1/2
✓ Branch 2 taken 25776 times.
✗ Branch 3 not taken.
25776 auto imuObs = std::make_shared<ImuObsWDelta>(vnObs->imuPos);
235
236
2/6
✗ Branch 2 not taken.
✓ Branch 3 taken 25776 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 25776 times.
✗ Branch 9 not taken.
25776 if (vnObs->gnss1Outputs || vnObs->gnss2Outputs) // If there is no GNSS data selected in the vnSensor, Imu messages should still be sent out. The VN-100 will not provide any data otherwise.
237 {
238 25776 if (!vnObs->timeOutputs
239
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
240
1/2
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
25776 || !vnObs->timeOutputs->timeStatus.dateOk()
241
1/2
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
25776 || !vnObs->timeOutputs->timeStatus.timeOk()
242
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
243
4/8
✓ Branch 0 taken 25776 times.
✗ Branch 1 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 25776 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 25776 times.
51552 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK))
244 {
245 return nullptr;
246 }
247
1/2
✓ Branch 7 taken 25776 times.
✗ Branch 8 not taken.
25776 imuObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->timeOutputs->gpsWeek), static_cast<double>(vnObs->timeOutputs->gpsTow) * 1e-9L));
248 }
249 else
250 {
251 // VN-100 vnObs->insTime is set from
252 // - 'timeSyncMaster->ppsTime + timeSyncIn' when working together with the VN-310E or
253 // - the computer time
254 imuObs->insTime = vnObs->insTime;
255 }
256
257 25776 bool accelFound = false;
258 25776 bool gyroFound = false;
259 25776 bool dThetaFound = false;
260 25776 bool dVelFound = false;
261
1/2
✓ Branch 2 taken 25776 times.
✗ Branch 3 not taken.
25776 if (vnObs->imuOutputs)
262 {
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25776 times.
25776 if (!_useCompensatedData)
264 {
265 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
266 {
267 imuObs->p_magneticField = vnObs->imuOutputs->uncompMag.cast<double>();
268 }
269 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
270 {
271 imuObs->p_acceleration = vnObs->imuOutputs->uncompAccel.cast<double>();
272 accelFound = true;
273 }
274 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
275 {
276 imuObs->p_angularRate = vnObs->imuOutputs->uncompGyro.cast<double>();
277 gyroFound = true;
278 }
279 }
280 else
281 {
282
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
283 {
284
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 25776 times.
✗ Branch 8 not taken.
25776 imuObs->p_magneticField = vnObs->imuOutputs->mag.cast<double>();
285 }
286
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
287 {
288
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 25776 times.
✗ Branch 8 not taken.
25776 imuObs->p_acceleration = vnObs->imuOutputs->accel.cast<double>();
289 25776 accelFound = true;
290 }
291
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
292 {
293
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 25776 times.
✗ Branch 8 not taken.
25776 imuObs->p_angularRate = vnObs->imuOutputs->angularRate.cast<double>();
294 25776 gyroFound = true;
295 }
296 }
297
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
298 {
299 25776 imuObs->temperature = vnObs->imuOutputs->temp;
300 }
301
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTATHETA)
302 {
303 25776 imuObs->dtime = vnObs->imuOutputs->deltaTime;
304
3/6
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 25776 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 25776 times.
✗ Branch 11 not taken.
25776 imuObs->dtheta = deg2rad(vnObs->imuOutputs->deltaTheta.cast<double>());
305 25776 dThetaFound = true;
306 }
307
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25776 times.
✗ Branch 6 not taken.
25776 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_DELTAVEL)
308 {
309
2/4
✓ Branch 3 taken 25776 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 25776 times.
✗ Branch 8 not taken.
25776 imuObs->dvel = vnObs->imuOutputs->deltaV.cast<double>();
310 25776 dVelFound = true;
311 }
312 }
313
314
4/8
✓ Branch 0 taken 25776 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25776 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25776 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 25776 times.
✗ Branch 7 not taken.
25776 if (accelFound && gyroFound && dThetaFound && dVelFound)
315 {
316 25776 return imuObs;
317 }
318
319 LOG_ERROR("{}: Conversion failed. Need {} acceleration and gyroscope measurements and deltaTheta and deltaVel in the input data.",
320 nameId(), _useCompensatedData ? "compensated" : "uncompensated");
321 return nullptr;
322 25776 }
323
324 std::shared_ptr<const NAV::ImuObs> NAV::VectorNavBinaryConverter::convert2ImuObs(const std::shared_ptr<const VectorNavBinaryOutput>& vnObs) const // NOLINT(readability-convert-member-functions-to-static)
325 {
326 auto imuObs = std::make_shared<ImuObs>(vnObs->imuPos);
327
328 if (vnObs->gnss1Outputs || vnObs->gnss2Outputs) // If there is no GNSS data selected in the vnSensor, Imu messages should still be sent out. The VN-100 will not provide any data otherwise.
329 {
330 if (!vnObs->timeOutputs
331 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
332 || !vnObs->timeOutputs->timeStatus.dateOk()
333 || !vnObs->timeOutputs->timeStatus.timeOk()
334 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
335 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK))
336 {
337 return nullptr;
338 }
339 imuObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->timeOutputs->gpsWeek), static_cast<double>(vnObs->timeOutputs->gpsTow) * 1e-9L));
340 }
341 else
342 {
343 // VN-100 vnObs->insTime is set from
344 // - 'timeSyncMaster->ppsTime + timeSyncIn' when working together with the VN-310E or
345 // - the computer time
346 imuObs->insTime = vnObs->insTime;
347 }
348
349 bool accelFound = false;
350 bool gyroFound = false;
351 if (vnObs->imuOutputs)
352 {
353 if (!_useCompensatedData)
354 {
355 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPMAG)
356 {
357 imuObs->p_magneticField = vnObs->imuOutputs->uncompMag.cast<double>();
358 }
359 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPACCEL)
360 {
361 imuObs->p_acceleration = vnObs->imuOutputs->uncompAccel.cast<double>();
362 accelFound = true;
363 }
364 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_UNCOMPGYRO)
365 {
366 imuObs->p_angularRate = vnObs->imuOutputs->uncompGyro.cast<double>();
367 gyroFound = true;
368 }
369 }
370 else
371 {
372 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_MAG)
373 {
374 imuObs->p_magneticField = vnObs->imuOutputs->mag.cast<double>();
375 }
376 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ACCEL)
377 {
378 imuObs->p_acceleration = vnObs->imuOutputs->accel.cast<double>();
379 accelFound = true;
380 }
381 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_ANGULARRATE)
382 {
383 imuObs->p_angularRate = vnObs->imuOutputs->angularRate.cast<double>();
384 gyroFound = true;
385 }
386 }
387 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
388 {
389 imuObs->temperature = vnObs->imuOutputs->temp;
390 }
391 }
392
393 if (accelFound && gyroFound)
394 {
395 return imuObs;
396 }
397
398 LOG_ERROR("{}: Conversion failed. Need {} acceleration and gyroscope measurements in the input data.", nameId(), _useCompensatedData ? "compensated" : "uncompensated");
399 return nullptr;
400 }
401
402 std::shared_ptr<const NAV::BaroPressObs> NAV::VectorNavBinaryConverter::convert2BaroPressObs(const std::shared_ptr<const VectorNavBinaryOutput>& vnObs) const // NOLINT(readability-convert-member-functions-to-static)
403 {
404 auto baroPressObs = std::make_shared<BaroPressObs>();
405
406 if (vnObs->gnss1Outputs || vnObs->gnss2Outputs) // If there is no GNSS data selected in the vnSensor, Baro messages should still be sent out. The VN-100 will not provide any data otherwise.
407 {
408 if (!vnObs->timeOutputs
409 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
410 || !vnObs->timeOutputs->timeStatus.dateOk()
411 || !vnObs->timeOutputs->timeStatus.timeOk()
412 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
413 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK))
414 {
415 return nullptr;
416 }
417 baroPressObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->timeOutputs->gpsWeek), static_cast<double>(vnObs->timeOutputs->gpsTow) * 1e-9L));
418 }
419 else
420 {
421 // VN-100 vnObs->insTime is set from
422 // - 'timeSyncMaster->ppsTime + timeSyncIn' when working together with the VN-310E or
423 // - the computer time
424 baroPressObs->insTime = vnObs->insTime;
425 }
426
427 bool baroFound = false;
428 if (vnObs->imuOutputs)
429 {
430 if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_PRES)
431 {
432 baroPressObs->baro_pressure = SCALE_FACTOR_KILO2HECTOPASCAL * static_cast<double>(vnObs->imuOutputs->pres);
433 baroFound = true;
434 }
435
436 // if (vnObs->imuOutputs->imuField & vn::protocol::uart::ImuGroup::IMUGROUP_TEMP)
437 // {
438 // baroPressObs->temperature = vnObs->imuOutputs->temp;
439 // }
440 }
441
442 if (baroFound)
443 {
444 return baroPressObs;
445 }
446
447 LOG_ERROR("{}: Conversion failed. No barometer pressure data found in the input data.", nameId());
448 return nullptr;
449 }
450
451 2608 std::shared_ptr<const NAV::PosVelAtt> NAV::VectorNavBinaryConverter::convert2PosVelAtt(const std::shared_ptr<const VectorNavBinaryOutput>& vnObs) // NOLINT(readability-convert-member-functions-to-static)
452 {
453 2608 std::optional<Eigen::Quaterniond> n_Quat_b;
454 2608 std::optional<Eigen::Vector3d> e_position;
455 2608 std::optional<Eigen::Vector3d> lla_position;
456 2608 std::optional<Eigen::Vector3d> n_velocity;
457
458
1/2
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
2608 if (vnObs->attitudeOutputs)
459 {
460
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2608 times.
2608 if (vnObs->attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_QUATERNION)
461 {
462 n_Quat_b = vnObs->attitudeOutputs->qtn.cast<double>();
463 }
464
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 else if (vnObs->attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_YAWPITCHROLL)
465 {
466
3/6
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2608 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2608 times.
✗ Branch 10 not taken.
2608 Eigen::Vector3d ypr = deg2rad(vnObs->attitudeOutputs->ypr.cast<double>());
467
4/8
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2608 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2608 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2608 times.
✗ Branch 11 not taken.
2608 n_Quat_b = trafo::n_Quat_b(ypr(2), ypr(1), ypr(0));
468 }
469 else if (vnObs->attitudeOutputs->attitudeField & vn::protocol::uart::AttitudeGroup::ATTITUDEGROUP_DCM)
470 {
471 n_Quat_b = vnObs->attitudeOutputs->dcm.cast<double>();
472 }
473 }
474
475
1/2
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
2608 auto posVelAttObs = std::make_shared<PosVelAtt>();
476
477 if ((_posVelSource == PosVelSource_Best || _posVelSource == PosVelSource_Ins)
478
1/2
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
2608 && vnObs->insOutputs
479
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2608 times.
7824 && (vnObs->insOutputs->insStatus.mode() == NAV::vendor::vectornav::InsStatus::Mode::Aligning
480
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2608 times.
2608 || vnObs->insOutputs->insStatus.mode() == NAV::vendor::vectornav::InsStatus::Mode::Tracking))
481 {
482 if (!vnObs->timeOutputs
483 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_TIMESTATUS)
484 || !vnObs->timeOutputs->timeStatus.dateOk()
485 || !vnObs->timeOutputs->timeStatus.timeOk()
486 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSTOW)
487 || !(vnObs->timeOutputs->timeField & vn::protocol::uart::TimeGroup::TIMEGROUP_GPSWEEK))
488 {
489 return nullptr;
490 }
491
492 posVelAttObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->timeOutputs->gpsWeek), static_cast<double>(vnObs->timeOutputs->gpsTow) * 1e-9L));
493
494 if (vnObs->insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSLLA)
495 {
496 lla_position = { deg2rad(vnObs->insOutputs->posLla(0)),
497 deg2rad(vnObs->insOutputs->posLla(1)),
498 vnObs->insOutputs->posLla(2) };
499 }
500 if (vnObs->insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_POSECEF)
501 {
502 e_position = vnObs->insOutputs->posEcef;
503 }
504
505 if (vnObs->insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELNED)
506 {
507 n_velocity = vnObs->insOutputs->velNed.cast<double>();
508 }
509 else if ((vnObs->insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELECEF)
510 && (e_position.has_value() || lla_position.has_value()))
511 {
512 Eigen::Vector3d lla = lla_position.has_value() ? lla_position.value() : trafo::ecef2lla_WGS84(e_position.value());
513 n_velocity = trafo::n_Quat_e(lla(0), lla(1)) * vnObs->insOutputs->velEcef.cast<double>();
514 }
515 else if ((vnObs->insOutputs->insField & vn::protocol::uart::InsGroup::INSGROUP_VELBODY)
516 && n_Quat_b.has_value())
517 {
518 n_velocity = n_Quat_b.value() * vnObs->insOutputs->velBody.cast<double>();
519 }
520 }
521
522 if ((_posVelSource == PosVelSource_Best || _posVelSource == PosVelSource_Gnss1)
523
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
✓ Branch 4 taken 2608 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2608 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2608 times.
✗ Branch 11 not taken.
2608 && vnObs->gnss1Outputs && vnObs->gnss1Outputs->fix >= 2)
524 {
525 2608 if (!vnObs->gnss1Outputs
526
1/2
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
2608 || !vnObs->gnss1Outputs->timeInfo.status.timeOk()
527
3/6
✓ Branch 0 taken 2608 times.
✗ Branch 1 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2608 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2608 times.
5216 || !vnObs->gnss1Outputs->timeInfo.status.dateOk())
528 {
529 return nullptr;
530 }
531
532
1/2
✓ Branch 7 taken 2608 times.
✗ Branch 8 not taken.
2608 posVelAttObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->gnss1Outputs->week), static_cast<double>(vnObs->gnss1Outputs->tow) * 1e-9L));
533
534
3/6
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2608 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2608 times.
✗ Branch 7 not taken.
2608 if (!e_position.has_value() && !lla_position.has_value())
535 {
536
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 if (vnObs->gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
537 {
538
1/2
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
2608 lla_position = { deg2rad(vnObs->gnss1Outputs->posLla(0)),
539
1/2
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
2608 deg2rad(vnObs->gnss1Outputs->posLla(1)),
540
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2608 times.
✗ Branch 7 not taken.
2608 vnObs->gnss1Outputs->posLla(2) };
541 }
542
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2608 times.
2608 if (vnObs->gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
543 {
544 e_position = vnObs->gnss1Outputs->posEcef;
545 }
546 }
547
548
1/2
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
2608 if (!n_velocity.has_value())
549 {
550
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 if (vnObs->gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
551 {
552
2/4
✓ Branch 3 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2608 times.
✗ Branch 7 not taken.
2608 n_velocity = vnObs->gnss1Outputs->velNed.cast<double>();
553 }
554 else if ((vnObs->gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
555 && (e_position.has_value() || lla_position.has_value()))
556 {
557 Eigen::Vector3d lla = lla_position.has_value() ? lla_position.value() : trafo::ecef2lla_WGS84(e_position.value());
558 n_velocity = trafo::n_Quat_e(lla(0), lla(1)) * vnObs->gnss1Outputs->velEcef.cast<double>();
559 }
560 }
561 }
562 if ((_posVelSource == PosVelSource_Best || _posVelSource == PosVelSource_Gnss2)
563
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2608 times.
2608 && vnObs->gnss2Outputs && vnObs->gnss2Outputs->fix >= 2)
564 {
565 if (!vnObs->gnss2Outputs
566 || !vnObs->gnss2Outputs->timeInfo.status.timeOk()
567 || !vnObs->gnss2Outputs->timeInfo.status.dateOk())
568 {
569 return nullptr;
570 }
571
572 posVelAttObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->gnss2Outputs->week), static_cast<double>(vnObs->gnss2Outputs->tow) * 1e-9L));
573
574 if (!e_position.has_value() && !lla_position.has_value())
575 {
576 if (vnObs->gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSLLA)
577 {
578 lla_position = { deg2rad(vnObs->gnss2Outputs->posLla(0)),
579 deg2rad(vnObs->gnss2Outputs->posLla(1)),
580 vnObs->gnss2Outputs->posLla(2) };
581 }
582 if (vnObs->gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_POSECEF)
583 {
584 e_position = vnObs->gnss2Outputs->posEcef;
585 }
586 }
587
588 if (!n_velocity.has_value())
589 {
590 if (vnObs->gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELNED)
591 {
592 n_velocity = vnObs->gnss2Outputs->velNed.cast<double>();
593 }
594 else if ((vnObs->gnss2Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_VELECEF)
595 && (e_position.has_value() || lla_position.has_value()))
596 {
597 Eigen::Vector3d lla = lla_position.has_value() ? lla_position.value() : trafo::ecef2lla_WGS84(e_position.value());
598 n_velocity = trafo::n_Quat_e(lla(0), lla(1)) * vnObs->gnss2Outputs->velEcef.cast<double>();
599 }
600 }
601 }
602
603
4/8
✓ Branch 1 taken 2608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2608 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2608 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2608 times.
✗ Branch 10 not taken.
2608 if ((e_position.has_value() || lla_position.has_value()) && n_velocity.has_value())
604 {
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2608 times.
2608 if (e_position.has_value())
606 {
607 posVelAttObs->setPosition_e(e_position.value());
608 }
609 else
610 {
611
2/4
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 posVelAttObs->setPosition_lla(lla_position.value());
612 }
613
2/4
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 posVelAttObs->setVelocity_n(n_velocity.value());
614
615
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2608 times.
2608 if (!n_Quat_b.has_value())
616 {
617 LOG_DEBUG("{}: Conversion succeeded but has no attitude info.", nameId());
618 }
619 else
620 {
621
2/4
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2608 times.
✗ Branch 6 not taken.
2608 posVelAttObs->setAttitude_n_Quat_b(n_Quat_b.value());
622 }
623
624
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2592 times.
2608 if (_posVelAtt__init == nullptr)
625 {
626 16 _posVelAtt__init = posVelAttObs;
627 }
628
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2608 times.
2608 if (_forceStatic)
630 {
631 posVelAttObs->setPosition_e(_posVelAtt__init->e_position());
632 posVelAttObs->setVelocity_n(Eigen::Vector3d::Zero());
633 posVelAttObs->setAttitude_n_Quat_b(_posVelAtt__init->n_Quat_b());
634 }
635
636 2608 return posVelAttObs;
637 }
638
639 LOG_ERROR("{}: Conversion failed. No position or velocity data found in the input data.", nameId());
640 return nullptr;
641 2608 }
642
643 std::shared_ptr<const NAV::GnssObs> NAV::VectorNavBinaryConverter::convert2GnssObs(const std::shared_ptr<const VectorNavBinaryOutput>& vnObs)
644 {
645 auto gnssObs = std::make_shared<GnssObs>();
646
647 if (!vnObs->gnss1Outputs
648 || !vnObs->gnss1Outputs->timeInfo.status.timeOk()
649 || !vnObs->gnss1Outputs->timeInfo.status.dateOk())
650 {
651 return nullptr;
652 }
653
654 gnssObs->insTime = InsTime(InsTime_GPSweekTow(0, static_cast<int32_t>(vnObs->gnss1Outputs->raw.week), vnObs->gnss1Outputs->raw.tow));
655
656 if (vnObs->gnss1Outputs)
657 {
658 if (vnObs->gnss1Outputs->gnssField & vn::protocol::uart::GpsGroup::GPSGROUP_RAWMEAS)
659 {
660 for (const auto& satRaw : vnObs->gnss1Outputs->raw.satellites)
661 {
662 bool skipMeasurement = false;
663 SatelliteSystem satSys = SatSys_None;
664 switch (satRaw.sys)
665 {
666 case vendor::vectornav::SatSys::GPS:
667 satSys = GPS;
668 break;
669 case vendor::vectornav::SatSys::SBAS:
670 satSys = SBAS;
671 break;
672 case vendor::vectornav::SatSys::Galileo:
673 satSys = GAL;
674 break;
675 case vendor::vectornav::SatSys::BeiDou:
676 satSys = BDS;
677 break;
678 case vendor::vectornav::SatSys::IMES:
679 LOG_TRACE("VectorNav SatRawElement satellite system '{}' is not supported yet. Skipping measurement.", satRaw.sys);
680 skipMeasurement = true;
681 break;
682 case vendor::vectornav::SatSys::QZSS:
683 satSys = QZSS;
684 break;
685 case vendor::vectornav::SatSys::GLONASS:
686 satSys = GLO;
687 break;
688 default: // IRNSS not in vectorNav
689 LOG_TRACE("VectorNav SatRawElement satellite system '{}' is not supported yet. Skipping measurement.", satRaw.sys);
690 skipMeasurement = true;
691 break;
692 }
693
694 Frequency frequency = Freq_None;
695 Code code;
696 switch (SatelliteSystem_(satSys))
697 {
698 case GPS:
699 switch (satRaw.freq)
700 {
701 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
702 frequency = G01;
703 switch (satRaw.chan)
704 {
705 case vendor::vectornav::RawMeas::SatRawElement::Chan::P_Code:
706 code = Code::G1P;
707 break;
708 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
709 code = Code::G1C;
710 break;
711 case vendor::vectornav::RawMeas::SatRawElement::Chan::Y_Code:
712 code = Code::G1Y;
713 break;
714 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Code:
715 code = Code::G1M;
716 break;
717 case vendor::vectornav::RawMeas::SatRawElement::Chan::Codeless:
718 code = Code::G1N;
719 break;
720 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Chan:
721 code = Code::G1S;
722 break;
723 case vendor::vectornav::RawMeas::SatRawElement::Chan::L_Chan:
724 code = Code::G1L;
725 break;
726 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
727 code = Code::G1X;
728 break;
729 case vendor::vectornav::RawMeas::SatRawElement::Chan::Z_Tracking:
730 code = Code::G1W;
731 break;
732 default:
733 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
734 skipMeasurement = true;
735 break;
736 }
737 break;
738 case vendor::vectornav::RawMeas::SatRawElement::Freq::L2:
739 frequency = G02;
740 switch (satRaw.chan)
741 {
742 case vendor::vectornav::RawMeas::SatRawElement::Chan::P_Code:
743 code = Code::G2P;
744 break;
745 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
746 code = Code::G2C;
747 break;
748 case vendor::vectornav::RawMeas::SatRawElement::Chan::SemiCodeless:
749 code = Code::G2D;
750 break;
751 case vendor::vectornav::RawMeas::SatRawElement::Chan::Y_Code:
752 code = Code::G2Y;
753 break;
754 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Code:
755 code = Code::G2M;
756 break;
757 case vendor::vectornav::RawMeas::SatRawElement::Chan::Codeless:
758 code = Code::G2N;
759 break;
760 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Chan:
761 code = Code::G2S;
762 break;
763 case vendor::vectornav::RawMeas::SatRawElement::Chan::L_Chan:
764 code = Code::G2L;
765 break;
766 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
767 code = Code::G2X;
768 break;
769 case vendor::vectornav::RawMeas::SatRawElement::Chan::Z_Tracking:
770 code = Code::G2W;
771 break;
772 default:
773 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
774 skipMeasurement = true;
775 break;
776 }
777 break;
778 case vendor::vectornav::RawMeas::SatRawElement::Freq::L5:
779 frequency = G05;
780 switch (satRaw.chan)
781 {
782 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
783 code = Code::G5I;
784 break;
785 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
786 code = Code::G5Q;
787 break;
788 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
789 code = Code::G5X;
790 break;
791 default:
792 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
793 skipMeasurement = true;
794 break;
795 }
796 break;
797 default:
798 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
799 skipMeasurement = true;
800 break;
801 }
802 break;
803 case SBAS:
804 switch (satRaw.freq)
805 {
806 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
807 frequency = S01;
808 switch (satRaw.chan)
809 {
810 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
811 code = Code::S1C;
812 break;
813 default:
814 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
815 skipMeasurement = true;
816 break;
817 }
818 break;
819 case vendor::vectornav::RawMeas::SatRawElement::Freq::L5:
820 frequency = S05;
821 switch (satRaw.chan)
822 {
823 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
824 code = Code::S5I;
825 break;
826 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
827 code = Code::S5Q;
828 break;
829 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
830 code = Code::S5X;
831 break;
832 default:
833 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
834 skipMeasurement = true;
835 break;
836 }
837 break;
838 default:
839 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
840 skipMeasurement = true;
841 break;
842 }
843 break;
844 case GAL:
845 switch (satRaw.freq)
846 {
847 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
848 frequency = E01;
849 switch (satRaw.chan)
850 {
851 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
852 code = Code::E1C;
853 break;
854 case vendor::vectornav::RawMeas::SatRawElement::Chan::A_Chan:
855 code = Code::E1A;
856 break;
857 case vendor::vectornav::RawMeas::SatRawElement::Chan::B_Chan:
858 code = Code::E1B;
859 break;
860 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
861 code = Code::E1X;
862 break;
863 case vendor::vectornav::RawMeas::SatRawElement::Chan::ABC:
864 code = Code::E1Z;
865 break;
866 default:
867 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
868 skipMeasurement = true;
869 break;
870 }
871 break;
872 case vendor::vectornav::RawMeas::SatRawElement::Freq::L5:
873 frequency = E08;
874 switch (satRaw.chan)
875 {
876 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
877 code = Code::E8I;
878 break;
879 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
880 code = Code::E8Q;
881 break;
882 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
883 code = Code::E8X;
884 break;
885 default:
886 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
887 skipMeasurement = true;
888 break;
889 }
890 break;
891 case vendor::vectornav::RawMeas::SatRawElement::Freq::E6:
892 frequency = E06;
893 switch (satRaw.chan)
894 {
895 case vendor::vectornav::RawMeas::SatRawElement::Chan::B_Chan:
896 code = Code::E6B;
897 break;
898 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
899 code = Code::E6C;
900 break;
901 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
902 code = Code::E6X;
903 break;
904 default:
905 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
906 skipMeasurement = true;
907 break;
908 }
909 break;
910 case vendor::vectornav::RawMeas::SatRawElement::Freq::E5a:
911 frequency = E05;
912 switch (satRaw.chan)
913 {
914 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
915 code = Code::E5I;
916 break;
917 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
918 code = Code::E5Q;
919 break;
920 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
921 code = Code::E5X;
922 break;
923 default:
924 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
925 skipMeasurement = true;
926 break;
927 }
928 break;
929 case vendor::vectornav::RawMeas::SatRawElement::Freq::E5b:
930 frequency = E07;
931 switch (satRaw.chan)
932 {
933 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
934 code = Code::E7I;
935 break;
936 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
937 code = Code::E7Q;
938 break;
939 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
940 code = Code::E7X;
941 break;
942 default:
943 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
944 skipMeasurement = true;
945 break;
946 }
947 break;
948 default:
949 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
950 skipMeasurement = true;
951 break;
952 }
953 break;
954 case BDS:
955 switch (satRaw.freq)
956 {
957 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
958 frequency = B01;
959 switch (satRaw.chan)
960 {
961 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
962 code = Code::B2I;
963 break;
964 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
965 code = Code::B2Q;
966 break;
967 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
968 code = Code::B2X;
969 break;
970 default:
971 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
972 skipMeasurement = true;
973 break;
974 }
975 break;
976 case vendor::vectornav::RawMeas::SatRawElement::Freq::E6:
977 frequency = B06;
978 switch (satRaw.chan)
979 {
980 case vendor::vectornav::RawMeas::SatRawElement::Chan::A_Chan:
981 code = Code::B6A;
982 break;
983 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
984 code = Code::B6I;
985 break;
986 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
987 code = Code::B6Q;
988 break;
989 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
990 code = Code::B6X;
991 break;
992 default:
993 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
994 skipMeasurement = true;
995 break;
996 }
997 break;
998 case vendor::vectornav::RawMeas::SatRawElement::Freq::E5b:
999 frequency = B08;
1000 switch (satRaw.chan)
1001 {
1002 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
1003 code = Code::B7I;
1004 break;
1005 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
1006 code = Code::B7Q;
1007 break;
1008 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
1009 code = Code::B7X;
1010 break;
1011 default:
1012 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1013 skipMeasurement = true;
1014 break;
1015 }
1016 break;
1017 default:
1018 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
1019 skipMeasurement = true;
1020 break;
1021 }
1022 break;
1023 case QZSS:
1024 switch (satRaw.freq)
1025 {
1026 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
1027 frequency = J01;
1028 switch (satRaw.chan)
1029 {
1030 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
1031 code = Code::J1C;
1032 break;
1033 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Chan:
1034 code = Code::J1S;
1035 break;
1036 case vendor::vectornav::RawMeas::SatRawElement::Chan::L_Chan:
1037 code = Code::J1L;
1038 break;
1039 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
1040 code = Code::J1X;
1041 break;
1042 default:
1043 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1044 skipMeasurement = true;
1045 break;
1046 }
1047 break;
1048 case vendor::vectornav::RawMeas::SatRawElement::Freq::L2:
1049 frequency = J02;
1050 switch (satRaw.chan)
1051 {
1052 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Chan:
1053 code = Code::J2S;
1054 break;
1055 case vendor::vectornav::RawMeas::SatRawElement::Chan::L_Chan:
1056 code = Code::J2L;
1057 break;
1058 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
1059 code = Code::J2X;
1060 break;
1061 default:
1062 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1063 skipMeasurement = true;
1064 break;
1065 }
1066 break;
1067 case vendor::vectornav::RawMeas::SatRawElement::Freq::L5:
1068 frequency = J05;
1069 switch (satRaw.chan)
1070 {
1071 case vendor::vectornav::RawMeas::SatRawElement::Chan::I_Chan:
1072 code = Code::J5I;
1073 break;
1074 case vendor::vectornav::RawMeas::SatRawElement::Chan::Q_Chan:
1075 code = Code::J5Q;
1076 break;
1077 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
1078 code = Code::J5X;
1079 break;
1080 default:
1081 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1082 skipMeasurement = true;
1083 break;
1084 }
1085 break;
1086 case vendor::vectornav::RawMeas::SatRawElement::Freq::E6:
1087 frequency = J06;
1088 switch (satRaw.chan)
1089 {
1090 case vendor::vectornav::RawMeas::SatRawElement::Chan::M_Chan:
1091 code = Code::J6S;
1092 break;
1093 case vendor::vectornav::RawMeas::SatRawElement::Chan::L_Chan:
1094 code = Code::J6L;
1095 break;
1096 case vendor::vectornav::RawMeas::SatRawElement::Chan::BC_Chan:
1097 code = Code::J6X;
1098 break;
1099 default:
1100 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1101 skipMeasurement = true;
1102 break;
1103 }
1104 break;
1105 default:
1106 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
1107 skipMeasurement = true;
1108 break;
1109 }
1110 break;
1111 case GLO:
1112 switch (satRaw.freq)
1113 {
1114 case vendor::vectornav::RawMeas::SatRawElement::Freq::L1:
1115 frequency = R01;
1116 switch (satRaw.chan)
1117 {
1118 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
1119 code = Code::R1C;
1120 break;
1121 case vendor::vectornav::RawMeas::SatRawElement::Chan::P_Code:
1122 code = Code::R1P;
1123 break;
1124 default:
1125 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1126 skipMeasurement = true;
1127 break;
1128 }
1129 break;
1130 case vendor::vectornav::RawMeas::SatRawElement::Freq::L2:
1131 frequency = R02;
1132 switch (satRaw.chan)
1133 {
1134 case vendor::vectornav::RawMeas::SatRawElement::Chan::CA_Code:
1135 code = Code::R2C;
1136 break;
1137 case vendor::vectornav::RawMeas::SatRawElement::Chan::P_Code:
1138 code = Code::R2P;
1139 break;
1140 default:
1141 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' channel '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq, satRaw.chan);
1142 skipMeasurement = true;
1143 break;
1144 }
1145 break;
1146 default:
1147 LOG_TRACE("VectorNav SatRawElement satellite system '{}' frequency '{}' is not supported yet. Skipping measurement.", satRaw.sys, satRaw.freq);
1148 skipMeasurement = true;
1149 break;
1150 }
1151 break;
1152 case IRNSS: // IRNSS not in vectorNav
1153 case SatSys_None:
1154 skipMeasurement = true;
1155 break;
1156 }
1157
1158 if (skipMeasurement)
1159 {
1160 continue;
1161 }
1162
1163 (*gnssObs)(SatSigId(code, satRaw.svId)).pseudorange = { .value = satRaw.pr };
1164 (*gnssObs)(SatSigId(code, satRaw.svId)).carrierPhase = { .value = satRaw.cp };
1165 (*gnssObs)(SatSigId(code, satRaw.svId)).doppler = satRaw.dp;
1166 (*gnssObs)(SatSigId(code, satRaw.svId)).CN0 = satRaw.cno;
1167
1168 // LLI has not been implemented yet, but can be calculated from vendor::vectornav::RawMeas::SatRawElement::Flags
1169 // (*gnssObs)[{ frequency, satRaw.svId }].LLI = ...
1170 }
1171 }
1172 }
1173
1174 return gnssObs;
1175 }
1176
1177 const char* NAV::to_string(NAV::VectorNavBinaryConverter::OutputType value)
1178 {
1179 switch (value)
1180 {
1181 case NAV::VectorNavBinaryConverter::OutputType::ImuObs:
1182 return "ImuObs";
1183 case NAV::VectorNavBinaryConverter::OutputType::ImuObsWDelta:
1184 return "ImuObsWDelta";
1185 case NAV::VectorNavBinaryConverter::OutputType::BaroPressObs:
1186 return "BaroPressObs";
1187 case NAV::VectorNavBinaryConverter::OutputType::PosVelAtt:
1188 return "PosVelAtt";
1189 case NAV::VectorNavBinaryConverter::OutputType::GnssObs:
1190 return "GnssObs";
1191 case NAV::VectorNavBinaryConverter::OutputType::COUNT:
1192 return "";
1193 }
1194 return "";
1195 }
1196