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