SMACC2
Loading...
Searching...
No Matches
smacc_state_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
29
30namespace smacc2
31{
32using namespace smacc2::introspection;
33#define THIS_STATE_NAME ((demangleSymbol(typeid(*this).name()).c_str()))
34template <typename TOrthogonal, typename TBehavior, typename... Args>
35std::shared_ptr<TBehavior> ISmaccState::configure(Args &&... args)
36{
37 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
38 RCLCPP_INFO(
39 getLogger(), "[%s] Configuring orthogonal: %s", THIS_STATE_NAME, orthogonalkey.c_str());
40
41 TOrthogonal * orthogonal = this->getOrthogonal<TOrthogonal>();
42 if (orthogonal != nullptr)
43 {
44 auto clientBehavior =
45 std::shared_ptr<TBehavior>(new TBehavior(args...)); // is there an error here? are the
46 // behavior constructor parameters right?
47 orthogonal->addClientBehavior(clientBehavior);
48 clientBehavior->template onStateOrthogonalAllocation<TOrthogonal, TBehavior>();
49 return clientBehavior;
50 }
51 else
52 {
53 RCLCPP_ERROR(
54 getLogger(), "[%s] Skipping client behavior creation in orthogonal [%s]. It does not exist.",
55 THIS_STATE_NAME, orthogonalkey.c_str());
56 return nullptr;
57 }
58}
59//-------------------------------------------------------------------------------------------------------
60
61template <typename SmaccComponentType>
62void ISmaccState::requiresComponent(SmaccComponentType *& storage)
63{
64 this->getStateMachine().requiresComponent(storage);
65}
66//-------------------------------------------------------------------------------------------------------
67
68template <typename SmaccClientType>
69void ISmaccState::requiresClient(SmaccClientType *& storage)
70{
71 const char * sname = (demangleSymbol(typeid(*this).name()).c_str());
72 storage = nullptr;
73 auto & orthogonals = this->getStateMachine().getOrthogonals();
74 for (auto & ortho : orthogonals)
75 {
76 ortho.second->requiresClient(storage);
77 if (storage != nullptr) return;
78 }
79
80 RCLCPP_ERROR(
81 getLogger(),
82 "[%s] Client of type '%s' not found in any orthogonal of the current state machine. This may "
83 "produce a segmentation fault if the returned reference is used.",
84 sname, demangleSymbol<SmaccClientType>().c_str());
85}
86//-------------------------------------------------------------------------------------------------------
87
88template <typename T>
89bool ISmaccState::getGlobalSMData(std::string name, T & ret)
90{
91 return this->getStateMachine().getGlobalSMData(name, ret);
92}
93//-------------------------------------------------------------------------------------------------------
94
95// Store globally in this state machine. (By value parameter )
96template <typename T>
97void ISmaccState::setGlobalSMData(std::string name, T value)
98{
99 this->getStateMachine().setGlobalSMData(name, value);
100}
101//-------------------------------------------------------------------------------------------------------
102
103template <typename TStateReactor, typename... TEvArgs>
104std::shared_ptr<TStateReactor> ISmaccState::createStateReactor(TEvArgs... args)
105{
106 auto sr = std::make_shared<TStateReactor>(args...);
107 stateReactors_.push_back(sr);
108 return sr;
109}
110
111template <typename TEventGenerator, typename... TEvArgs>
112std::shared_ptr<TEventGenerator> ISmaccState::createEventGenerator(TEvArgs... args)
113{
114 auto eg = std::make_shared<TEventGenerator>(args...);
115 eventGenerators_.push_back(eg);
116 return eg;
117}
118
119// used to iterate on the source events list and fill the information of the stateReactorInfo structure
120template <typename TEventList>
122{
125
126 template <typename T>
128 {
129 auto evinfo = std::make_shared<SmaccEventInfo>(TypeInfo::getTypeInfoFromType<T>());
130 srInfo_->sourceEventTypes.push_back(evinfo);
131 EventLabel<T>(evinfo->label);
132 }
133};
134
135// used to iterate on the source events list and fill the information of the stateReactorInfo structure
136// (is it required alreadyy having the AddTEventTypeStateReactorInfo?)
137template <typename TEventList>
139{
142
143 template <typename T>
145 {
146 sr_->addInputEvent<T>();
147 }
148};
149
150template <typename TStateReactor, typename TTriggerEvent, typename TEventList, typename... TEvArgs>
151std::shared_ptr<TStateReactor> ISmaccState::createStateReactor(TEvArgs... args)
152{
153 auto sr = std::make_shared<TStateReactor>(args...);
154 sr->initialize(this);
155 sr->template setOutputEvent<TTriggerEvent>();
156
157 using boost::mpl::_1;
158 using wrappedList = typename boost::mpl::transform<TEventList, _1>::type;
160 boost::mpl::for_each<wrappedList>(op);
161
162 stateReactors_.push_back(sr);
163 return sr;
164}
165
166template <typename TOrthogonal>
168{
169 return this->getStateMachine().getOrthogonal<TOrthogonal>();
170}
171
172template <typename TOrthogonal, typename TClientBehavior>
173TClientBehavior * ISmaccState::getClientBehavior(int index)
174{
175 return this->getStateMachine().getClientBehavior<TOrthogonal, TClientBehavior>(index);
176}
177
178template <typename TEventGenerator>
180{
181 TEventGenerator * ret = nullptr;
182 for (auto & evg : this->eventGenerators_)
183 {
184 ret = dynamic_cast<TEventGenerator *>(evg.get());
185 if (ret != nullptr) break;
186 }
187 return ret;
188}
189
190template <typename TStateReactor>
192{
193 TStateReactor * ret = nullptr;
194 for (auto & sr : this->eventGenerators_)
195 {
196 ret = dynamic_cast<TStateReactor *>(sr.get());
197 if (ret != nullptr) break;
198 }
199 return ret;
200}
201
202//-------------------------------------------------------------------------------------------------------
203
204template <typename EventType>
205void ISmaccState::postEvent(const EventType & ev)
206{
208}
209
210template <typename EventType>
212{
213 getStateMachine().postEvent<EventType>();
214}
215//-------------------------------------------------------------------------------------------------------
216
217template <typename TransitionType>
223
224//-------------------------------------------------------------------------------------------------------------------
225
226} // namespace smacc2
227
228// implementation depends on state definition
bool getGlobalSMData(std::string name, T &ret)
TClientBehavior * getClientBehavior(int index=0)
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType)
void setGlobalSMData(std::string name, T value)
const std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > & getOrthogonals() const
void postEvent(EventType *ev, EventLifeTime evlifetime=EventLifeTime::ABSOLUTE)
rclcpp::Logger getLogger()
TClientBehavior * getClientBehavior(int index=0)
std::shared_ptr< TEventGenerator > createEventGenerator(TEvArgs... args)
std::vector< std::shared_ptr< StateReactor > > stateReactors_
bool getGlobalSMData(std::string name, T &ret)
std::shared_ptr< TBehavior > configure(Args &&... args)
void requiresClient(SmaccClientType *&storage)
std::shared_ptr< TStateReactor > createStateReactor(TEvArgs... args)
TOrthogonal * getOrthogonal()
void requiresComponent(SmaccComponentType *&storage)
TStateReactor * getStateReactor()
virtual ISmaccStateMachine & getStateMachine()=0
std::vector< std::shared_ptr< smacc2::SmaccEventGenerator > > eventGenerators_
void setGlobalSMData(std::string name, T value)
TEventGenerator * getEventGenerator()
void notifyTransitionFromTransitionTypeInfo(std::shared_ptr< smacc2::introspection::TypeInfo > &transitionTypeInfo)
static TypeInfo::Ptr getTypeInfoFromType()
std::enable_if< HasEventLabel< T >::value, void >::type EventLabel(std::string &label)
std::string demangleSymbol()
std::string demangledTypeName()
#define THIS_STATE_NAME
smacc2::SmaccStateReactorInfo * srInfo_
AddTEventTypeStateReactorInfo(smacc2::SmaccStateReactorInfo *srInfo)
AddTEventTypeStateReactor(smacc2::StateReactor *sr)
std::vector< std::shared_ptr< SmaccEventInfo > > sourceEventTypes