36 std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
37 auto* t = std::localtime(&now);
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) };
63 if (j.contains(
"boolean"))
65 j.at(
"boolean").get_to(data.
boolean);
67 if (j.contains(
"integer"))
69 j.at(
"integer").get_to(data.
integer);
115 if (ImGui::BeginTable(
"##DemoValues", 3, ImGuiTableFlags_Borders))
117 ImGui::TableSetupColumn(
"Enable");
118 ImGui::TableSetupColumn(
"Input");
119 ImGui::TableSetupColumn(
"Output");
120 ImGui::TableHeadersRow();
123 ImGui::TableNextRow();
124 ImGui::TableSetColumnIndex(0);
125 if (ImGui::Checkbox(fmt::format(
"Delegate##enable {}",
size_t(
id)).c_str(), &
_enableDelegate))
132 ImGui::TableSetColumnIndex(1);
136 ImGui::Text(
"Delegate: %s", connectedNode ? connectedNode->v->nameId().c_str() :
"N/A");
140 ImGui::TableNextRow();
141 ImGui::TableSetColumnIndex(0);
142 if (ImGui::Checkbox(fmt::format(
"Flow##enable {}",
size_t(
id)).c_str(), &
_enableFlow))
149 ImGui::TableSetColumnIndex(1);
151 ImGui::TableSetColumnIndex(2);
162 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
171 ImGui::SetNextItemWidth(100.0F);
172 if (ImGui::InputInt(fmt::format(
"FileReader Obs Count##{}",
size_t(
id)).c_str(), &
_nPollData))
179 if (ImGui::SliderInt(fmt::format(
"Frequency##{}",
size_t(
id)).c_str(), &
_outputFrequency, 1, 10))
181 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
182 _timer.setInterval(outputInterval);
188 ImGui::TableNextRow();
189 ImGui::TableSetColumnIndex(0);
190 if (ImGui::Checkbox(fmt::format(
"Bool##enable {}",
size_t(
id)).c_str(), &
_enableBool))
197 ImGui::TableSetColumnIndex(1);
200 ImGui::Text(
"Bool: %s", connectedBool ? (connectedBool->v ?
"true" :
"false") :
"N/A");
203 ImGui::TableSetColumnIndex(2);
206 if (ImGui::Checkbox(fmt::format(
"Bool##{}",
size_t(
id)).c_str(), &
_valueBool))
213 ImGui::TableNextRow();
214 ImGui::TableSetColumnIndex(0);
215 if (ImGui::Checkbox(fmt::format(
"Int##enable {}",
size_t(
id)).c_str(), &
_enableInt))
222 ImGui::TableSetColumnIndex(1);
225 ImGui::Text(
"Int: %d", *connectedInt->v);
229 ImGui::TextUnformatted(
"Int: N/A");
232 ImGui::TableSetColumnIndex(2);
235 if (ImGui::InputInt(fmt::format(
"Int##{}",
size_t(
id)).c_str(), &
_valueInt))
246 ImGui::TableNextRow();
247 ImGui::TableSetColumnIndex(0);
248 if (ImGui::Checkbox(fmt::format(
"Float##enable {}",
size_t(
id)).c_str(), &
_enableFloat))
255 ImGui::TableSetColumnIndex(1);
258 ImGui::Text(
"Float: %.3f", *connectedFloat->v);
262 ImGui::TextUnformatted(
"Float: N/A");
265 ImGui::TableSetColumnIndex(2);
268 if (ImGui::DragFloat(fmt::format(
"Float##{}",
size_t(
id)).c_str(), &
_valueFloat))
275 ImGui::TableNextRow();
276 ImGui::TableSetColumnIndex(0);
277 if (ImGui::Checkbox(fmt::format(
"Double##enable {}",
size_t(
id)).c_str(), &
_enableDouble))
284 ImGui::TableSetColumnIndex(1);
287 ImGui::Text(
"Double : %.3f", *connectedDouble->v);
291 ImGui::TextUnformatted(
"Double: N/A");
294 ImGui::TableSetColumnIndex(2);
304 ImGui::TableNextRow();
305 ImGui::TableSetColumnIndex(0);
306 if (ImGui::Checkbox(fmt::format(
"String##enable {}",
size_t(
id)).c_str(), &
_enableString))
313 ImGui::TableSetColumnIndex(1);
316 ImGui::Text(
"String: %s", connectedString->v->c_str());
320 ImGui::TextUnformatted(
"String: N/A");
324 ImGui::TableSetColumnIndex(2);
328 if (ImGui::InputText(fmt::format(
"String##{}",
size_t(
id)).c_str(), &
_valueString))
332 if (outputPin.isPinLinked())
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(); }))
338 LOG_WARN(
"{}: Notifying connected nodes requires at least one connected node to be initialized.",
nameId());
348 ImGui::TableNextRow();
349 ImGui::TableSetColumnIndex(0);
350 if (ImGui::Checkbox(fmt::format(
"Object##enable {}",
size_t(
id)).c_str(), &
_enableObject))
357 ImGui::TableSetColumnIndex(1);
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");
365 ImGui::TextUnformatted(
"Object: N/A");
368 ImGui::TableSetColumnIndex(2);
371 if (ImGui::InputInt3(fmt::format(
"##object.integer {}",
size_t(
id)).c_str(),
_valueObject.integer.data()))
376 if (ImGui::Checkbox(fmt::format(
"Object##{}",
size_t(
id)).c_str(), &
_valueObject.boolean))
383 ImGui::TableNextRow();
384 ImGui::TableSetColumnIndex(0);
385 if (ImGui::Checkbox(fmt::format(
"Matrix##enable {}",
size_t(
id)).c_str(), &
_enableMatrix))
392 ImGui::TableSetColumnIndex(1);
399 ImGui::TextUnformatted(
"Matrix: N/A");
402 ImGui::TableSetColumnIndex(2);
449 if (j.contains(
"outputFrequency")) { j.at(
"outputFrequency").get_to(
_outputFrequency); }
450 if (j.contains(
"nPollData")) { j.at(
"nPollData").get_to(
_nPollData); }
451 if (j.contains(
"enableDelegate")) { j.at(
"enableDelegate").get_to(
_enableDelegate); }
452 if (j.contains(
"enableFlow")) { j.at(
"enableFlow").get_to(
_enableFlow); }
453 if (j.contains(
"enableBool")) { j.at(
"enableBool").get_to(
_enableBool); }
454 if (j.contains(
"enableInt")) { j.at(
"enableInt").get_to(
_enableInt); }
455 if (j.contains(
"enableFloat")) { j.at(
"enableFloat").get_to(
_enableFloat); }
456 if (j.contains(
"enableDouble")) { j.at(
"enableDouble").get_to(
_enableDouble); }
457 if (j.contains(
"enableString")) { j.at(
"enableString").get_to(
_enableString); }
458 if (j.contains(
"enableObject")) { j.at(
"enableObject").get_to(
_enableObject); }
459 if (j.contains(
"enableMatrix")) { j.at(
"enableMatrix").get_to(
_enableMatrix); }
460 if (j.contains(
"valueBool")) { j.at(
"valueBool").get_to(
_valueBool); }
461 if (j.contains(
"valueInt")) { j.at(
"valueInt").get_to(
_valueInt); }
462 if (j.contains(
"valueFloat")) { j.at(
"valueFloat").get_to(
_valueFloat); }
463 if (j.contains(
"valueDouble")) { j.at(
"valueDouble").get_to(
_valueDouble); }
464 if (j.contains(
"valueString")) { j.at(
"valueString").get_to(
_valueString); }
465 if (j.contains(
"valueObject")) { j.at(
"valueObject").get_to(
_valueObject); }
466 if (j.contains(
"valueMatrix")) { j.at(
"valueMatrix").get_to(
_valueMatrix); }
467 if (j.contains(
"fileReaderInsteadSensor"))
480 std::this_thread::sleep_for(std::chrono::milliseconds(2000));
489 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
506 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
513 auto updatePin = [&](
bool pinExists,
bool enabled,
514 const char* pinName,
Pin::Type pinType,
const std::vector<std::string>& dataIdentifier = {},
517 if (!pinExists && enabled)
519 nm::CreateInputPin(
this, pinName, pinType, dataIdentifier, notifyFunc,
static_cast<int>(pinIdx));
520 nm::CreateOutputPin(
this, pinName, pinType, dataIdentifier, data,
static_cast<int>(pinIdx));
522 else if (pinExists && !enabled)
527 if (enabled) { pinIdx++; }
588 for (
size_t i = 0; i <
inputPins.size(); i++)
638 std::vector<ax::NodeEditor::PinId> connectedPins;
639 for (
const auto& link :
outputPins.at(flowPinIdx).links)
641 connectedPins.push_back(link.connectedPinId);
652 for (
const auto& pinId : connectedPins)
656 if (
outputPins.at(flowPinIdx).canCreateLink(*targetPin))
658 outputPins.at(flowPinIdx).createLink(*targetPin);
666 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
678 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
688 std::shared_ptr<const NAV::NodeData> obs = queue.
extract_front();
696 auto* node =
static_cast<Demo*
>(userData);
698 if (!node->_enableFlow || !node->getPinIdx(
DemoPins::Flow).has_value()) {
return; }
700 if (!node->outputPins.at(node->getPinIdx(
DemoPins::Flow).value()).isPinLinked() || !node->callbacksEnabled)
707 LOG_WARN(
"{}: Flow contains nodes which can only do post-processing. Sensor output is suppressed.");
713 auto obs = std::make_shared<ImuObs>(imuPos);
715 std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
716 auto* t = std::gmtime(&now);
718 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 static_cast<uint16_t
>(t->tm_hour),
static_cast<uint16_t
>(t->tm_min),
static_cast<long double>(t->tm_sec),
GPST);
721 std::random_device rd;
722 std::default_random_engine generator(rd());
724 std::uniform_real_distribution<double> distribution(-9.0, 9.0);
725 obs->p_acceleration = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
727 distribution = std::uniform_real_distribution<double>(-3.0, 3.0);
728 obs->p_angularRate = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
730 distribution = std::uniform_real_distribution<double>(-1.0, 1.0);
731 obs->p_magneticField = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
733 distribution = std::uniform_real_distribution<double>(15.0, 25.0);
734 obs->temperature = distribution(generator);
736 LOG_INFO(
"{}: Sending Sensor data with time [{} GPST]", node->nameId(), obs->insTime.toYMDHMS(
GPST));
738 node->invokeCallbacks(node->getPinIdx(
DemoPins::Flow).value(), obs);
751 auto obs = std::make_shared<NodeData>();
756 auto obs = std::make_shared<NodeData>();
773 auto obs = std::make_shared<NodeData>();
788 LOG_DEBUG(
"String value updated to '{}' at time {}", *value->v, insTime);
Demo Node which demonstrates all capabilities.
nlohmann::json json
json namespace
Text Help Marker (?) with Tooltip.
Parent Class for all IMU Observations.
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
#define LOG_WARN
Error occurred, but a fallback option exists and program continues to work normally.
#define LOG_INFO
Info to the user on the state of the program.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Widgets related to Matrices.
@ GuiMatrixViewFlags_Header
Print all Header.
Demonstrates the basic GUI functionality of nodes.
bool _fileReaderInsteadSensor
Whether to have a file reader instead of a sensor output pin.
int _iPollData
Counter for data Reading.
bool _valueBool
Value which is represented over the Bool pin.
bool _enableInt
Switch to enable the int pin.
void afterDeleteLink(OutputPin &startPin, InputPin &endPin) override
Called when a link was deleted.
bool onCreateLink(OutputPin &startPin, InputPin &endPin) override
Called when a new link is to be established.
CallbackTimer _timer
Timer object to handle async data requests.
bool _enableFlow
Switch to enable the flow pin.
int _receivedDataCnt
Counter how often data was received.
bool _enableDouble
Switch to enable the double pin.
std::optional< size_t > getPinIdx(DemoPins pinType) const
Calculates the pin index for the given type.
bool _enableObject
Switch to enable the object pin.
float _valueFloat
Value which is represented over the Float pin.
bool _enableString
Switch to enable the string pin.
bool initialize() override
Initialize the node.
bool _enableFloat
Switch to enable the float pin.
void updatePins()
Update the pins depending on the GUI.
bool _enableBool
Switch to enable the bool pin.
size_t _stringUpdateCounter
Counter of how often the string was updated.
bool resetNode() override
Resets the node. It is guaranteed that the node is initialized when this is called.
static void readSensorDataThread(void *userData)
Function which performs the async data reading.
void stringUpdatedNotifyFunction(const InsTime &insTime, size_t pinIdx)
Function to call when the string is updated.
void restore(const json &j) override
Restores the node from a json object.
void updateOutputFlowPin()
Updates the output flow pin depending on the GUI selection.
std::shared_ptr< const NodeData > peekPollData(bool peek=false)
Polls data from the file. This function is needed, if we have multiple output pins,...
static std::string typeStatic()
String representation of the Class Type.
int _valueInt
Value which is represented over the Int pin.
Eigen::MatrixXd _valueMatrix
Value which is represented over the Matrix pin.
void deinitialize() override
Deinitialize the node.
int _nPollData
Amount of Observations to be read.
std::shared_ptr< const NodeData > pollData()
Polls data from the file.
bool _enableMatrix
Switch to enable the matrix pin.
std::string type() const override
String representation of the Class Type.
DemoPins
Pin types used in this demo.
@ Delegate
Delegate pins giving access to the complete connected node.
@ Flow
Flow pins transmitting data as timestamped shared pointers.
int _outputFrequency
Output frequency for the simulated sensor data.
void receiveData(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive callback on the Flow pin.
std::string _valueString
Value which is represented over the String pin.
static std::string category()
String representation of the Class Category.
bool _enableDelegate
Switch to enable the delegate pin.
void guiConfig() override
ImGui config window which is shown on double click.
Demo()
Default constructor.
json save() const override
Saves the node into a json object.
DemoData _valueObject
Value which is represented over the Object pin.
double _valueDouble
Value which is represented over the Double pin.
~Demo() override
Destructor.
static std::string type()
Returns the type of the data class.
The class is responsible for all time-related tasks.
static std::string type()
Returns the type of the data class.
bool isInitialized() const
Checks if the node is initialized.
ImVec2 _guiConfigDefaultWindowSize
void notifyOutputValueChanged(size_t pinIdx, const InsTime &insTime, const std::scoped_lock< std::mutex > &&guard)
Notifies connected nodes about the change.
std::vector< OutputPin > outputPins
List of output pins.
Node(std::string name)
Constructor.
std::optional< InputPin::IncomingLink::ValueWrapper< T > > getInputValue(size_t portIndex) const
Get Input Value connected on the pin. Only const data types.
std::vector< InputPin > inputPins
List of input pins.
@ POST_PROCESSING
Node running in post-processing mode.
bool callbacksEnabled
Enables the callbacks.
std::string nameId() const
Node name and id.
bool _lockConfigDuringRun
Lock the config when executing post-processing.
std::string name
Name of the Node.
bool _onlyRealTime
Whether the node can run in post-processing or only real-time.
std::scoped_lock< std::mutex > requestOutputValueLock(size_t pinIdx)
Blocks the thread till the output values was read by all connected nodes.
void invokeCallbacks(size_t portIndex, const std::shared_ptr< const NodeData > &data)
Calls all registered callbacks on the specified output port.
bool _hasConfig
Flag if the config window should be shown.
std::variant< const void *, const bool *, const int *, const float *, const double *, const std::string *, PeekPollDataFunc, PollDataFunc > PinData
Possible Types represented by an output pin.
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
bool DragDouble(const char *label, double *v, float v_speed, double v_min, double v_max, const char *format, ImGuiSliderFlags flags)
Shows a Drag GUI element for 'double'.
OutputPin * CreateOutputPin(Node *node, const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier, OutputPin::PinData data=static_cast< void * >(nullptr), int idx=-1)
Create an Output Pin object.
bool DeleteOutputPin(OutputPin &pin)
Deletes the output pin. Invalidates the pin reference given.
InputPin * FindInputPin(ax::NodeEditor::PinId id)
Finds the Pin for the PinId.
bool DeleteInputPin(InputPin &pin)
Deletes the input pin. Invalidates the pin reference given.
InputPin * CreateInputPin(Node *node, const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier={}, InputPin::Callback callback=static_cast< InputPin::FlowFirableCallbackFunc >(nullptr), InputPin::FlowFirableCheckFunc firable=nullptr, int priority=0, int idx=-1)
Create an Input Pin object.
void ApplyChanges()
Signals that there have been changes to the flow.
void to_json(json &j, const Node &node)
Converts the provided node into a json object.
void from_json(const json &j, Node &node)
Converts the provided json object into a node object.
Data struct transmitted over an output port.
bool boolean
Boolean inside the DemoData.
std::array< int, 3 > integer
Integer inside the DemoData.
Collection of information about the connected node and pin.
Type of the data on the Pin.
@ Delegate
Reference to the Node object.
@ Float
Floating Point Number.