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_);
59 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
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_);
97 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
101 auto ret = std::make_shared<TOrthogonal>();
102 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc2::ISmaccOrthogonal>(ret);
104 ret->setStateMachine(
this);
106 RCLCPP_INFO(
getLogger(),
"%s Orthogonal is created", orthogonalkey.c_str());
111 getLogger(),
"There were already one existing orthogonal of type "
112 << orthogonalkey.c_str() <<
". Skipping creation orthogonal request. ");
113 std::stringstream ss;
114 ss <<
"The existing orthogonals are the following: " << std::endl;
117 ss <<
" - " << orthogonal.first << std::endl;
119 RCLCPP_WARN_STREAM(
getLogger(), ss.str());
125template <
typename SmaccComponentType>
131 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
135 for (
auto & client : ortho.second->clients_)
137 storage = client->getComponent<SmaccComponentType>();
138 if (storage !=
nullptr)
146 getLogger(),
"component %s is required but it was not found in any orthogonal",
150 throw std::runtime_error(
"component is required but it was not found in any orthogonal");
176template <
typename EventType>
181#define eventtypename demangleSymbol<EventType>().c_str()
192 "[ISmaccStateMachine] CURRENT STATE SCOPED EVENT DISCARDED, state is exiting/transitioning "
214template <
typename EventType>
217 auto evname = smacc2::introspection::demangleSymbol<EventType>();
219 auto * ev =
new EventType();
226 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
228 bool success =
false;
243 ret = boost::any_cast<T>(v.second);
247 catch (boost::bad_any_cast & ex)
249 RCLCPP_ERROR(
getLogger(),
"bad any cast: %s", ex.what());
262 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
268 std::stringstream ss;
279template <
typename StateField,
typename BehaviorType>
282 std::string stateFieldName =
demangleSymbol(
typeid(StateField).name());
283 std::string behaviorType =
demangleSymbol(
typeid(BehaviorType).name());
285 getLogger(),
"Mapping state field '%s' to stateReactor '%s'", stateFieldName.c_str(),
286 behaviorType.c_str());
292 BehaviorType * behavior;
305 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
307 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
308 std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
314 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
316 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
317 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
319 return signal.connect(
323 if (callbackCounter ==
nullptr)
325 (
object->*callback)();
327 else if (callbackCounter->acquire())
329 (
object->*callback)();
330 callbackCounter->release();
339 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
341 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
342 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
344 return signal.connect(
347 if (callbackCounter ==
nullptr)
349 return (object->*callback)(a1);
351 else if (callbackCounter->acquire())
353 (object->*callback)(a1);
354 callbackCounter->release();
363 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
365 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
366 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
368 return signal.connect(
369 [=](
auto a1,
auto a2)
371 if (callbackCounter ==
nullptr)
373 return (object->*callback)(a1, a2);
375 else if (callbackCounter->acquire())
377 (object->*callback)(a1, a2);
378 callbackCounter->release();
387 template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
389 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object,
390 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
392 return signal.connect(
393 [=](
auto a1,
auto a2,
auto a3)
395 if (callbackCounter ==
nullptr)
397 return (object->*callback)(a1, a2, a3);
399 else if (callbackCounter->acquire())
401 (object->*callback)(a1, a2, a3);
402 callbackCounter->release();
410template <
typename TSmaccSignal,
typename TMemberFunctionPrototype,
typename TSmaccObjectType>
412 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType *
object)
414 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
417 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
418 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
419 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value ||
420 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
421 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value,
422 "Only are accepted smacc types as subscribers for smacc signals");
424 typedef decltype(callback) ft;
426 boost::signals2::connection connection;
430 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value ||
431 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
432 std::is_base_of<ISmaccOrthogonal, TSmaccObjectType>::value ||
433 std::is_base_of<ISmaccStateMachine, TSmaccObjectType>::value)
437 "[StateMachine] long life-time smacc signal subscription created. Subscriber is %s. Callback "
439 demangledTypeName<TSmaccObjectType>().c_str(),
442 connection = binder.bindaux(signal, callback,
object,
nullptr);
446 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
447 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
448 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
452 "[StateMachine] life-time constrained smacc signal subscription created. Subscriber is %s",
453 demangledTypeName<TSmaccObjectType>().c_str());
455 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
462 callbackCounterSemaphore =
463 std::make_shared<CallbackCounterSemaphore>(demangledTypeName<TSmaccObjectType>().c_str());
467 connection = binder.bindaux(signal, callback,
object, callbackCounterSemaphore);
468 callbackCounterSemaphore->addConnection(connection);
474 "[StateMachine] connecting signal to an unknown object with life-time unknown "
475 "behavior. It might provoke "
476 "an exception if the object is destroyed during the execution.");
478 connection = binder.bindaux(signal, callback,
object,
nullptr);
484template <
typename StateType>
487 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
491 "[State Machne] Initializing a new state '%s' and updating current state. Getting state "
492 "meta-information. number of orthogonals: %ld",
500template <
typename StateType>
504 getLogger(),
"[%s] State OnEntry code finished",
510 RCLCPP_DEBUG(
getLogger(),
"ortho onentry: %s", pair.second->getName().c_str());
511 auto & orthogonal = pair.second;
514 orthogonal->onEntry();
516 catch (
const std::exception & e)
520 "[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
521 pair.second->getName().c_str(), e.what());
525 for (
auto & sr : currentState->getStateReactors())
528 RCLCPP_INFO_STREAM(
getLogger(),
"state reactor onEntry: " << srname);
533 catch (
const std::exception & e)
537 "[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception "
539 srname.c_str(), e.what());
543 for (
auto & eg : currentState->getEventGenerators())
546 RCLCPP_INFO_STREAM(
getLogger(),
"event generator onEntry: " << egname);
551 catch (
const std::exception & e)
555 "[Event generator %s] Exception on Entry - continuing with next state reactor. Exception "
557 egname.c_str(), e.what());
562 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
568template <
typename StateType>
574 auto & orthogonal = pair.second;
575 orthogonal->runtimeConfigure();
579 std::lock_guard<std::recursive_mutex> lock(
m_mutex_);
587template <
typename StateType>
593template <
typename StateType>
598 RCLCPP_WARN_STREAM(
getLogger(),
"exiting state: " << fullname);
601 RCLCPP_INFO_STREAM(
getLogger(),
"Notification State Exit: leaving state " << state);
604 auto & orthogonal = pair.second;
607 orthogonal->onExit();
609 catch (
const std::exception & e)
613 "[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
614 pair.second->getName().c_str(), e.what());
618 for (
auto & sr : state->getStateReactors())
621 RCLCPP_INFO_STREAM(
getLogger(),
"state reactor OnExit: " << srname);
626 catch (
const std::exception & e)
630 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
632 srname.c_str(), e.what());
636 for (
auto & eg : state->getEventGenerators())
639 RCLCPP_INFO_STREAM(
getLogger(),
"event generator OnExit: " << egname);
644 catch (
const std::exception & e)
648 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
650 egname.c_str(), e.what());
655template <
typename StateType>
663 RCLCPP_WARN_STREAM(
getLogger(),
"exiting state: " << fullname);
665 RCLCPP_INFO_STREAM(
getLogger(),
"Notification State Disposing: leaving state" << state);
668 auto & orthogonal = pair.second;
671 orthogonal->onDispose();
673 catch (
const std::exception & e)
677 "[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
678 pair.second->getName().c_str(), e.what());
682 for (
auto & sr : state->getStateReactors())
685 RCLCPP_INFO(
getLogger(),
"state reactor disposing: %s", srname);
690 catch (
const std::exception & e)
694 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
700 for (
auto & eg : state->getEventGenerators())
703 RCLCPP_INFO(
getLogger(),
"state reactor disposing: %s", egname);
708 catch (
const std::exception & e)
712 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
722 RCLCPP_WARN_STREAM(
getLogger(),
"state exit: " << fullname);
728template <
typename EventType>
732 getLogger(),
"PROPAGATING EVENT [%s] TO SRs [%s]: ", demangleSymbol<EventType>().c_str(),
746template <
typename InitialStateType>
std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > orthogonals_
std::vector< ISmaccState * > currentState_
std::recursive_mutex eventQueueMutex_
uint64_t stateSeqCounter_
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()
uint64_t getCurrentStateCounter() const
void unlockStateMachine(std::string msg)
void requiresComponent(SmaccComponentType *&storage, bool throwsExceptionIfNotExist=false)
ISmaccState * getCurrentState() const
void checkStateMachineConsistence()
SignalDetector * signalDetector_
std::vector< boost::signals2::scoped_connection > longLivedSignalConnections_
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)
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)
std::string demangleSymbol()
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)