SMACC2
Loading...
Searching...
No Matches
smacc_state_machine_impl.hpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/**************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 **************************************************************************************************/
20
21#pragma once
22
23#include <memory>
24#include <sstream>
25#include <string>
26
35
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>
41
42namespace smacc2
43{
44using namespace smacc2::introspection;
45
46template <typename TOrthogonal>
48{
49 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
50
51 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
52 TOrthogonal * ret;
53
54 auto it = orthogonals_.find(orthogonalkey);
55
56 if (it != orthogonals_.end())
57 {
58 RCLCPP_DEBUG(
59 getLogger(),
60 "Orthogonal %s resource is being required from some state, client or component. Found "
61 "resource in "
62 "cache.",
63 orthogonalkey.c_str());
64 ret = dynamic_cast<TOrthogonal *>(it->second.get());
65 return ret;
66 }
67 else
68 {
69 std::stringstream ss;
70 ss << "Orthogonal not found " << orthogonalkey.c_str() << std::endl;
71 ss << "The existing orthogonals are the following: " << std::endl;
72 for (auto & orthogonal : orthogonals_)
73 {
74 ss << " - " << orthogonal.first << std::endl;
75 }
76
77 RCLCPP_WARN_STREAM(getLogger(), ss.str());
78
79 return nullptr;
80 }
81}
82
83//-------------------------------------------------------------------------------------------------------
84template <typename TOrthogonal>
86{
87 std::lock_guard<std::recursive_mutex> guard(m_mutex_);
88
89 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
90
91 if (orthogonals_.count(orthogonalkey) == 0)
92 {
93 auto ret = std::make_shared<TOrthogonal>();
94 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc2::ISmaccOrthogonal>(ret);
95
96 ret->setStateMachine(this);
97
98 RCLCPP_INFO(getLogger(), "%s Orthogonal is created", orthogonalkey.c_str());
99 }
100 else
101 {
102 RCLCPP_WARN_STREAM(
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;
107 for (auto & orthogonal : orthogonals_)
108 {
109 ss << " - " << orthogonal.first << std::endl;
110 }
111 RCLCPP_WARN_STREAM(getLogger(), ss.str());
112 }
113}
114
115//-------------------------------------------------------------------------------------------------------
116template <typename SmaccComponentType>
118 SmaccComponentType *& storage, ComponentRequirement requirementType)
119{
120 bool throwsException = requirementType == ComponentRequirement::HARD;
121 RCLCPP_DEBUG(
122 getLogger(), "component %s is required",
123 demangleSymbol(typeid(SmaccComponentType).name()).c_str());
124 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
125
126 for (auto ortho : this->orthogonals_)
127 {
128 for (auto & client : ortho.second->clients_)
129 {
130 storage = client->getComponent<SmaccComponentType>();
131 if (storage != nullptr)
132 {
133 return;
134 }
135 }
136 }
137
138 RCLCPP_WARN(
139 getLogger(), "component %s is required but it was not found in any orthogonal",
140 demangleSymbol(typeid(SmaccComponentType).name()).c_str());
141
142 if (throwsException)
143 throw std::runtime_error("component is required but it was not found in any orthogonal");
144}
145//-------------------------------------------------------------------------------------------------------
146template <typename SmaccComponentType>
148 std::string name, SmaccComponentType *& storage, ComponentRequirement requirementType)
149{
150 bool throwsException = requirementType == ComponentRequirement::HARD;
151 RCLCPP_DEBUG(
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_);
155
156 for (auto ortho : this->orthogonals_)
157 {
158 for (auto & client : ortho.second->clients_)
159 {
160 storage = client->getComponent<SmaccComponentType>(name);
161 if (storage != nullptr)
162 {
163 return;
164 }
165 }
166 }
167
168 RCLCPP_WARN(
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());
171
172 if (throwsException)
173 throw std::runtime_error("named component is required but it was not found in any orthogonal");
174}
175//-------------------------------------------------------------------------------------------------------
176template <typename EventType>
177void ISmaccStateMachine::postEvent(EventType * ev, EventLifeTime evlifetime)
178{
179 std::lock_guard<std::recursive_mutex> guard(eventQueueMutex_);
180
181#define eventtypename demangleSymbol<EventType>().c_str()
182
183 TRACETOOLS_TRACEPOINT(smacc2_event, eventtypename);
184
185 {
187 EventLabel<EventType>(evinfo.label);
188
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;
194
195 if (this->eventsLogPub_)
196 {
197 this->eventsLogPub_->publish(event);
198 }
199 }
200
201 if (
202 evlifetime == EventLifeTime::CURRENT_STATE &&
205 {
206 RCLCPP_WARN_STREAM(
207 getLogger(),
208 "[ISmaccStateMachine] CURRENT STATE SCOPED EVENT DISCARDED, state is exiting/transitioning "
209 << eventtypename);
210 return;
211 // in this case we may lose/skip events, if this is not right for some cases we should create a
212 // queue to lock the events during the transitions. This issues appeared when a client
213 // asyncbehavior was posting an event meanwhile we were doing the transition, but the main
214 // thread was waiting for its correct finalization (with thread.join)
215 }
216
217 // when a postting event is requested by any component, client, or client behavior
218 // we reach this place. Now, we propagate the events to all the state state reactors to generate
219 // some more events
220
221 RCLCPP_DEBUG_STREAM(getLogger(), "[PostEvent entry point] " << eventtypename);
222 if (!currentState_.empty())
223 {
225 }
226
227 this->signalDetector_->postEvent(ev);
228}
229
230template <typename EventType>
232{
234 RCLCPP_INFO_STREAM(getLogger(), "Event: " << evname);
235 auto * ev = new EventType();
236 this->postEvent(ev, evlifetime);
237}
238
239template <typename T>
240bool ISmaccStateMachine::getGlobalSMData(std::string name, T & ret)
241{
242 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
243 // RCLCPP_WARN(getLogger(),"get SM Data lock acquire");
244 bool success = false;
245
246 if (!globalData_.count(name))
247 {
248 // RCLCPP_WARN(getLogger(),"get SM Data - data do not exist");
249 success = false;
250 }
251 else
252 {
253 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. accessing");
254 try
255 {
256 auto & v = globalData_[name];
257
258 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. any cast");
259 ret = boost::any_cast<T>(v.second);
260 success = true;
261 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. success");
262 }
263 catch (boost::bad_any_cast & ex)
264 {
265 RCLCPP_ERROR(getLogger(), "bad any cast: %s", ex.what());
266 success = false;
267 }
268 }
269
270 // RCLCPP_WARN(getLogger(),"get SM Data lock release");
271 return success;
272}
273
274template <typename T>
275void ISmaccStateMachine::setGlobalSMData(std::string name, T value)
276{
277 {
278 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
279 // RCLCPP_WARN(getLogger(),"set SM Data lock acquire");
280
281 globalData_[name] = {
282 [this, name]()
283 {
284 std::stringstream ss;
285 auto val = any_cast<T>(globalData_[name].second);
286 ss << val;
287 return ss.str();
288 },
289 value};
290 }
291
292 this->updateStatusMessage();
293}
294
295namespace utils
296{
297template <int arity>
298struct Bind
299{
300 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
302 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
303 std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
304};
305
306template <>
307struct Bind<1>
308{
309 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
311 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
312 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
313 {
314 return signal.connect(
315
316 [=]()
317 {
318 if (callbackCounter == nullptr)
319 {
320 (object->*callback)();
321 }
322 else if (callbackCounter->acquire())
323 {
324 (object->*callback)();
325 callbackCounter->release();
326 }
327 });
328 }
329};
330
331template <>
332struct Bind<2>
333{
334 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
336 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
337 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
338 {
339 return signal.connect(
340 [=](auto a1)
341 {
342 if (callbackCounter == nullptr)
343 {
344 return (object->*callback)(a1);
345 }
346 else if (callbackCounter->acquire())
347 {
348 (object->*callback)(a1);
349 callbackCounter->release();
350 }
351 });
352 }
353};
354
355template <>
356struct Bind<3>
357{
358 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
360 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
361 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
362 {
363 return signal.connect(
364 [=](auto a1, auto a2)
365 {
366 if (callbackCounter == nullptr)
367 {
368 return (object->*callback)(a1, a2);
369 }
370 else if (callbackCounter->acquire())
371 {
372 (object->*callback)(a1, a2);
373 callbackCounter->release();
374 }
375 });
376 }
377};
378
379template <>
380struct Bind<4>
381{
382 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
384 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
385 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
386 {
387 return signal.connect(
388 [=](auto a1, auto a2, auto a3)
389 {
390 if (callbackCounter == nullptr)
391 {
392 return (object->*callback)(a1, a2, a3);
393 }
394 else if (callbackCounter->acquire())
395 {
396 (object->*callback)(a1, a2, a3);
397 callbackCounter->release();
398 }
399 });
400 }
401};
402} // namespace utils
403using namespace smacc2::utils;
404
405template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
407 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object)
408{
409 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
410
411 static_assert(
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");
418
419 typedef decltype(callback) ft;
422
423 // long life-time objects
424 if (
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)
429 {
430 RCLCPP_INFO(
431 getLogger(),
432 "[StateMachine] Long life-time SMACC signal subscription created. Subscriber is %s. Callback "
433 "is: %s",
435 demangleSymbol(typeid(callback).name()).c_str());
436
437 connection = binder.bindaux(signal, callback, object, nullptr);
438 }
439 else if (
440 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
441 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
442 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
443 {
444 RCLCPP_INFO(
445 getLogger(),
446 "[StateMachine] Life-time constrained SMACC signal subscription created. Subscriber is %s",
448
449 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
450 if (stateCallbackConnections.count(object))
451 {
452 callbackCounterSemaphore = stateCallbackConnections[object];
453 }
454 else
455 {
456 callbackCounterSemaphore =
457 std::make_shared<CallbackCounterSemaphore>(demangledTypeName<TSmaccObjectType>().c_str());
458 stateCallbackConnections[object] = callbackCounterSemaphore;
459 }
460
461 connection = binder.bindaux(signal, callback, object, callbackCounterSemaphore);
462 callbackCounterSemaphore->addConnection(connection);
463 }
464 else // state life-time objects
465 {
466 RCLCPP_WARN(
467 getLogger(),
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.");
470
471 connection = binder.bindaux(signal, callback, object, nullptr);
472 }
473
474 return connection;
475}
476
477template <typename StateType>
479{
480 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
481
482 RCLCPP_DEBUG(
483 getLogger(),
484 "[State Machine] Initializing a new state '%s' and updating current state. Getting state "
485 "meta-information. number of orthogonals: %ld",
486 demangleSymbol(typeid(StateType).name()).c_str(), this->orthogonals_.size());
487
489 currentState_.push_back(state);
490 currentStateInfo_ = stateMachineInfo_->getState<StateType>();
491}
492
493template <typename StateType>
495{
496 RCLCPP_INFO(
497 getLogger(), "[%s] State OnEntry code finished.",
498 demangleSymbol(typeid(StateType).name()).c_str());
499
500 auto currentState = this->currentState_.back();
501 for (auto pair : this->orthogonals_)
502 {
503 RCLCPP_DEBUG(getLogger(), "Orthogonal onEntry: %s.", pair.second->getName().c_str());
504 auto & orthogonal = pair.second;
505 try
506 {
507 orthogonal->onEntry();
508 }
509 catch (const std::exception & e)
510 {
511 RCLCPP_ERROR(
512 getLogger(),
513 "[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
514 pair.second->getName().c_str(), e.what());
515 }
516 }
517
518 for (auto & sr : currentState->getStateReactors())
519 {
520 auto srname = smacc2::demangleSymbol(typeid(*sr).name());
521 RCLCPP_INFO_STREAM(getLogger(), "State reactor onEntry: " << srname);
522 try
523 {
524 sr->onEntry();
525 }
526 catch (const std::exception & e)
527 {
528 RCLCPP_ERROR(
529 getLogger(),
530 "[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception "
531 "info: %s",
532 srname.c_str(), e.what());
533 }
534 }
535
536 for (auto & eg : currentState->getEventGenerators())
537 {
538 auto egname = smacc2::demangleSymbol(typeid(*eg).name());
539 RCLCPP_INFO_STREAM(getLogger(), "Event generator onEntry: " << egname);
540 try
541 {
542 eg->onEntry();
543 }
544 catch (const std::exception & e)
545 {
546 RCLCPP_ERROR(
547 getLogger(),
548 "[Event generator %s] Exception on Entry - continuing with next state reactor. Exception "
549 "info: %s",
550 egname.c_str(), e.what());
551 }
552 }
553
554 {
555 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
556 this->updateStatusMessage();
558 }
559}
560
561template <typename StateType>
563{
564 for (auto pair : this->orthogonals_)
565 {
566 // RCLCPP_INFO(getLogger(),"ortho onruntime configure: %s", pair.second->getName().c_str());
567 auto & orthogonal = pair.second;
568 orthogonal->runtimeConfigure();
569 }
570
571 {
572 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
573 this->updateStatusMessage();
575
577 }
578}
579
580template <typename StateType>
585
586template <typename StateType>
588{
590 auto fullname = demangleSymbol(typeid(StateType).name());
591 RCLCPP_WARN_STREAM(getLogger(), "Exiting state: " << fullname);
592
593 RCLCPP_INFO_STREAM(getLogger(), "Notification state exit: leaving state " << state);
594 for (auto pair : this->orthogonals_)
595 {
596 auto & orthogonal = pair.second;
597 try
598 {
599 orthogonal->onExit();
600 }
601 catch (const std::exception & e)
602 {
603 RCLCPP_ERROR(
604 getLogger(),
605 "[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
606 pair.second->getName().c_str(), e.what());
607 }
608 }
609
610 for (auto & sr : state->getStateReactors())
611 {
612 auto srname = smacc2::demangleSymbol(typeid(*sr).name());
613 RCLCPP_INFO_STREAM(getLogger(), "State reactor OnExit: " << srname);
614 try
615 {
616 sr->onExit();
617 }
618 catch (const std::exception & e)
619 {
620 RCLCPP_ERROR(
621 getLogger(),
622 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
623 "info: %s",
624 srname.c_str(), e.what());
625 }
626 }
627
628 for (auto & eg : state->getEventGenerators())
629 {
630 auto egname = smacc2::demangleSymbol(typeid(*eg).name());
631 RCLCPP_INFO_STREAM(getLogger(), "Event generator OnExit: " << egname);
632 try
633 {
634 eg->onExit();
635 }
636 catch (const std::exception & e)
637 {
638 RCLCPP_ERROR(
639 getLogger(),
640 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
641 "info: %s",
642 egname.c_str(), e.what());
643 }
644 }
645}
646
647template <typename StateType>
649{
650 this->lockStateMachine("state exit");
651
653
654 auto fullname = demangleSymbol(typeid(StateType).name());
655 RCLCPP_WARN_STREAM(getLogger(), "Exiting state: " << fullname);
656
657 RCLCPP_INFO_STREAM(getLogger(), "Notification state disposing: leaving state" << state);
658 for (auto pair : this->orthogonals_)
659 {
660 auto & orthogonal = pair.second;
661 try
662 {
663 orthogonal->onDispose();
664 }
665 catch (const std::exception & e)
666 {
667 RCLCPP_ERROR(
668 getLogger(),
669 "[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
670 pair.second->getName().c_str(), e.what());
671 }
672 }
673
674 for (auto & sr : state->getStateReactors())
675 {
676 auto srname = smacc2::demangleSymbol(typeid(*sr).name()).c_str();
677 RCLCPP_INFO(getLogger(), "State reactor disposing: %s", srname);
678 try
679 {
680 this->disconnectSmaccSignalObject(sr.get());
681 }
682 catch (const std::exception & e)
683 {
684 RCLCPP_ERROR(
685 getLogger(),
686 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
687 "info: %s",
688 srname, e.what());
689 }
690 }
691
692 for (auto & eg : state->getEventGenerators())
693 {
694 auto egname = smacc2::demangleSymbol(typeid(*eg).name()).c_str();
695 RCLCPP_INFO(getLogger(), "Event generator disposing: %s", egname);
696 try
697 {
698 this->disconnectSmaccSignalObject(eg.get());
699 }
700 catch (const std::exception & e)
701 {
702 RCLCPP_ERROR(
703 getLogger(),
704 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
705 "info: %s",
706 egname, e.what());
707 }
708 }
709
710 // NOTE: do NOT clear stateCallbackConnections here. Entries are erased
711 // per-object by disconnectSmaccSignalObject when each owner is disposed
712 // (behaviors via orthogonal onDispose, state reactors and event generators
713 // above). A blanket clear also dropped - without finalizing - the entries of
714 // container-state behaviors that outlive this inner state exit, so their
715 // boost connections were never disconnected and the next signal emission
716 // invoked a callback on a destroyed object (use-after-free segfault).
717 currentState_.pop_back();
718
719 // then call exit state
720 RCLCPP_WARN_STREAM(getLogger(), "State exit: " << fullname);
721
723 this->unlockStateMachine("state exit");
724}
725//------------------------------------------------------------------------------------------------
726template <typename EventType>
728{
729 RCLCPP_DEBUG(
730 getLogger(), "PROPAGATING EVENT [%s] TO SRs [%s]: ", demangleSymbol<EventType>().c_str(),
731 st->getClassName().c_str());
732 for (auto & sb : st->getStateReactors())
733 {
734 sb->notifyEvent(ev);
735 }
736
737 auto * pst = st->getParentState();
738 if (pst != nullptr)
739 {
741 }
742}
743
744template <typename InitialStateType>
746{
747 this->stateMachineInfo_ = std::make_shared<SmaccStateMachineInfo>(this->getNode());
748 this->stateMachineInfo_->buildStateMachineInfo<InitialStateType>();
749 this->stateMachineInfo_->assembleSMStructureMessage(this);
751}
752
754
756
761
762} // namespace smacc2
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)
void notifyOnRuntimeConfigurationFinished(StateType *state)
smacc2::SmaccSignalConnection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
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)
void notifyOnStateExiting(StateType *state)
std::map< void *, std::shared_ptr< CallbackCounterSemaphore > > stateCallbackConnections
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 notifyOnStateEntryStart(StateType *state)
ISmaccState * getParentState()
virtual std::string getClassName()
std::vector< std::shared_ptr< StateReactor > > & getStateReactors()
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
ComponentRequirement
Definition common.hpp:74
#define eventtypename
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)
smacc2_event