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