34 std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
35 auto* t = std::localtime(&now);
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) };
61 if (j.contains(
"boolean"))
63 j.at(
"boolean").get_to(data.
boolean);
65 if (j.contains(
"integer"))
67 j.at(
"integer").get_to(data.
integer);
113 if (ImGui::BeginTable(
"##DemoValues", 3, ImGuiTableFlags_Borders))
115 ImGui::TableSetupColumn(
"Enable");
116 ImGui::TableSetupColumn(
"Input");
117 ImGui::TableSetupColumn(
"Output");
118 ImGui::TableHeadersRow();
121 ImGui::TableNextRow();
122 ImGui::TableSetColumnIndex(0);
123 if (ImGui::Checkbox(fmt::format(
"Delegate##enable {}",
size_t(
id)).c_str(), &
_enableDelegate))
130 ImGui::TableSetColumnIndex(1);
134 ImGui::Text(
"Delegate: %s", connectedNode ? connectedNode->v->nameId().c_str() :
"N/A");
138 ImGui::TableNextRow();
139 ImGui::TableSetColumnIndex(0);
140 if (ImGui::Checkbox(fmt::format(
"Flow##enable {}",
size_t(
id)).c_str(), &
_enableFlow))
147 ImGui::TableSetColumnIndex(1);
149 ImGui::TableSetColumnIndex(2);
160 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
169 ImGui::SetNextItemWidth(100.0F);
170 if (ImGui::InputInt(fmt::format(
"FileReader Obs Count##{}",
size_t(
id)).c_str(), &
_nPollData))
177 if (ImGui::SliderInt(fmt::format(
"Frequency##{}",
size_t(
id)).c_str(), &
_outputFrequency, 1, 10))
179 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
180 _timer.setInterval(outputInterval);
186 ImGui::TableNextRow();
187 ImGui::TableSetColumnIndex(0);
188 if (ImGui::Checkbox(fmt::format(
"Bool##enable {}",
size_t(
id)).c_str(), &
_enableBool))
195 ImGui::TableSetColumnIndex(1);
198 ImGui::Text(
"Bool: %s", connectedBool ? (connectedBool->v ?
"true" :
"false") :
"N/A");
201 ImGui::TableSetColumnIndex(2);
204 if (ImGui::Checkbox(fmt::format(
"Bool##{}",
size_t(
id)).c_str(), &
_valueBool))
211 ImGui::TableNextRow();
212 ImGui::TableSetColumnIndex(0);
213 if (ImGui::Checkbox(fmt::format(
"Int##enable {}",
size_t(
id)).c_str(), &
_enableInt))
220 ImGui::TableSetColumnIndex(1);
223 ImGui::Text(
"Int: %d", *connectedInt->v);
227 ImGui::TextUnformatted(
"Int: N/A");
230 ImGui::TableSetColumnIndex(2);
233 if (ImGui::InputInt(fmt::format(
"Int##{}",
size_t(
id)).c_str(), &
_valueInt))
244 ImGui::TableNextRow();
245 ImGui::TableSetColumnIndex(0);
246 if (ImGui::Checkbox(fmt::format(
"Float##enable {}",
size_t(
id)).c_str(), &
_enableFloat))
253 ImGui::TableSetColumnIndex(1);
256 ImGui::Text(
"Float: %.3f", *connectedFloat->v);
260 ImGui::TextUnformatted(
"Float: N/A");
263 ImGui::TableSetColumnIndex(2);
266 if (ImGui::DragFloat(fmt::format(
"Float##{}",
size_t(
id)).c_str(), &
_valueFloat))
273 ImGui::TableNextRow();
274 ImGui::TableSetColumnIndex(0);
275 if (ImGui::Checkbox(fmt::format(
"Double##enable {}",
size_t(
id)).c_str(), &
_enableDouble))
282 ImGui::TableSetColumnIndex(1);
285 ImGui::Text(
"Double : %.3f", *connectedDouble->v);
289 ImGui::TextUnformatted(
"Double: N/A");
292 ImGui::TableSetColumnIndex(2);
302 ImGui::TableNextRow();
303 ImGui::TableSetColumnIndex(0);
304 if (ImGui::Checkbox(fmt::format(
"String##enable {}",
size_t(
id)).c_str(), &
_enableString))
311 ImGui::TableSetColumnIndex(1);
314 ImGui::Text(
"String: %s", connectedString->v->c_str());
318 ImGui::TextUnformatted(
"String: N/A");
322 ImGui::TableSetColumnIndex(2);
326 if (ImGui::InputText(fmt::format(
"String##{}",
size_t(
id)).c_str(), &
_valueString))
330 if (outputPin.isPinLinked())
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(); }))
336 LOG_WARN(
"{}: Notifying connected nodes requires at least one connected node to be initialized.",
nameId());
346 ImGui::TableNextRow();
347 ImGui::TableSetColumnIndex(0);
348 if (ImGui::Checkbox(fmt::format(
"Object##enable {}",
size_t(
id)).c_str(), &
_enableObject))
355 ImGui::TableSetColumnIndex(1);
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");
363 ImGui::TextUnformatted(
"Object: N/A");
366 ImGui::TableSetColumnIndex(2);
369 if (ImGui::InputInt3(fmt::format(
"##object.integer {}",
size_t(
id)).c_str(),
_valueObject.integer.data()))
374 if (ImGui::Checkbox(fmt::format(
"Object##{}",
size_t(
id)).c_str(), &
_valueObject.boolean))
381 ImGui::TableNextRow();
382 ImGui::TableSetColumnIndex(0);
383 if (ImGui::Checkbox(fmt::format(
"Matrix##enable {}",
size_t(
id)).c_str(), &
_enableMatrix))
390 ImGui::TableSetColumnIndex(1);
397 ImGui::TextUnformatted(
"Matrix: N/A");
400 ImGui::TableSetColumnIndex(2);
447 if (j.contains(
"outputFrequency")) { j.at(
"outputFrequency").get_to(
_outputFrequency); }
448 if (j.contains(
"nPollData")) { j.at(
"nPollData").get_to(
_nPollData); }
449 if (j.contains(
"enableDelegate")) { j.at(
"enableDelegate").get_to(
_enableDelegate); }
450 if (j.contains(
"enableFlow")) { j.at(
"enableFlow").get_to(
_enableFlow); }
451 if (j.contains(
"enableBool")) { j.at(
"enableBool").get_to(
_enableBool); }
452 if (j.contains(
"enableInt")) { j.at(
"enableInt").get_to(
_enableInt); }
453 if (j.contains(
"enableFloat")) { j.at(
"enableFloat").get_to(
_enableFloat); }
454 if (j.contains(
"enableDouble")) { j.at(
"enableDouble").get_to(
_enableDouble); }
455 if (j.contains(
"enableString")) { j.at(
"enableString").get_to(
_enableString); }
456 if (j.contains(
"enableObject")) { j.at(
"enableObject").get_to(
_enableObject); }
457 if (j.contains(
"enableMatrix")) { j.at(
"enableMatrix").get_to(
_enableMatrix); }
458 if (j.contains(
"valueBool")) { j.at(
"valueBool").get_to(
_valueBool); }
459 if (j.contains(
"valueInt")) { j.at(
"valueInt").get_to(
_valueInt); }
460 if (j.contains(
"valueFloat")) { j.at(
"valueFloat").get_to(
_valueFloat); }
461 if (j.contains(
"valueDouble")) { j.at(
"valueDouble").get_to(
_valueDouble); }
462 if (j.contains(
"valueString")) { j.at(
"valueString").get_to(
_valueString); }
463 if (j.contains(
"valueObject")) { j.at(
"valueObject").get_to(
_valueObject); }
464 if (j.contains(
"valueMatrix")) { j.at(
"valueMatrix").get_to(
_valueMatrix); }
465 if (j.contains(
"fileReaderInsteadSensor"))
478 std::this_thread::sleep_for(std::chrono::milliseconds(2000));
487 int outputInterval =
static_cast<int>(1.0 /
static_cast<double>(
_outputFrequency) * 1000.0);
504 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
511 auto updatePin = [&](
bool pinExists,
bool enabled,
512 const char* pinName,
Pin::Type pinType,
const std::vector<std::string>& dataIdentifier = {},
515 if (!pinExists && enabled)
517 CreateInputPin(pinName, pinType, dataIdentifier, notifyFunc,
static_cast<int>(pinIdx));
518 CreateOutputPin(pinName, pinType, dataIdentifier, data,
static_cast<int>(pinIdx));
520 else if (pinExists && !enabled)
525 if (enabled) { pinIdx++; }
586 for (
size_t i = 0; i <
inputPins.size(); i++)
636 std::vector<ax::NodeEditor::PinId> connectedPins;
637 for (
const auto& link :
outputPins.at(flowPinIdx).links)
639 connectedPins.push_back(link.connectedPinId);
650 for (
const auto& pinId : connectedPins)
654 if (
outputPins.at(flowPinIdx).canCreateLink(*targetPin))
656 outputPins.at(flowPinIdx).createLink(*targetPin);
664 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
676 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
686 std::shared_ptr<const NAV::NodeData> obs = queue.
extract_front();
694 auto* node =
static_cast<Demo*
>(userData);
696 if (!node->_enableFlow || !node->getPinIdx(
DemoPins::Flow).has_value()) {
return; }
698 if (!node->outputPins.at(node->getPinIdx(
DemoPins::Flow).value()).isPinLinked() || !node->callbacksEnabled)
705 LOG_WARN(
"{}: Flow contains nodes which can only do post-processing. Sensor output is suppressed.");
711 auto obs = std::make_shared<ImuObs>(imuPos);
713 std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
714 auto* t = std::gmtime(&now);
716 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 static_cast<uint16_t
>(t->tm_hour),
static_cast<uint16_t
>(t->tm_min),
static_cast<long double>(t->tm_sec),
GPST);
719 std::random_device rd;
720 std::default_random_engine generator(rd());
722 std::uniform_real_distribution<double> distribution(-9.0, 9.0);
723 obs->p_acceleration = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
725 distribution = std::uniform_real_distribution<double>(-3.0, 3.0);
726 obs->p_angularRate = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
728 distribution = std::uniform_real_distribution<double>(-1.0, 1.0);
729 obs->p_magneticField = Eigen::Vector3d(distribution(generator), distribution(generator), distribution(generator));
731 distribution = std::uniform_real_distribution<double>(15.0, 25.0);
732 obs->temperature = distribution(generator);
734 LOG_INFO(
"{}: Sending Sensor data with time [{} GPST]", node->nameId(), obs->insTime.toYMDHMS(
GPST));
736 node->invokeCallbacks(node->getPinIdx(
DemoPins::Flow).value(), obs);
749 auto obs = std::make_shared<NodeData>();
754 auto obs = std::make_shared<NodeData>();
771 auto obs = std::make_shared<NodeData>();
786 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.
bool DeleteOutputPin(size_t pinIndex)
Deletes the output pin. Invalidates the pin reference given.
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.
OutputPin * CreateOutputPin(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.
@ 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.
InputPin * CreateInputPin(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.
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 DeleteInputPin(size_t pinIndex)
Deletes the input pin. Invalidates the pin reference given.
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'.
InputPin * FindInputPin(ax::NodeEditor::PinId id)
Finds the Pin for the PinId.
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.