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 "Demo.hpp" | ||
10 | #include <cstddef> | ||
11 | #include <imgui.h> | ||
12 | #include <optional> | ||
13 | |||
14 | #include "util/Logger.hpp" | ||
15 | |||
16 | #include "internal/NodeManager.hpp" | ||
17 | namespace nm = NAV::NodeManager; | ||
18 | #include "internal/FlowManager.hpp" | ||
19 | |||
20 | #include "internal/gui/widgets/HelpMarker.hpp" | ||
21 | #include "internal/gui/widgets/Matrix.hpp" | ||
22 | #include "internal/gui/widgets/imgui_ex.hpp" | ||
23 | |||
24 | #include "NodeData/IMU/ImuObs.hpp" | ||
25 | |||
26 | #include <chrono> | ||
27 | #include <thread> | ||
28 | #include <random> | ||
29 | |||
30 | namespace NAV | ||
31 | { | ||
32 | namespace | ||
33 | { | ||
34 | ✗ | InsTime getCurrentInsTime() | |
35 | { | ||
36 | ✗ | std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); | |
37 | ✗ | auto* t = std::localtime(&now); // NOLINT(concurrency-mt-unsafe) | |
38 | |||
39 | ✗ | return { static_cast<uint16_t>(t->tm_year + 1900), | |
40 | ✗ | static_cast<uint16_t>(t->tm_mon), | |
41 | ✗ | static_cast<uint16_t>(t->tm_mday), | |
42 | ✗ | static_cast<uint16_t>(t->tm_hour), | |
43 | ✗ | static_cast<uint16_t>(t->tm_min), | |
44 | ✗ | static_cast<long double>(t->tm_sec) }; | |
45 | } | ||
46 | } // namespace | ||
47 | |||
48 | /// @brief Write info to a json object | ||
49 | /// @param[out] j Json output | ||
50 | /// @param[in] data Object to read info from | ||
51 | ✗ | static void to_json(json& j, const Demo::DemoData& data) // NOLINT(misc-use-anonymous-namespace) | |
52 | { | ||
53 | ✗ | j = json{ | |
54 | ✗ | { "boolean", data.boolean }, | |
55 | ✗ | { "integer", data.integer }, | |
56 | ✗ | }; | |
57 | ✗ | } | |
58 | /// @brief Read info from a json object | ||
59 | /// @param[in] j Json variable to read info from | ||
60 | /// @param[out] data Output object | ||
61 | 6 | static void from_json(const json& j, Demo::DemoData& data) // NOLINT(misc-use-anonymous-namespace) | |
62 | { | ||
63 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("boolean")) |
64 | { | ||
65 | 6 | j.at("boolean").get_to(data.boolean); | |
66 | } | ||
67 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("integer")) |
68 | { | ||
69 | 6 | j.at("integer").get_to(data.integer); | |
70 | } | ||
71 | 6 | } | |
72 | |||
73 | } // namespace NAV | ||
74 | |||
75 | 118 | NAV::Demo::Demo() | |
76 |
5/10✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 118 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 118 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 118 times.
✗ Branch 17 not taken.
|
354 | : Node(typeStatic()) |
77 | { | ||
78 | LOG_TRACE("{}: called", name); | ||
79 | |||
80 | 118 | _onlyRealTime = false; // Set this to true if you have a sensor, network stream, ... | |
81 | 118 | _hasConfig = true; | |
82 | 118 | _lockConfigDuringRun = false; | |
83 | 118 | _guiConfigDefaultWindowSize = { 630, 410 }; | |
84 | |||
85 | // Pins are usually created by calling the following functions in the constructor | ||
86 |
4/8✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 118 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 118 times.
✓ Branch 9 taken 118 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
354 | nm::CreateInputPin(this, "Flow", Pin::Type::Flow, { NAV::NodeData::type() }, &Demo::receiveData); |
87 |
4/8✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 118 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 118 times.
✓ Branch 10 taken 118 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
472 | nm::CreateOutputPin(this, "Sensor\nData", Pin::Type::Flow, { NAV::ImuObs::type() }); |
88 | |||
89 | // To create or delete pins depending on GUI options we use a function as it needs to be called from multiple places | ||
90 |
1/2✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
|
118 | updatePins(); |
91 | 354 | } | |
92 | |||
93 | 248 | NAV::Demo::~Demo() | |
94 | { | ||
95 | LOG_TRACE("{}: called", nameId()); | ||
96 | 248 | } | |
97 | |||
98 | 355 | std::string NAV::Demo::typeStatic() | |
99 | { | ||
100 |
1/2✓ Branch 1 taken 355 times.
✗ Branch 2 not taken.
|
710 | return "Demo"; |
101 | } | ||
102 | |||
103 | 1 | std::string NAV::Demo::type() const | |
104 | { | ||
105 | 1 | return typeStatic(); | |
106 | } | ||
107 | |||
108 | 112 | std::string NAV::Demo::category() | |
109 | { | ||
110 |
1/2✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
|
224 | return "Utility"; |
111 | } | ||
112 | |||
113 | ✗ | void NAV::Demo::guiConfig() | |
114 | { | ||
115 | ✗ | if (ImGui::BeginTable("##DemoValues", 3, ImGuiTableFlags_Borders)) | |
116 | { | ||
117 | ✗ | ImGui::TableSetupColumn("Enable"); | |
118 | ✗ | ImGui::TableSetupColumn("Input"); | |
119 | ✗ | ImGui::TableSetupColumn("Output"); | |
120 | ✗ | ImGui::TableHeadersRow(); | |
121 | |||
122 | /* ----------------------------------------------- Delegate ----------------------------------------------- */ | ||
123 | ✗ | ImGui::TableNextRow(); | |
124 | ✗ | ImGui::TableSetColumnIndex(0); | |
125 | ✗ | if (ImGui::Checkbox(fmt::format("Delegate##enable {}", size_t(id)).c_str(), &_enableDelegate)) | |
126 | { | ||
127 | ✗ | updatePins(); | |
128 | ✗ | flow::ApplyChanges(); | |
129 | } | ||
130 | ✗ | if (_enableDelegate) | |
131 | { | ||
132 | ✗ | ImGui::TableSetColumnIndex(1); | |
133 | { | ||
134 | // The returned type automatically blocks editing on the other side of the link. Like a scoped_lock for mutexes | ||
135 | ✗ | auto connectedNode = getInputValue<Demo>(getPinIdx(DemoPins::Delegate).value()); | |
136 | ✗ | ImGui::Text("Delegate: %s", connectedNode ? connectedNode->v->nameId().c_str() : "N/A"); | |
137 | ✗ | } | |
138 | } | ||
139 | /* ------------------------------------------------ Flow ------------------------------------------------ */ | ||
140 | ✗ | ImGui::TableNextRow(); | |
141 | ✗ | ImGui::TableSetColumnIndex(0); | |
142 | ✗ | if (ImGui::Checkbox(fmt::format("Flow##enable {}", size_t(id)).c_str(), &_enableFlow)) | |
143 | { | ||
144 | ✗ | updatePins(); | |
145 | ✗ | flow::ApplyChanges(); | |
146 | } | ||
147 | ✗ | if (_enableFlow) | |
148 | { | ||
149 | ✗ | ImGui::TableSetColumnIndex(1); | |
150 | ✗ | ImGui::Text("Flow Data Count: %d", _receivedDataCnt); | |
151 | ✗ | ImGui::TableSetColumnIndex(2); | |
152 | ✗ | if (ImGui::Checkbox(fmt::format("Simulate File Reader##{}", size_t(id)).c_str(), &_fileReaderInsteadSensor)) | |
153 | { | ||
154 | ✗ | if (_fileReaderInsteadSensor) | |
155 | { | ||
156 | ✗ | if (_timer.is_running()) { _timer.stop(); } | |
157 | } | ||
158 | else | ||
159 | { | ||
160 | ✗ | if (isInitialized() && !_timer.is_running()) | |
161 | { | ||
162 | ✗ | int outputInterval = static_cast<int>(1.0 / static_cast<double>(_outputFrequency) * 1000.0); | |
163 | ✗ | _timer.start(outputInterval, readSensorDataThread, this); | |
164 | } | ||
165 | } | ||
166 | ✗ | updateOutputFlowPin(); | |
167 | ✗ | flow::ApplyChanges(); | |
168 | } | ||
169 | ✗ | if (_fileReaderInsteadSensor) | |
170 | { | ||
171 | ✗ | ImGui::SetNextItemWidth(100.0F); | |
172 | ✗ | if (ImGui::InputInt(fmt::format("FileReader Obs Count##{}", size_t(id)).c_str(), &_nPollData)) | |
173 | { | ||
174 | ✗ | flow::ApplyChanges(); | |
175 | } | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | ✗ | if (ImGui::SliderInt(fmt::format("Frequency##{}", size_t(id)).c_str(), &_outputFrequency, 1, 10)) | |
180 | { | ||
181 | ✗ | int outputInterval = static_cast<int>(1.0 / static_cast<double>(_outputFrequency) * 1000.0); | |
182 | ✗ | _timer.setInterval(outputInterval); | |
183 | ✗ | flow::ApplyChanges(); | |
184 | } | ||
185 | } | ||
186 | } | ||
187 | /* ------------------------------------------------- Bool ------------------------------------------------- */ | ||
188 | ✗ | ImGui::TableNextRow(); | |
189 | ✗ | ImGui::TableSetColumnIndex(0); | |
190 | ✗ | if (ImGui::Checkbox(fmt::format("Bool##enable {}", size_t(id)).c_str(), &_enableBool)) | |
191 | { | ||
192 | ✗ | updatePins(); | |
193 | ✗ | flow::ApplyChanges(); | |
194 | } | ||
195 | ✗ | if (_enableBool) | |
196 | { | ||
197 | ✗ | ImGui::TableSetColumnIndex(1); | |
198 | { | ||
199 | ✗ | auto connectedBool = getInputValue<bool>(getPinIdx(DemoPins::Bool).value()); | |
200 | ✗ | ImGui::Text("Bool: %s", connectedBool ? (connectedBool->v ? "true" : "false") : "N/A"); | |
201 | ✗ | } | |
202 | |||
203 | ✗ | ImGui::TableSetColumnIndex(2); | |
204 | { | ||
205 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Bool).value()); | |
206 | ✗ | if (ImGui::Checkbox(fmt::format("Bool##{}", size_t(id)).c_str(), &_valueBool)) | |
207 | { | ||
208 | ✗ | flow::ApplyChanges(); | |
209 | } | ||
210 | ✗ | } | |
211 | } | ||
212 | /* -------------------------------------------------- Int ------------------------------------------------- */ | ||
213 | ✗ | ImGui::TableNextRow(); | |
214 | ✗ | ImGui::TableSetColumnIndex(0); | |
215 | ✗ | if (ImGui::Checkbox(fmt::format("Int##enable {}", size_t(id)).c_str(), &_enableInt)) | |
216 | { | ||
217 | ✗ | updatePins(); | |
218 | ✗ | flow::ApplyChanges(); | |
219 | } | ||
220 | ✗ | if (_enableInt) | |
221 | { | ||
222 | ✗ | ImGui::TableSetColumnIndex(1); | |
223 | ✗ | if (auto connectedInt = getInputValue<int>(getPinIdx(DemoPins::Int).value())) | |
224 | { | ||
225 | ✗ | ImGui::Text("Int: %d", *connectedInt->v); | |
226 | } | ||
227 | else | ||
228 | { | ||
229 | ✗ | ImGui::TextUnformatted("Int: N/A"); | |
230 | ✗ | } | |
231 | |||
232 | ✗ | ImGui::TableSetColumnIndex(2); | |
233 | { | ||
234 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Int).value()); | |
235 | ✗ | if (ImGui::InputInt(fmt::format("Int##{}", size_t(id)).c_str(), &_valueInt)) // Returns true if a change was made | |
236 | { | ||
237 | // Limit the values to [-2,5] | ||
238 | ✗ | _valueInt = std::max(_valueInt, -2); | |
239 | ✗ | _valueInt = std::min(_valueInt, 5); | |
240 | |||
241 | ✗ | flow::ApplyChanges(); | |
242 | } | ||
243 | ✗ | } | |
244 | } | ||
245 | /* ------------------------------------------------- Float ------------------------------------------------ */ | ||
246 | ✗ | ImGui::TableNextRow(); | |
247 | ✗ | ImGui::TableSetColumnIndex(0); | |
248 | ✗ | if (ImGui::Checkbox(fmt::format("Float##enable {}", size_t(id)).c_str(), &_enableFloat)) | |
249 | { | ||
250 | ✗ | updatePins(); | |
251 | ✗ | flow::ApplyChanges(); | |
252 | } | ||
253 | ✗ | if (_enableFloat) | |
254 | { | ||
255 | ✗ | ImGui::TableSetColumnIndex(1); | |
256 | ✗ | if (auto connectedFloat = getInputValue<float>(getPinIdx(DemoPins::Float).value())) | |
257 | { | ||
258 | ✗ | ImGui::Text("Float: %.3f", *connectedFloat->v); | |
259 | } | ||
260 | else | ||
261 | { | ||
262 | ✗ | ImGui::TextUnformatted("Float: N/A"); | |
263 | ✗ | } | |
264 | |||
265 | ✗ | ImGui::TableSetColumnIndex(2); | |
266 | { | ||
267 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Float).value()); | |
268 | ✗ | if (ImGui::DragFloat(fmt::format("Float##{}", size_t(id)).c_str(), &_valueFloat)) | |
269 | { | ||
270 | ✗ | flow::ApplyChanges(); | |
271 | } | ||
272 | ✗ | } | |
273 | } | ||
274 | /* ------------------------------------------------ Double ------------------------------------------------ */ | ||
275 | ✗ | ImGui::TableNextRow(); | |
276 | ✗ | ImGui::TableSetColumnIndex(0); | |
277 | ✗ | if (ImGui::Checkbox(fmt::format("Double##enable {}", size_t(id)).c_str(), &_enableDouble)) | |
278 | { | ||
279 | ✗ | updatePins(); | |
280 | ✗ | flow::ApplyChanges(); | |
281 | } | ||
282 | ✗ | if (_enableDouble) | |
283 | { | ||
284 | ✗ | ImGui::TableSetColumnIndex(1); | |
285 | ✗ | if (auto connectedDouble = getInputValue<double>(getPinIdx(DemoPins::Double).value())) | |
286 | { | ||
287 | ✗ | ImGui::Text("Double : %.3f", *connectedDouble->v); | |
288 | } | ||
289 | else | ||
290 | { | ||
291 | ✗ | ImGui::TextUnformatted("Double: N/A"); | |
292 | ✗ | } | |
293 | |||
294 | ✗ | ImGui::TableSetColumnIndex(2); | |
295 | { | ||
296 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Double).value()); | |
297 | ✗ | if (ImGui::DragDouble(fmt::format("Double##{}", size_t(id)).c_str(), &_valueDouble)) | |
298 | { | ||
299 | ✗ | flow::ApplyChanges(); | |
300 | } | ||
301 | ✗ | } | |
302 | } | ||
303 | /* ------------------------------------------------ String ------------------------------------------------ */ | ||
304 | ✗ | ImGui::TableNextRow(); | |
305 | ✗ | ImGui::TableSetColumnIndex(0); | |
306 | ✗ | if (ImGui::Checkbox(fmt::format("String##enable {}", size_t(id)).c_str(), &_enableString)) | |
307 | { | ||
308 | ✗ | updatePins(); | |
309 | ✗ | flow::ApplyChanges(); | |
310 | } | ||
311 | ✗ | if (_enableString) | |
312 | { | ||
313 | ✗ | ImGui::TableSetColumnIndex(1); | |
314 | ✗ | if (auto connectedString = getInputValue<std::string>(getPinIdx(DemoPins::String).value())) | |
315 | { | ||
316 | ✗ | ImGui::Text("String: %s", connectedString->v->c_str()); | |
317 | } | ||
318 | else | ||
319 | { | ||
320 | ✗ | ImGui::TextUnformatted("String: N/A"); | |
321 | ✗ | } | |
322 | ✗ | ImGui::Text("The String was updated %lu time%s", _stringUpdateCounter, _stringUpdateCounter > 1 || _stringUpdateCounter == 0 ? "s" : ""); | |
323 | |||
324 | ✗ | ImGui::TableSetColumnIndex(2); | |
325 | { | ||
326 | // Before accessing and changing the value. A lock has to be requested to ensure it is not changed before all linked nodes received the value. | ||
327 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::String).value()); | |
328 | ✗ | if (ImGui::InputText(fmt::format("String##{}", size_t(id)).c_str(), &_valueString)) | |
329 | { | ||
330 | ✗ | flow::ApplyChanges(); | |
331 | ✗ | const auto& outputPin = outputPins[getPinIdx(DemoPins::String).value()]; | |
332 | ✗ | if (outputPin.isPinLinked()) | |
333 | { | ||
334 | ✗ | if (!isInitialized()) { LOG_WARN("{}: Notifying connected nodes requires this node to be initialized.", nameId()); } | |
335 | ✗ | else if (!callbacksEnabled) { LOG_WARN("{}: Notifying connected nodes requires enabled callbacks on this node. Do this by running the flow.", nameId()); } | |
336 | ✗ | else if (std::ranges::none_of(outputPin.links, [](const OutputPin::OutgoingLink& link) { return link.connectedNode->isInitialized(); })) | |
337 | { | ||
338 | ✗ | LOG_WARN("{}: Notifying connected nodes requires at least one connected node to be initialized.", nameId()); | |
339 | } | ||
340 | } | ||
341 | ✗ | notifyOutputValueChanged(getPinIdx(DemoPins::String).value(), getCurrentInsTime(), std::move(guard)); | |
342 | } | ||
343 | ✗ | } | |
344 | ✗ | ImGui::SameLine(); | |
345 | ✗ | gui::widgets::HelpMarker("The string notifies about changes.\nInitialize both nodes for this to work."); | |
346 | } | ||
347 | /* ------------------------------------------------ Object ------------------------------------------------ */ | ||
348 | ✗ | ImGui::TableNextRow(); | |
349 | ✗ | ImGui::TableSetColumnIndex(0); | |
350 | ✗ | if (ImGui::Checkbox(fmt::format("Object##enable {}", size_t(id)).c_str(), &_enableObject)) | |
351 | { | ||
352 | ✗ | updatePins(); | |
353 | ✗ | flow::ApplyChanges(); | |
354 | } | ||
355 | ✗ | if (_enableObject) | |
356 | { | ||
357 | ✗ | ImGui::TableSetColumnIndex(1); | |
358 | ✗ | if (auto connectedObject = getInputValue<DemoData>(getPinIdx(DemoPins::Object).value())) | |
359 | { | ||
360 | ✗ | ImGui::Text("Object: [%d, %d, %d], %s", connectedObject->v->integer.at(0), connectedObject->v->integer.at(1), connectedObject->v->integer.at(2), | |
361 | ✗ | connectedObject->v->boolean ? "true" : "false"); | |
362 | } | ||
363 | else | ||
364 | { | ||
365 | ✗ | ImGui::TextUnformatted("Object: N/A"); | |
366 | ✗ | } | |
367 | |||
368 | ✗ | ImGui::TableSetColumnIndex(2); | |
369 | { | ||
370 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Object).value()); | |
371 | ✗ | if (ImGui::InputInt3(fmt::format("##object.integer {}", size_t(id)).c_str(), _valueObject.integer.data())) | |
372 | { | ||
373 | ✗ | flow::ApplyChanges(); | |
374 | } | ||
375 | ✗ | ImGui::SameLine(); | |
376 | ✗ | if (ImGui::Checkbox(fmt::format("Object##{}", size_t(id)).c_str(), &_valueObject.boolean)) | |
377 | { | ||
378 | ✗ | flow::ApplyChanges(); | |
379 | } | ||
380 | ✗ | } | |
381 | } | ||
382 | /* ------------------------------------------------ Matrix ------------------------------------------------ */ | ||
383 | ✗ | ImGui::TableNextRow(); | |
384 | ✗ | ImGui::TableSetColumnIndex(0); | |
385 | ✗ | if (ImGui::Checkbox(fmt::format("Matrix##enable {}", size_t(id)).c_str(), &_enableMatrix)) | |
386 | { | ||
387 | ✗ | updatePins(); | |
388 | ✗ | flow::ApplyChanges(); | |
389 | } | ||
390 | ✗ | if (_enableMatrix) | |
391 | { | ||
392 | ✗ | ImGui::TableSetColumnIndex(1); | |
393 | ✗ | if (auto connectedMatrix = getInputValue<Eigen::MatrixXd>(getPinIdx(DemoPins::Matrix).value())) | |
394 | { | ||
395 | ✗ | gui::widgets::MatrixView("Current Matrix", connectedMatrix->v, GuiMatrixViewFlags_Header, ImGuiTableFlags_Borders | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_SizingFixedFit, "%.1f"); | |
396 | } | ||
397 | else | ||
398 | { | ||
399 | ✗ | ImGui::TextUnformatted("Matrix: N/A"); | |
400 | ✗ | } | |
401 | |||
402 | ✗ | ImGui::TableSetColumnIndex(2); | |
403 | { | ||
404 | ✗ | auto guard = requestOutputValueLock(getPinIdx(DemoPins::Matrix).value()); | |
405 | ✗ | if (gui::widgets::InputMatrix(fmt::format("Init Matrix##{}", size_t(id)).c_str(), &_valueMatrix, GuiMatrixViewFlags_Header, ImGuiTableFlags_Borders | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_SizingFixedFit, 30.0F, 0.0, 0.0, "%.1f")) | |
406 | { | ||
407 | ✗ | flow::ApplyChanges(); | |
408 | } | ||
409 | ✗ | } | |
410 | } | ||
411 | |||
412 | ✗ | ImGui::EndTable(); | |
413 | } | ||
414 | ✗ | } | |
415 | |||
416 | ✗ | [[nodiscard]] json NAV::Demo::save() const | |
417 | { | ||
418 | LOG_TRACE("{}: called", nameId()); | ||
419 | |||
420 | ✗ | json j; | |
421 | |||
422 | return { | ||
423 | ✗ | { "outputFrequency", _outputFrequency }, | |
424 | ✗ | { "nPollData", _nPollData }, | |
425 | ✗ | { "enableDelegate", _enableDelegate }, | |
426 | ✗ | { "enableFlow", _enableFlow }, | |
427 | ✗ | { "enableBool", _enableBool }, | |
428 | ✗ | { "enableInt", _enableInt }, | |
429 | ✗ | { "enableFloat", _enableFloat }, | |
430 | ✗ | { "enableDouble", _enableDouble }, | |
431 | ✗ | { "enableString", _enableString }, | |
432 | ✗ | { "enableObject", _enableObject }, | |
433 | ✗ | { "enableMatrix", _enableMatrix }, | |
434 | ✗ | { "valueBool", _valueBool }, | |
435 | ✗ | { "valueInt", _valueInt }, | |
436 | ✗ | { "valueFloat", _valueFloat }, | |
437 | ✗ | { "valueDouble", _valueDouble }, | |
438 | ✗ | { "valueString", _valueString }, | |
439 | ✗ | { "valueObject", _valueObject }, | |
440 | ✗ | { "valueMatrix", _valueMatrix }, | |
441 | ✗ | { "fileReaderInsteadSensor", _fileReaderInsteadSensor }, | |
442 | ✗ | }; | |
443 | ✗ | } | |
444 | |||
445 | 6 | void NAV::Demo::restore(json const& j) | |
446 | { | ||
447 | LOG_TRACE("{}: called", nameId()); | ||
448 | |||
449 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("outputFrequency")) { j.at("outputFrequency").get_to(_outputFrequency); } |
450 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("nPollData")) { j.at("nPollData").get_to(_nPollData); } |
451 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableDelegate")) { j.at("enableDelegate").get_to(_enableDelegate); } |
452 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableFlow")) { j.at("enableFlow").get_to(_enableFlow); } |
453 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableBool")) { j.at("enableBool").get_to(_enableBool); } |
454 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableInt")) { j.at("enableInt").get_to(_enableInt); } |
455 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableFloat")) { j.at("enableFloat").get_to(_enableFloat); } |
456 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableDouble")) { j.at("enableDouble").get_to(_enableDouble); } |
457 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableString")) { j.at("enableString").get_to(_enableString); } |
458 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableObject")) { j.at("enableObject").get_to(_enableObject); } |
459 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("enableMatrix")) { j.at("enableMatrix").get_to(_enableMatrix); } |
460 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueBool")) { j.at("valueBool").get_to(_valueBool); } |
461 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueInt")) { j.at("valueInt").get_to(_valueInt); } |
462 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueFloat")) { j.at("valueFloat").get_to(_valueFloat); } |
463 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueDouble")) { j.at("valueDouble").get_to(_valueDouble); } |
464 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueString")) { j.at("valueString").get_to(_valueString); } |
465 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueObject")) { j.at("valueObject").get_to(_valueObject); } |
466 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("valueMatrix")) { j.at("valueMatrix").get_to(_valueMatrix); } |
467 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (j.contains("fileReaderInsteadSensor")) |
468 | { | ||
469 | 6 | j.at("fileReaderInsteadSensor").get_to(_fileReaderInsteadSensor); | |
470 | 6 | updateOutputFlowPin(); | |
471 | } | ||
472 | 6 | updatePins(); | |
473 | 6 | } | |
474 | |||
475 | 6 | bool NAV::Demo::initialize() | |
476 | { | ||
477 | LOG_TRACE("{}: called", nameId()); | ||
478 | |||
479 | // To Show the Initialization in the GUI | ||
480 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | std::this_thread::sleep_for(std::chrono::milliseconds(2000)); |
481 | |||
482 | 6 | _receivedDataCnt = 0; | |
483 | |||
484 | 6 | _stringUpdateCounter = 0; | |
485 | |||
486 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
|
6 | if (_enableFlow && !_fileReaderInsteadSensor) |
487 | { | ||
488 | // The Timer is used to simulate a sensor reader | ||
489 | 4 | int outputInterval = static_cast<int>(1.0 / static_cast<double>(_outputFrequency) * 1000.0); | |
490 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | _timer.start(outputInterval, readSensorDataThread, this); |
491 | } | ||
492 | |||
493 | 6 | return true; | |
494 | } | ||
495 | |||
496 | 6 | void NAV::Demo::deinitialize() | |
497 | { | ||
498 | LOG_TRACE("{}: called", nameId()); | ||
499 | |||
500 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
|
6 | if (_timer.is_running()) |
501 | { | ||
502 | 4 | _timer.stop(); | |
503 | } | ||
504 | |||
505 | // To Show the Deinitialization in the GUI | ||
506 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); |
507 | 6 | } | |
508 | |||
509 | 124 | void NAV::Demo::updatePins() | |
510 | { | ||
511 | 124 | size_t pinIdx = 0; | |
512 | |||
513 | 992 | auto updatePin = [&](bool pinExists, bool enabled, | |
514 | const char* pinName, Pin::Type pinType, const std::vector<std::string>& dataIdentifier = {}, // BUG: Bug in clang-format, so we need to disable formatting | ||
515 | OutputPin::PinData data = static_cast<void*>(nullptr), // clang-format off | ||
516 | void(NAV::Demo::*notifyFunc)(const InsTime&, size_t) = nullptr) { // clang-format on | ||
517 |
3/4✓ Branch 0 taken 992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 975 times.
|
992 | if (!pinExists && enabled) |
518 | { | ||
519 | 17 | nm::CreateInputPin(this, pinName, pinType, dataIdentifier, notifyFunc, static_cast<int>(pinIdx)); | |
520 | 17 | nm::CreateOutputPin(this, pinName, pinType, dataIdentifier, data, static_cast<int>(pinIdx)); | |
521 | } | ||
522 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 975 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
975 | else if (pinExists && !enabled) |
523 | { | ||
524 | ✗ | nm::DeleteInputPin(inputPins.at(pinIdx)); | |
525 | ✗ | nm::DeleteOutputPin(outputPins.at(pinIdx)); | |
526 | } | ||
527 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 975 times.
|
992 | if (enabled) { pinIdx++; } |
528 | 1116 | }; | |
529 | |||
530 |
6/18✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 124 times.
✓ Branch 25 taken 124 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
372 | updatePin(getPinIdx(DemoPins::Delegate) && inputPins.at(*getPinIdx(DemoPins::Delegate)).type == Pin::Type::Delegate, _enableDelegate, |
531 | 124 | "Demo Node", Pin::Type::Delegate, { typeStatic() }, this); | |
532 | // nm::CreateInputPin(this, "Demo Node", Pin::Type::Delegate, { typeStatic() }); | ||
533 | // nm::CreateOutputPin(this, "", Pin::Type::Delegate, { typeStatic() }, this, 0); | ||
534 | |||
535 | { | ||
536 |
5/10✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 124 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 124 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 124 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 124 times.
✗ Branch 15 not taken.
|
124 | bool pinExists = getPinIdx(DemoPins::Flow) && inputPins.at(*getPinIdx(DemoPins::Flow)).type == Pin::Type::Flow; |
537 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
124 | if (!pinExists && _enableFlow) |
538 | { | ||
539 | ✗ | nm::CreateInputPin(this, "Flow", Pin::Type::Flow, { NAV::NodeData::type() }, &Demo::receiveData); | |
540 | ✗ | nm::CreateOutputPin(this, "Sensor\nData", Pin::Type::Flow, { NAV::ImuObs::type() }); | |
541 | } | ||
542 |
3/4✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 123 times.
|
124 | else if (pinExists && !_enableFlow) |
543 | { | ||
544 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | nm::DeleteInputPin(inputPins.at(pinIdx)); |
545 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | nm::DeleteOutputPin(outputPins.at(pinIdx)); |
546 | } | ||
547 |
2/2✓ Branch 0 taken 123 times.
✓ Branch 1 taken 1 times.
|
124 | if (_enableFlow) { pinIdx++; } |
548 | } | ||
549 | |||
550 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Bool) && inputPins.at(*getPinIdx(DemoPins::Bool)).type == Pin::Type::Bool, _enableBool, |
551 | 124 | "Bool", Pin::Type::Bool, { "" }, &_valueBool); | |
552 | // nm::CreateInputPin(this, "Bool", Pin::Type::Bool); | ||
553 | // nm::CreateOutputPin(this, "Bool", Pin::Type::Bool, { "" }, &_valueBool); | ||
554 | |||
555 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Int) && inputPins.at(*getPinIdx(DemoPins::Int)).type == Pin::Type::Int, _enableInt, |
556 | 124 | "Int", Pin::Type::Int, { "" }, &_valueInt); | |
557 | // nm::CreateInputPin(this, "Int", Pin::Type::Int); | ||
558 | // nm::CreateOutputPin(this, "Int", Pin::Type::Int, { "" }, &_valueInt); | ||
559 | |||
560 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Float) && inputPins.at(*getPinIdx(DemoPins::Float)).type == Pin::Type::Float, _enableFloat, |
561 | 124 | "Float", Pin::Type::Float, { "Float" }, &_valueFloat); | |
562 | // nm::CreateInputPin(this, "Float", Pin::Type::Float); | ||
563 | // nm::CreateOutputPin(this, "Float", Pin::Type::Float, { "" }, &_valueFloat); | ||
564 | |||
565 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Double) && inputPins.at(*getPinIdx(DemoPins::Double)).type == Pin::Type::Float, _enableDouble, |
566 | 124 | "Double", Pin::Type::Float, { "Double" }, &_valueDouble); | |
567 | // nm::CreateInputPin(this, "Double", Pin::Type::Float); | ||
568 | // nm::CreateOutputPin(this, "Double", Pin::Type::Float, { "" }, &_valueDouble); | ||
569 | |||
570 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::String) && inputPins.at(*getPinIdx(DemoPins::String)).type == Pin::Type::String, _enableString, |
571 | 124 | "String", Pin::Type::String, { "" }, &_valueString, &Demo::stringUpdatedNotifyFunction); | |
572 | // nm::CreateInputPin(this, "String", Pin::Type::String, {}, &Demo::stringUpdatedNotifyFunction); | ||
573 | // nm::CreateOutputPin(this, "String", Pin::Type::String, { "" }, &_valueString); | ||
574 | |||
575 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Object) && inputPins.at(*getPinIdx(DemoPins::Object)).type == Pin::Type::Object, _enableObject, |
576 | 124 | "Object", Pin::Type::Object, { "Demo::DemoData" }, &_valueObject); | |
577 | // nm::CreateInputPin(this, "Object", Pin::Type::Object, { "Demo::DemoData" }); | ||
578 | // nm::CreateOutputPin(this, "Object", Pin::Type::Object, { "Demo::DemoData" }, &_valueObject); | ||
579 | |||
580 |
4/14✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 124 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 124 times.
✗ Branch 22 not taken.
|
248 | updatePin(getPinIdx(DemoPins::Matrix) && inputPins.at(*getPinIdx(DemoPins::Matrix)).type == Pin::Type::Matrix, _enableMatrix, |
581 | 124 | "Matrix", Pin::Type::Matrix, { "Eigen::MatrixXd" }, &_valueMatrix); | |
582 | // nm::CreateInputPin(this, "Matrix", Pin::Type::Matrix, { "Eigen::MatrixXd" }); | ||
583 | // nm::CreateOutputPin(this, "Matrix", Pin::Type::Matrix, { "Eigen::MatrixXd" }, &_valueMatrix); | ||
584 | 248 | } | |
585 | |||
586 | 1387 | std::optional<size_t> NAV::Demo::getPinIdx(DemoPins pinType) const | |
587 | { | ||
588 |
2/2✓ Branch 1 taken 1520 times.
✓ Branch 2 taken 993 times.
|
2511 | for (size_t i = 0; i < inputPins.size(); i++) |
589 | { | ||
590 |
9/10✓ Branch 0 taken 124 times.
✓ Branch 1 taken 481 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 127 times.
✓ Branch 4 taken 129 times.
✓ Branch 5 taken 131 times.
✓ Branch 6 taken 133 times.
✓ Branch 7 taken 136 times.
✓ Branch 8 taken 138 times.
✗ Branch 9 not taken.
|
1520 | switch (pinType) |
591 | { | ||
592 | 124 | case DemoPins::Delegate: | |
593 |
2/4✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 124 times.
|
124 | if (inputPins.at(i).type == Pin::Type::Delegate) { return i; } |
594 | 124 | break; | |
595 | 481 | case DemoPins::Flow: | |
596 |
3/4✓ Branch 1 taken 476 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 392 times.
✓ Branch 5 taken 85 times.
|
481 | if (inputPins.at(i).type == Pin::Type::Flow) { return i; } |
597 | 85 | break; | |
598 | 125 | case DemoPins::Bool: | |
599 |
2/4✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 125 times.
|
125 | if (inputPins.at(i).type == Pin::Type::Bool) { return i; } |
600 | 125 | break; | |
601 | 127 | case DemoPins::Int: | |
602 |
2/4✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127 times.
|
127 | if (inputPins.at(i).type == Pin::Type::Int) { return i; } |
603 | 127 | break; | |
604 | 129 | case DemoPins::Float: | |
605 |
3/12✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 129 times.
|
129 | if (inputPins.at(i).type == Pin::Type::Float && inputPins.at(i).dataIdentifier.front() == "Float") { return i; } |
606 | 129 | break; | |
607 | 131 | case DemoPins::Double: | |
608 |
7/12✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 129 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 131 times.
|
131 | if (inputPins.at(i).type == Pin::Type::Float && inputPins.at(i).dataIdentifier.front() == "Double") { return i; } |
609 | 131 | break; | |
610 | 133 | case DemoPins::String: | |
611 |
2/4✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 133 times.
|
133 | if (inputPins.at(i).type == Pin::Type::String) { return i; } |
612 | 133 | break; | |
613 | 136 | case DemoPins::Object: | |
614 |
2/4✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 136 times.
|
136 | if (inputPins.at(i).type == Pin::Type::Object) { return i; } |
615 | 136 | break; | |
616 | 138 | case DemoPins::Matrix: | |
617 |
2/4✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 138 times.
|
138 | if (inputPins.at(i).type == Pin::Type::Matrix) { return i; } |
618 | 138 | break; | |
619 | } | ||
620 | } | ||
621 | |||
622 | 993 | return std::nullopt; | |
623 | } | ||
624 | |||
625 | 12 | bool NAV::Demo::resetNode() | |
626 | { | ||
627 | LOG_TRACE("{}: called", nameId()); | ||
628 | // Here you could reset a FileReader | ||
629 | 12 | _iPollData = 0; | |
630 | 12 | _receivedDataCnt = 0; | |
631 | |||
632 | 12 | return true; | |
633 | } | ||
634 | |||
635 | 6 | void NAV::Demo::updateOutputFlowPin() | |
636 | { | ||
637 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | size_t flowPinIdx = getPinIdx(DemoPins::Flow).value(); |
638 | 6 | std::vector<ax::NodeEditor::PinId> connectedPins; | |
639 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
|
6 | for (const auto& link : outputPins.at(flowPinIdx).links) |
640 | { | ||
641 | ✗ | connectedPins.push_back(link.connectedPinId); | |
642 | } | ||
643 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | nm::DeleteOutputPin(outputPins.at(flowPinIdx)); |
644 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | if (_fileReaderInsteadSensor) |
645 | { | ||
646 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
3 | nm::CreateOutputPin(this, "FileReader\n Data", Pin::Type::Flow, { NAV::NodeData::type() }, &Demo::pollData, static_cast<int>(flowPinIdx)); |
647 | } | ||
648 | else | ||
649 | { | ||
650 |
4/8✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
20 | nm::CreateOutputPin(this, "Sensor\nData", Pin::Type::Flow, { NAV::ImuObs::type() }, static_cast<void*>(nullptr), static_cast<int>(flowPinIdx)); |
651 | } | ||
652 |
1/2✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
|
6 | for (const auto& pinId : connectedPins) |
653 | { | ||
654 | ✗ | if (auto* targetPin = nm::FindInputPin(pinId)) | |
655 | { | ||
656 | ✗ | if (outputPins.at(flowPinIdx).canCreateLink(*targetPin)) | |
657 | { | ||
658 | ✗ | outputPins.at(flowPinIdx).createLink(*targetPin); | |
659 | } | ||
660 | } | ||
661 | } | ||
662 | 12 | } | |
663 | |||
664 | 24 | bool NAV::Demo::onCreateLink([[maybe_unused]] OutputPin& startPin, [[maybe_unused]] InputPin& endPin) | |
665 | { | ||
666 | LOG_TRACE("{}: called for {} ==> {}", nameId(), size_t(startPin.id), size_t(endPin.id)); | ||
667 | |||
668 |
10/14✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 23 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 23 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9 times.
✓ Branch 15 taken 14 times.
✓ Branch 16 taken 9 times.
✓ Branch 17 taken 15 times.
|
24 | if (_enableFlow && outputPins.at(getPinIdx(DemoPins::Flow).value()).isPinLinked()) |
669 | { | ||
670 | 9 | _onlyRealTime = !_fileReaderInsteadSensor; | |
671 | } | ||
672 | |||
673 | 24 | return true; | |
674 | } | ||
675 | |||
676 | 24 | void NAV::Demo::afterDeleteLink([[maybe_unused]] OutputPin& startPin, [[maybe_unused]] InputPin& endPin) | |
677 | { | ||
678 | LOG_TRACE("{}: called for {} ==> {}", nameId(), size_t(startPin.id), size_t(endPin.id)); | ||
679 | |||
680 |
10/14✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 23 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 23 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13 times.
✓ Branch 15 taken 10 times.
✓ Branch 16 taken 13 times.
✓ Branch 17 taken 11 times.
|
24 | if (_enableFlow && !outputPins.at(getPinIdx(DemoPins::Flow).value()).isPinLinked()) |
681 | { | ||
682 | 13 | _onlyRealTime = false; | |
683 | } | ||
684 | 24 | } | |
685 | |||
686 | 30 | void NAV::Demo::receiveData(NAV::InputPin::NodeDataQueue& queue, size_t /* pinIdx */) | |
687 | { | ||
688 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | std::shared_ptr<const NAV::NodeData> obs = queue.extract_front(); // Either 'extract_front()' or 'pop_front()' needs to be called |
689 | 30 | _receivedDataCnt++; | |
690 | |||
691 |
4/8✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 30 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 30 times.
✗ Branch 14 not taken.
|
30 | LOG_DEBUG("{}: received {} data at [{} GPST]", nameId(), _receivedDataCnt, obs->insTime.toYMDHMS(GPST)); |
692 | 30 | } | |
693 | |||
694 | 36 | void NAV::Demo::readSensorDataThread(void* userData) | |
695 | { | ||
696 | 36 | auto* node = static_cast<Demo*>(userData); | |
697 | |||
698 |
5/8✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
|
72 | if (!node->_enableFlow || !node->getPinIdx(DemoPins::Flow).has_value()) { return; } |
699 | |||
700 |
10/14✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 34 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 40 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13 times.
✓ Branch 13 taken 27 times.
✓ Branch 14 taken 8 times.
✓ Branch 15 taken 5 times.
✓ Branch 16 taken 36 times.
✓ Branch 17 taken 4 times.
|
27 | if (!node->outputPins.at(node->getPinIdx(DemoPins::Flow).value()).isPinLinked() || !node->callbacksEnabled) |
701 | { | ||
702 | 36 | return; | |
703 | } | ||
704 | |||
705 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
4 | if (node->getMode() == Mode::POST_PROCESSING) |
706 | { | ||
707 | ✗ | LOG_WARN("{}: Flow contains nodes which can only do post-processing. Sensor output is suppressed."); | |
708 | |||
709 | ✗ | return; | |
710 | } | ||
711 | |||
712 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | auto imuPos = ImuPos(); |
713 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | auto obs = std::make_shared<ImuObs>(imuPos); |
714 | |||
715 | 5 | std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); | |
716 | 5 | auto* t = std::gmtime(&now); // NOLINT(concurrency-mt-unsafe) | |
717 | |||
718 | 5 | obs->insTime = InsTime(static_cast<uint16_t>(t->tm_year + 1900), static_cast<uint16_t>(t->tm_mon) + 1, static_cast<uint16_t>(t->tm_mday), | |
719 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | static_cast<uint16_t>(t->tm_hour), static_cast<uint16_t>(t->tm_min), static_cast<long double>(t->tm_sec), GPST); |
720 | |||
721 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | std::random_device rd; |
722 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | std::default_random_engine generator(rd()); |
723 | |||
724 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | std::uniform_real_distribution<double> distribution(-9.0, 9.0); |
725 |
4/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
|
5 | obs->p_acceleration = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator)); |
726 | |||
727 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | distribution = std::uniform_real_distribution<double>(-3.0, 3.0); |
728 |
4/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
|
5 | obs->p_angularRate = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator)); |
729 | |||
730 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | distribution = std::uniform_real_distribution<double>(-1.0, 1.0); |
731 |
4/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
|
5 | obs->p_magneticField = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator)); |
732 | |||
733 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | distribution = std::uniform_real_distribution<double>(15.0, 25.0); |
734 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | obs->temperature = distribution(generator); |
735 | |||
736 |
4/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
|
5 | LOG_INFO("{}: Sending Sensor data with time [{} GPST]", node->nameId(), obs->insTime.toYMDHMS(GPST)); |
737 | |||
738 |
3/6✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
|
5 | node->invokeCallbacks(node->getPinIdx(DemoPins::Flow).value(), obs); |
739 | 5 | } | |
740 | |||
741 | ✗ | std::shared_ptr<const NAV::NodeData> NAV::Demo::peekPollData(bool peek) | |
742 | { | ||
743 | // This function is only an example of how to implement peek/poll logic. It is not used in this node. | ||
744 | ✗ | if (_iPollData >= _nPollData) | |
745 | { | ||
746 | ✗ | return nullptr; | |
747 | } | ||
748 | |||
749 | ✗ | if (peek) // Early return with time to let the Node sort the observations | |
750 | { | ||
751 | ✗ | auto obs = std::make_shared<NodeData>(); // Construct the real observation (here in example also from type NodeData) | |
752 | ✗ | obs->insTime = InsTime(2000, 1, 1, 0, 0, _iPollData); | |
753 | ✗ | return obs; | |
754 | ✗ | } | |
755 | |||
756 | ✗ | auto obs = std::make_shared<NodeData>(); // Construct the real observation (here in example also from type NodeData) | |
757 | ✗ | obs->insTime = InsTime(2000, 1, 1, 0, 0, _iPollData); | |
758 | |||
759 | ✗ | _iPollData++; | |
760 | // Calls all the callbacks | ||
761 | ✗ | invokeCallbacks(getPinIdx(DemoPins::Flow).value(), obs); | |
762 | |||
763 | ✗ | return obs; | |
764 | ✗ | } | |
765 | |||
766 | 21 | std::shared_ptr<const NAV::NodeData> NAV::Demo::pollData() | |
767 | { | ||
768 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | if (_iPollData >= _nPollData) |
769 | { | ||
770 | 1 | return nullptr; // Tells the node that the last message was read | |
771 | } | ||
772 | |||
773 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | auto obs = std::make_shared<NodeData>(); // Construct the real observation (here in example also from type NodeData) |
774 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | obs->insTime = InsTime(2000, 1, 1, 0, 0, _iPollData); |
775 | |||
776 | 20 | _iPollData++; | |
777 | |||
778 |
3/6✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
|
20 | invokeCallbacks(getPinIdx(DemoPins::Flow).value(), obs); // Calls all the callbacks |
779 | 20 | return obs; | |
780 | 20 | } | |
781 | |||
782 | ✗ | void NAV::Demo::stringUpdatedNotifyFunction([[maybe_unused]] const InsTime& insTime, size_t pinIdx) | |
783 | { | ||
784 | ✗ | _stringUpdateCounter++; | |
785 | |||
786 | ✗ | if (auto value = getInputValue<std::string>(pinIdx)) | |
787 | { | ||
788 | ✗ | LOG_DEBUG("String value updated to '{}' at time {}", *value->v, insTime); | |
789 | ✗ | } | |
790 | ✗ | } | |
791 |