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