44#include <boost/function_types/function_arity.hpp>
45#include <boost/function_types/function_type.hpp>
46#include <boost/function_types/parameter_types.hpp>
48#include <smacc2_msgs/msg/smacc_status.hpp>
54template <
typename TOrthogonal>
57 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
68 "Orthogonal %s resource is being required from some state, client or component. Found "
71 orthogonalkey.c_str());
72 ret =
dynamic_cast<TOrthogonal *
>(it->second.get());
78 ss <<
"Orthogonal not found " << orthogonalkey.c_str() << std::endl;
79 ss <<
"The existing orthogonals are the following: " << std::endl;
82 ss <<
" - " << orthogonal.first << std::endl;
85 RCLCPP_WARN_STREAM(
getLogger(), ss.str());
92template <
typename TOrthogonal>
96 std::lock_guard<std::recursive_mutex> guard(
m_mutex_);
102 auto ret = std::make_shared<TOrthogonal>();
103 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc2::ISmaccOrthogonal>(ret);
105 ret->setStateMachine(
this);
107 RCLCPP_INFO(
getLogger(),
"%s Orthogonal is created", orthogonalkey.c_str());
112 getLogger(),
"There were already one existing orthogonal of type "
113 << orthogonalkey.c_str() <<
". Skipping creation orthogonal request. ");
114 std::stringstream ss;
115 ss <<
"The existing orthogonals are the following: " << std::endl;
118 ss <<
" - " << orthogonal.first << std::endl;
120 RCLCPP_WARN_STREAM(
getLogger(), ss.str());
126template <
typename SmaccComponentType>
132 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
136 for (
auto & client : ortho.second->clients_)
138 storage = client->getComponent<SmaccComponentType>();
139 if (storage !=
nullptr)
147 getLogger(),
"component %s is required but it was not found in any orthogonal",
151 throw std::runtime_error(
"component is required but it was not found in any orthogonal");
177template <
typename EventType>
182#define eventtypename demangleSymbol<EventType>().c_str()
190 smacc2_msgs::msg::SmaccEvent event;
191 event.event_type = evinfo.getEventTypeName();
192 event.event_source = evinfo.getEventSourceName();
193 event.event_object_tag = evinfo.getOrthogonalName();
194 event.label = evinfo.label;
209 "[ISmaccStateMachine] CURRENT STATE SCOPED EVENT DISCARDED, state is exiting/transitioning "
231template <
typename EventType>
235 RCLCPP_INFO_STREAM(
getLogger(),
"Event: " << evname);
236 auto * ev =
new EventType();
243 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
245 bool success =
false;
260 ret = boost::any_cast<T>(v.second);
264 catch (boost::bad_any_cast & ex)
266 RCLCPP_ERROR(
getLogger(),
"bad any cast: %s", ex.what());
279 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
285 std::stringstream ss;
322 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
324 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
325 std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
331 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
333 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
334 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
336 return signal.connect(
340 if (callbackCounter ==
nullptr)
342 (
object->*callback)();
344 else if (callbackCounter->acquire())
346 (
object->*callback)();
347 callbackCounter->release();
356 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
358 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
359 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
361 return signal.connect(
364 if (callbackCounter ==
nullptr)
366 return (object->*callback)(a1);
368 else if (callbackCounter->acquire())
370 (
object->*callback)(a1);
371 callbackCounter->release();
380 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
382 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
383 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
385 return signal.connect(
386 [=](
auto a1,
auto a2)
388 if (callbackCounter ==
nullptr)
390 return (object->*callback)(a1, a2);
392 else if (callbackCounter->acquire())
394 (
object->*callback)(a1, a2);
395 callbackCounter->release();
404 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
406 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
407 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
409 return signal.connect(
410 [=](
auto a1,
auto a2,
auto a3)
412 if (callbackCounter ==
nullptr)
414 return (object->*callback)(a1, a2, a3);
416 else if (callbackCounter->acquire())
418 (
object->*callback)(a1, a2, a3);
419 callbackCounter->release();
427template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
429 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object)
431 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
434 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
435 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
436 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value ||
437 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
438 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value,
439 "Only are accepted smacc types as subscribers for smacc signals");
441 typedef decltype(callback) ft;
443 boost::signals2::connection connection;
447 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value ||
448 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
449 std::is_base_of<ISmaccOrthogonal, TSmaccObjectType>::value ||
450 std::is_base_of<ISmaccStateMachine, TSmaccObjectType>::value)
454 "[StateMachine] Long life-time SMACC signal subscription created. Subscriber is %s. Callback "
459 connection = binder.bindaux(signal, callback,
object,
nullptr);
462 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
463 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
464 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
468 "[StateMachine] Life-time constrained SMACC signal subscription created. Subscriber is %s",
471 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
478 callbackCounterSemaphore =
483 connection = binder.bindaux(signal, callback,
object, callbackCounterSemaphore);
484 callbackCounterSemaphore->addConnection(connection);
490 "[StateMachine] Connecting signal to an unknown object with unknown lifetime "
491 "behavior. An exception may occur if the object is destroyed during the execution.");
493 connection = binder.bindaux(signal, callback,
object,
nullptr);
499template <
typename StateType>
502 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
506 "[State Machine] Initializing a new state '%s' and updating current state. Getting state "
507 "meta-information. number of orthogonals: %ld",
515template <
typename StateType>
519 getLogger(),
"[%s] State OnEntry code finished.",
525 RCLCPP_DEBUG(
getLogger(),
"Orthogonal onEntry: %s.", pair.second->getName().c_str());
526 auto & orthogonal = pair.second;
529 orthogonal->onEntry();
531 catch (
const std::exception & e)
535 "[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
536 pair.second->getName().c_str(), e.what());
540 for (
auto & sr : currentState->getStateReactors())
543 RCLCPP_INFO_STREAM(
getLogger(),
"State reactor onEntry: " << srname);
548 catch (
const std::exception & e)
552 "[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception "
554 srname.c_str(), e.what());
558 for (
auto & eg : currentState->getEventGenerators())
561 RCLCPP_INFO_STREAM(
getLogger(),
"Event generator onEntry: " << egname);
566 catch (
const std::exception & e)
570 "[Event generator %s] Exception on Entry - continuing with next state reactor. Exception "
572 egname.c_str(), e.what());
577 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
583template <
typename StateType>
589 auto & orthogonal = pair.second;
590 orthogonal->runtimeConfigure();
594 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
602template <
typename StateType>
608template <
typename StateType>
613 RCLCPP_WARN_STREAM(
getLogger(),
"Exiting state: " << fullname);
616 RCLCPP_INFO_STREAM(
getLogger(),
"Notification state exit: leaving state " << state);
619 auto & orthogonal = pair.second;
622 orthogonal->onExit();
624 catch (
const std::exception & e)
628 "[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
629 pair.second->getName().c_str(), e.what());
633 for (
auto & sr : state->getStateReactors())
636 RCLCPP_INFO_STREAM(
getLogger(),
"State reactor OnExit: " << srname);
641 catch (
const std::exception & e)
645 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
647 srname.c_str(), e.what());
651 for (
auto & eg : state->getEventGenerators())
654 RCLCPP_INFO_STREAM(
getLogger(),
"Event generator OnExit: " << egname);
659 catch (
const std::exception & e)
663 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
665 egname.c_str(), e.what());
670template <
typename StateType>
678 RCLCPP_WARN_STREAM(
getLogger(),
"Exiting state: " << fullname);
680 RCLCPP_INFO_STREAM(
getLogger(),
"Notification state disposing: leaving state" << state);
683 auto & orthogonal = pair.second;
686 orthogonal->onDispose();
688 catch (
const std::exception & e)
692 "[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
693 pair.second->getName().c_str(), e.what());
697 for (
auto & sr : state->getStateReactors())
700 RCLCPP_INFO(
getLogger(),
"State reactor disposing: %s", srname);
705 catch (
const std::exception & e)
709 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
715 for (
auto & eg : state->getEventGenerators())
718 RCLCPP_INFO(
getLogger(),
"Event generator disposing: %s", egname);
723 catch (
const std::exception & e)
727 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
737 RCLCPP_WARN_STREAM(
getLogger(),
"State exit: " << fullname);
743template <
typename EventType>
761template <
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)
boost::signals2::connection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
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 notifyOnStateExitting(StateType *state)
void setGlobalSMData(std::string name, T value)
TOrthogonal * getOrthogonal()
void buildStateMachineInfo()
void notifyOnRuntimeConfigurationFinished(StateType *state)
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
void requiresComponent(SmaccComponentType *&storage, bool throwsExceptionIfNotExist=false)
ISmaccState * getCurrentState() const
void checkStateMachineConsistence()
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()
void TRACEPOINT(spinOnce)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)