36#include <boost/function_types/function_arity.hpp>
37#include <boost/function_types/function_type.hpp>
38#include <boost/function_types/parameter_types.hpp>
40#include <smacc2_msgs/msg/smacc_status.hpp>
46template <
typename TOrthogonal>
49 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
60 "Orthogonal %s resource is being required from some state, client or component. Found "
63 orthogonalkey.c_str());
64 ret =
dynamic_cast<TOrthogonal *
>(it->second.get());
70 ss <<
"Orthogonal not found " << orthogonalkey.c_str() << std::endl;
71 ss <<
"The existing orthogonals are the following: " << std::endl;
74 ss <<
" - " << orthogonal.first << std::endl;
77 RCLCPP_WARN_STREAM(
getLogger(), ss.str());
84template <
typename TOrthogonal>
87 std::lock_guard<std::recursive_mutex> guard(
m_mutex_);
93 auto ret = std::make_shared<TOrthogonal>();
94 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc2::ISmaccOrthogonal>(ret);
96 ret->setStateMachine(
this);
98 RCLCPP_INFO(
getLogger(),
"%s Orthogonal is created", orthogonalkey.c_str());
103 getLogger(),
"There were already one existing orthogonal of type "
104 << orthogonalkey.c_str() <<
". Skipping creation orthogonal request. ");
105 std::stringstream ss;
106 ss <<
"The existing orthogonals are the following: " << std::endl;
109 ss <<
" - " << orthogonal.first << std::endl;
111 RCLCPP_WARN_STREAM(
getLogger(), ss.str());
116template <
typename SmaccComponentType>
124 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
128 for (
auto & client : ortho.second->clients_)
130 storage = client->getComponent<SmaccComponentType>();
131 if (storage !=
nullptr)
139 getLogger(),
"component %s is required but it was not found in any orthogonal",
143 throw std::runtime_error(
"component is required but it was not found in any orthogonal");
146template <
typename SmaccComponentType>
152 getLogger(),
"component %s (named '%s') is required",
153 demangleSymbol(
typeid(SmaccComponentType).name()).c_str(), name.c_str());
154 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
158 for (
auto & client : ortho.second->clients_)
160 storage = client->getComponent<SmaccComponentType>(name);
161 if (storage !=
nullptr)
169 getLogger(),
"component %s (named '%s') is required but it was not found in any orthogonal",
170 demangleSymbol(
typeid(SmaccComponentType).name()).c_str(), name.c_str());
173 throw std::runtime_error(
"named component is required but it was not found in any orthogonal");
176template <
typename EventType>
181#define eventtypename demangleSymbol<EventType>().c_str()
189 smacc2_msgs::msg::SmaccEvent event;
190 event.event_type = evinfo.getEventTypeName();
191 event.event_source = evinfo.getEventSourceName();
192 event.event_object_tag = evinfo.getOrthogonalName();
193 event.label = evinfo.label;
208 "[ISmaccStateMachine] CURRENT STATE SCOPED EVENT DISCARDED, state is exiting/transitioning "
230template <
typename EventType>
234 RCLCPP_INFO_STREAM(
getLogger(),
"Event: " << evname);
235 auto * ev =
new EventType();
242 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
244 bool success =
false;
259 ret = boost::any_cast<T>(v.second);
263 catch (boost::bad_any_cast & ex)
265 RCLCPP_ERROR(
getLogger(),
"bad any cast: %s", ex.what());
278 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
284 std::stringstream ss;
300 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
302 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
303 std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
309 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
311 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
312 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
314 return signal.connect(
318 if (callbackCounter ==
nullptr)
320 (
object->*callback)();
322 else if (callbackCounter->acquire())
324 (
object->*callback)();
325 callbackCounter->release();
334 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
336 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
337 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
339 return signal.connect(
342 if (callbackCounter ==
nullptr)
344 return (object->*callback)(a1);
346 else if (callbackCounter->acquire())
348 (
object->*callback)(a1);
349 callbackCounter->release();
358 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
360 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
361 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
363 return signal.connect(
364 [=](
auto a1,
auto a2)
366 if (callbackCounter ==
nullptr)
368 return (object->*callback)(a1, a2);
370 else if (callbackCounter->acquire())
372 (
object->*callback)(a1, a2);
373 callbackCounter->release();
382 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
384 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
385 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
387 return signal.connect(
388 [=](
auto a1,
auto a2,
auto a3)
390 if (callbackCounter ==
nullptr)
392 return (object->*callback)(a1, a2, a3);
394 else if (callbackCounter->acquire())
396 (
object->*callback)(a1, a2, a3);
397 callbackCounter->release();
405template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
407 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object)
409 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
412 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
413 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
414 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value ||
415 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
416 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value,
417 "Only are accepted smacc types as subscribers for smacc signals");
419 typedef decltype(callback) ft;
425 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value ||
426 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
427 std::is_base_of<ISmaccOrthogonal, TSmaccObjectType>::value ||
428 std::is_base_of<ISmaccStateMachine, TSmaccObjectType>::value)
432 "[StateMachine] Long life-time SMACC signal subscription created. Subscriber is %s. Callback "
437 connection = binder.bindaux(signal, callback,
object,
nullptr);
440 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
441 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
442 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
446 "[StateMachine] Life-time constrained SMACC signal subscription created. Subscriber is %s",
449 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
456 callbackCounterSemaphore =
461 connection = binder.bindaux(signal, callback,
object, callbackCounterSemaphore);
462 callbackCounterSemaphore->addConnection(connection);
468 "[StateMachine] Connecting signal to an unknown object with unknown lifetime "
469 "behavior. An exception may occur if the object is destroyed during the execution.");
471 connection = binder.bindaux(signal, callback,
object,
nullptr);
477template <
typename StateType>
480 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
484 "[State Machine] Initializing a new state '%s' and updating current state. Getting state "
485 "meta-information. number of orthogonals: %ld",
493template <
typename StateType>
497 getLogger(),
"[%s] State OnEntry code finished.",
503 RCLCPP_DEBUG(
getLogger(),
"Orthogonal onEntry: %s.", pair.second->getName().c_str());
504 auto & orthogonal = pair.second;
507 orthogonal->onEntry();
509 catch (
const std::exception & e)
513 "[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
514 pair.second->getName().c_str(), e.what());
518 for (
auto & sr : currentState->getStateReactors())
521 RCLCPP_INFO_STREAM(
getLogger(),
"State reactor onEntry: " << srname);
526 catch (
const std::exception & e)
530 "[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception "
532 srname.c_str(), e.what());
536 for (
auto & eg : currentState->getEventGenerators())
539 RCLCPP_INFO_STREAM(
getLogger(),
"Event generator onEntry: " << egname);
544 catch (
const std::exception & e)
548 "[Event generator %s] Exception on Entry - continuing with next state reactor. Exception "
550 egname.c_str(), e.what());
555 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
561template <
typename StateType>
567 auto & orthogonal = pair.second;
568 orthogonal->runtimeConfigure();
572 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
580template <
typename StateType>
586template <
typename StateType>
591 RCLCPP_WARN_STREAM(
getLogger(),
"Exiting state: " << fullname);
593 RCLCPP_INFO_STREAM(
getLogger(),
"Notification state exit: leaving state " << state);
596 auto & orthogonal = pair.second;
599 orthogonal->onExit();
601 catch (
const std::exception & e)
605 "[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
606 pair.second->getName().c_str(), e.what());
610 for (
auto & sr : state->getStateReactors())
613 RCLCPP_INFO_STREAM(
getLogger(),
"State reactor OnExit: " << srname);
618 catch (
const std::exception & e)
622 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
624 srname.c_str(), e.what());
628 for (
auto & eg : state->getEventGenerators())
631 RCLCPP_INFO_STREAM(
getLogger(),
"Event generator OnExit: " << egname);
636 catch (
const std::exception & e)
640 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
642 egname.c_str(), e.what());
647template <
typename StateType>
655 RCLCPP_WARN_STREAM(
getLogger(),
"Exiting state: " << fullname);
657 RCLCPP_INFO_STREAM(
getLogger(),
"Notification state disposing: leaving state" << state);
660 auto & orthogonal = pair.second;
663 orthogonal->onDispose();
665 catch (
const std::exception & e)
669 "[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
670 pair.second->getName().c_str(), e.what());
674 for (
auto & sr : state->getStateReactors())
677 RCLCPP_INFO(
getLogger(),
"State reactor disposing: %s", srname);
682 catch (
const std::exception & e)
686 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
692 for (
auto & eg : state->getEventGenerators())
695 RCLCPP_INFO(
getLogger(),
"Event generator disposing: %s", egname);
700 catch (
const std::exception & e)
704 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
720 RCLCPP_WARN_STREAM(
getLogger(),
"State exit: " << fullname);
726template <
typename EventType>
744template <
typename InitialStateType>
std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > orthogonals_
std::vector< ISmaccState * > currentState_
std::recursive_mutex eventQueueMutex_
bool getGlobalSMData(std::string name, T &ret)
StateMachineInternalAction stateMachineCurrentAction
std::shared_ptr< SmaccStateInfo > currentStateInfo_
rclcpp::Node::SharedPtr getNode()
std::map< std::string, std::pair< std::function< std::string()>, boost::any > > globalData_
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType)
void setGlobalSMData(std::string name, T value)
TOrthogonal * getOrthogonal()
void buildStateMachineInfo()
void notifyOnRuntimeConfigurationFinished(StateType *state)
smacc2::SmaccSignalConnection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
std::recursive_mutex m_mutex_
void notifyOnStateExited(StateType *state)
void lockStateMachine(std::string msg)
void notifyOnStateEntryEnd(StateType *state)
void propagateEventToStateReactors(ISmaccState *st, EventType *ev)
void disconnectSmaccSignalObject(void *object)
const SmaccStateMachineInfo & getStateMachineInfo()
void unlockStateMachine(std::string msg)
int64_t getCurrentStateCounter() const
ISmaccState * getCurrentState() const
void checkStateMachineConsistence()
void notifyOnStateExiting(StateType *state)
SignalDetector * signalDetector_
std::map< void *, std::shared_ptr< CallbackCounterSemaphore > > stateCallbackConnections
rclcpp::Logger getLogger()
void notifyOnRuntimeConfigured(StateType *state)
std::shared_ptr< SmaccStateMachineInfo > stateMachineInfo_
void postEvent(EventType *ev, EventLifeTime evlifetime=EventLifeTime::ABSOLUTE)
rclcpp::Publisher< smacc2_msgs::msg::SmaccEvent >::SharedPtr eventsLogPub_
void updateStatusMessage()
void notifyOnStateEntryStart(StateType *state)
ISmaccState * getParentState()
virtual std::string getClassName()
std::vector< std::shared_ptr< StateReactor > > & getStateReactors()
void postEvent(EventType *ev)
void notifyStateExited(ISmaccState *currentState)
void notifyStateConfigured(ISmaccState *currentState)
static TypeInfo::Ptr getTypeInfoFromType()
std::enable_if< HasEventLabel< T >::value, void >::type EventLabel(std::string &label)
std::string demangleSymbol()
std::string demangledTypeName()
boost::signals2::connection SmaccSignalConnection
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)