Go to the documentation of this file.
22 #ifndef FUNCTIONAL_NODE_H
23 #define FUNCTIONAL_NODE_H
74 { _f2fEdges[i_port] = address; }
88 { _f2fEdges.clear(); }
100 for (
auto& [in_port, address]: _f2fEdges) {
101 std::string node_id, out_port;
103 createF2FEdge(in_port, node_id, out_port);
110 void createF2FEdge(
const std::string & in_port,
const std::string & node_id,
const std::string & out_port)
112 std::string address =
"/" + node_id +
"/" + out_port;
118 "'. A Functional node with name '" + node_id +
"' could not be found in the computational graph. Be sure that the edge"
119 " address is correctly formatted and the connected node exists.");
125 "'. Functional node '" + node_id +
"' doesn't have a declared output '"+ out_port +
"'. Be sure that the edge"
126 " address is correctly formatted and the specified output exists.");
133 std::map<std::string, std::string> _f2fEdges;
142 F2FEdge(
const std::string &keyword,
const std::string &address) :
152 boost::python::object
pySetup(
const boost::python::object& obj)
156 std::shared_ptr<FunctionalNodeBase> f = boost::python::extract<std::shared_ptr<FunctionalNodeBase> >(
160 catch (
const boost::python::error_already_set&) {
161 std::string error_msg =
"An error occurred while creating the F2FEdge '" +
_address +
162 "'. Check that Functional Node definition is correct";
178 template<
typename,
typename>
189 template<
typename... INPUT_TYPES,
typename... OUTPUT_TYPES>
195 template <std::
size_t N>
199 template <std::
size_t N>
202 using inputs_t = std::tuple<
const INPUT_TYPES* ...>;
209 using params_t = decltype(std::tuple_cat(std::declval<inputs_t>(), std::declval<outputs_t>()));
217 template <std::
size_t N,
class T_IN,
class T_OUT>
220 if constexpr (N >=
sizeof...(INPUT_TYPES)) {
222 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register input with index " << N <<
223 ", which is greater than the number of inputs in this node: " <<
sizeof...(INPUT_TYPES);
226 else if constexpr (!std::is_same_v<
input_n_t<N>, T_OUT>) {
228 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register input with index " << N <<
" and type '" <<
typeid(T_OUT).name() <<
229 "', but index " << N <<
" is of type " <<
typeid(
input_n_t<N>).name();
232 else if(_inputPorts.at(N)) {
234 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register input with index " << N <<
", but index "
235 << N <<
" is already registered.";
239 using std::placeholders::_1;
240 std::function<void(
const T_OUT*)> f = std::bind( &FunctionalNode::newInputCallback<N, T_OUT>,
this, _1 );
242 _inputPorts.at(N).reset(
port);
252 if (idx >= _inputPorts.size()) {
254 s <<
"In Functional node '" << this->id() <<
"'. Attempt to get input with index " << idx <<
255 ", which is greater than the number of inputs in this node: " << _inputPorts.size() - 1;
259 return _inputPorts.at(idx).get();
267 for(
auto& e : _inputPorts)
268 if (e && e->id() ==
id)
272 s <<
"In Functional node '" << this->id() <<
"'. Input with id '" <<
id <<
"' not found";
281 template <std::
size_t N,
class T>
284 if constexpr (N >=
sizeof...(OUTPUT_TYPES)) {
286 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register output with index " << N <<
287 ", which is greater than the number of outputs in this node: " <<
sizeof...(OUTPUT_TYPES);
292 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register output with index " << N <<
" and type '"
293 <<
typeid(T).name() <<
"', but index " << N <<
" is of type " <<
typeid(
output_n_t<N>).name();
296 else if(std::get<N>(_outputPorts)) {
298 s <<
"In Functional node '" << this->id() <<
"'. Attempt to register output with index " << N <<
", but index "
299 << N <<
" is already registered.";
304 std::get<N>(_outputPorts).reset(
port);
312 template <std::
size_t N>
315 if constexpr (N >=
sizeof...(OUTPUT_TYPES)) {
317 s <<
"In Functional node '" << this->id() <<
"'. Attempt to get or register output with index " << N <<
318 ", which is greater than the number of outputs in this node: " <<
sizeof...(OUTPUT_TYPES);
322 return std::get<N>(_outputPorts).get();
329 {
return getOutputByIdTuple(
id); }
331 template <std::
size_t N = 0>
334 if constexpr (N <
sizeof...(OUTPUT_TYPES)) {
335 if (std::get<N>(_outputPorts) && std::get<N>(_outputPorts)->
id() ==
id)
336 return std::get<N>(_outputPorts).get();
338 return getOutputByIdTuple<N+1>(
id);
342 s <<
"In Functional node '" << this->id() <<
"'. Attempt to get output with id '" <<
id <<
"', but it is not registered.";
354 { createEdgeTuple(port_id, out_port); }
356 template <std::
size_t N = 0>
359 std::stringstream error_msg;
360 error_msg <<
"In Functional node '" << this->id() <<
"'. Error While creating edge to port '" << port_id <<
"'. ";
362 if constexpr (N <
sizeof...(INPUT_TYPES)) {
363 if (_inputPorts.at(N) && _inputPorts.at(N)->id() == port_id) {
372 error_msg <<
"The port T_IN and T_OUT types are not equal. Currently this is the only supported case.";
376 error_msg <<
"Attempt to connect to port '" << out_port->
id() <<
"', but they are of different types.";
384 createEdgeTuple<N+1>(port_id, out_port);
387 error_msg <<
"This port is not registered in the node.";
397 if(boundInputPorts() < std::tuple_size_v<inputs_t>) {
399 s <<
"Functional node " << this->id() <<
" has been declared with " << std::tuple_size_v<inputs_t> <<
400 " inputs, but only " << boundInputPorts() <<
" are bounded" << std::endl;
404 if(boundOutputPorts() < std::tuple_size_v<outputs_t>) {
406 s <<
"Functional node " << this->id() <<
" has been declared with " << std::tuple_size_v<outputs_t>
408 " outputs, but only " << boundOutputPorts() <<
" are bounded" << std::endl;
420 if(_function(_params))
439 template<
size_t N = 0>
442 if constexpr ( N <
sizeof...(INPUT_TYPES)) {
443 std::get<N>(_params) =
nullptr;
451 template <
size_t N,
class T>
454 std::get<N>(_params) = value;
455 this->_hasNew = this->_hasNew || value !=
nullptr;
461 template<
size_t N = 0>
464 if constexpr ( N <
sizeof...(OUTPUT_TYPES)) {
465 if (std::get<N>(_outputPorts))
466 std::get<N>(_outputPorts)->publish(&std::get<
sizeof...(INPUT_TYPES) + N>(_params));
475 for(
auto p : _inputPorts)
481 template<
size_t N = 0>
484 if constexpr (N <
sizeof...(OUTPUT_TYPES)) {
485 size_t n = std::get<N>(_outputPorts) ? 1 : 0;
486 return n + boundOutputPorts<N+1>();
498 friend class ComputationalNodes_FUNCTIONAL_NODE_Test;
499 friend class ComputationalNodes_FUNCTIONAL_NODE_FACTORY_Test;
500 friend class ComputationalGraphPythonNodes_PYTHON_FUNCTIONAL_NODE_Test;
501 friend class ComputationalGraphPythonNodes_PYTHON_DECORATORS_BASIC_Test;
506 std::array< std::shared_ptr<Port>,
sizeof...(INPUT_TYPES) > _inputPorts;
508 std::tuple< std::shared_ptr< OutputPort<OUTPUT_TYPES> > ...> _outputPorts;
510 bool _hasNew =
false;
514 #endif //FUNCTIONAL_NODE_H
void registerEdge(OutputPort< T_IN > *source, InputPort< T_IN, T_OUT > *target)
Connects an InputPort to an Output port and registers an edge in the graph between their parent nodes...
Definition: computational_graph_manager.h:107
std::string _address
Definition: functional_node.h:174
std::tuple< OUTPUT_TYPES ... > outputs_t
Definition: functional_node.h:203
size_t boundInputPorts()
Definition: functional_node.h:472
void clearEdgeRequests()
Definition: functional_node.h:87
std::tuple< const INPUT_TYPES *... > inputs_t
Definition: functional_node.h:202
F2FEdge(const std::string &keyword, const std::string &address)
Definition: functional_node.h:142
ExecutionPolicy
Possible execution policies for this node.
Definition: computational_node_policies.h:41
Base class implementing a port in the computational graph.
Definition: port.h:30
Creates an instance of FunctionalNode with the right template given a function signature.
Definition: functional_node_factory.h:47
void newInputCallback(const T *value)
Process incoming new msg.
Definition: functional_node.h:452
typename std::tuple_element< N, std::tuple< INPUT_TYPES... > >::type input_n_t
Type of the nth element in INPUT_TYPES parameter pack.
Definition: functional_node.h:196
friend class ComputationalGraphPythonNodes_F2F_EDGES_Test
Definition: functional_node.h:90
const std::string & id()
Returns the port 'id'.
Definition: port.h:47
FunctionalNodeBase(const std::string &id)
Definition: functional_node.h:45
FunctionalNode(const std::string &id, std::function< bool(params_t &)> f, FunctionalNodePolicies::ExecutionPolicy policy=FunctionalNodePolicies::ExecutionPolicy::ON_NEW_INPUT)
Constructor.
Definition: functional_node.h:430
virtual Port * getInputById(const std::string &)
Returns an InputPort by id.
Definition: functional_node.h:52
size_t boundOutputPorts()
Definition: functional_node.h:482
Port * getInputByIndex(size_t idx)
Returns an InputPort by index.
Definition: functional_node.h:250
type
Definition: python_grpc_engine.py:63
Helper class used to implement a F2FEdge Python decorator.
Definition: functional_node.h:139
Definition: functional_node.h:179
void graphLoadedCB() override
Function called by the Computational Graph to nodes that the graph has been completely loaded.
Definition: functional_node.h:78
const std::string & id() const
Returns the node 'id'.
Definition: computational_node.h:57
static void info(const FormatString &fmt, const Args &...args)
NRP logging function with message formatting for info level.
Definition: nrp_logger.h:138
Port * getOutputByIdTuple(const std::string &id)
Definition: functional_node.h:332
void createEdgeTuple(const std::string &port_id, Port *out_port)
Definition: functional_node.h:357
void configure() override
Configures the node making it ready to execute 'compute'.
Definition: functional_node.h:61
virtual Port * getOutputById(const std::string &)
Returns an OutputPort by id.
Definition: functional_node.h:57
Non-abstract, non-templated base class for the FunctionalNode class.
Definition: functional_node.h:42
static ComputationalGraphManager & getInstance()
Get singleton instance of ComputationalGraphManager.
Definition: computational_graph_manager.cpp:31
@ ON_NEW_INPUT
Definition: computational_node_policies.h:43
ComputationalNode * getNode(const std::string &id)
Retrieve a node from the graph as a pointer.
Definition: computational_graph_manager.h:95
static std::pair< std::string, std::string > parseNodeAddress(const std::string &address, bool hasPort=true)
Parses a computational node address returning the node id and the port (if any) contained in the addr...
Definition: computational_node.h:106
virtual void createEdge(const std::string &, Port *)
Create an edge in the graph between this node 'port_id' input port and o_port.
Definition: functional_node.h:84
@ ALWAYS
Definition: computational_node_policies.h:42
void configure() override
Configure. Print warnings if node is not fully connected.
Definition: functional_node.h:395
std::function< bool(params_t &)> _function
function performing main computation in this node. It sets the output part of _params from its input ...
Definition: functional_node.h:495
static EXCEPTION logCreate(LOG_EXCEPTION_T &exception, const std::string &msg, NRPLogger::spdlog_out_fcn_t spdlogCall=NRPLogger::critical)
Definition: nrp_exceptions.h:73
void createEdge(const std::string &port_id, Port *out_port) override
Create an edge in the graph between this node 'port_id' input port and o_port.
Definition: functional_node.h:353
boost::python::object pySetup(const boost::python::object &obj)
call function in the decorator
Definition: functional_node.h:152
decltype(std::tuple_cat(std::declval< inputs_t >(), std::declval< outputs_t >())) params_t
Type representing the argument of _function.
Definition: functional_node.h:209
Implementation of an output port in the computation graph.
Definition: output_port.h:36
void registerF2FEdge(const std::string &i_port, const std::string &address)
Request the registration of an edge between an output port in another functional node an i_port input...
Definition: functional_node.h:73
@ Functional
Definition: computational_node.h:38
void compute() override final
Compute. Execute '_function' and send its outputs out.
Definition: functional_node.h:416
port
Definition: python_json_engine.py:197
Port * getOutputByIndex()
Returns an OutputPort by index.
Definition: functional_node.h:313
Port * getInputById(const std::string &id) override
Returns an InputPort by id.
Definition: functional_node.h:265
void initInputs()
Init all inputs to a nullptr.
Definition: functional_node.h:440
void compute() override
Requests the node to execute its computation.
Definition: functional_node.h:62
std::string _keyword
Definition: functional_node.h:173
params_t _params
function performing main computation in this node
Definition: functional_node.h:493
void sendOutputs()
Sends all outputs through connected to ports.
Definition: functional_node.h:462
OutputPort< T > * registerOutput(const std::string &id)
Creates an OutputPort and connect it to an output specified by N. Returns the created port.
Definition: functional_node.h:282
typename std::tuple_element< N, std::tuple< OUTPUT_TYPES... > >::type output_n_t
Type of the nth element in OUTPUT_TYPES parameter pack.
Definition: functional_node.h:200
Port * getOutputById(const std::string &id) override
Returns an OutputPort by id.
Definition: functional_node.h:328
Base class implementing a node in the computational graph.
Definition: computational_node.h:31
InputPort< T_IN, T_OUT > * registerInput(const std::string &id)
Creates an InputPort and connect it to an input specified by N. Returns the created port.
Definition: functional_node.h:218