SMACC
Loading...
Searching...
No Matches
smacc_state_machine_info.h
Go to the documentation of this file.
1/*****************************************************************************************************************
2 * ReelRobotix Inc. - Software License Agreement Copyright (c) 2018
3 * Authors: Pablo Inigo Blasco, Brett Aldrich
4 *
5 ******************************************************************************************************************/
6
7#pragma once
8
9#include <smacc/common.h>
11
12// smacc_msgs
13#include <smacc_msgs/SmaccState.h>
14#include <smacc_msgs/SmaccTransition.h>
15#include <smacc_msgs/SmaccOrthogonal.h>
16#include <smacc_msgs/SmaccStateReactor.h>
17#include <smacc_msgs/SmaccEventGenerator.h>
18
19namespace smacc
20{
21namespace introspection
22{
23class SmaccStateMachineInfo : public std::enable_shared_from_this<SmaccStateMachineInfo>
24{
25public:
26 std::map<std::string, std::shared_ptr<SmaccStateInfo>> states;
27
28 std::vector<smacc_msgs::SmaccState> stateMsgs;
29
30 template <typename InitialStateType>
32
33 template <typename StateType>
34 std::shared_ptr<SmaccStateInfo> createState(std::shared_ptr<SmaccStateInfo> parentState);
35
36 template <typename StateType>
38 {
39 auto typeNameStr = typeid(StateType).name();
40
41 return states.count(typeNameStr) > 0;
42 }
43
44 template <typename StateType>
45 std::shared_ptr<SmaccStateInfo> getState()
46 {
47 if (this->containsState<StateType>())
48 {
49 return states[typeid(StateType).name()];
50 }
51 return nullptr;
52 }
53
54 template <typename StateType>
55 void addState(std::shared_ptr<StateType> &state);
56
58};
59
60//---------------------------------------------
62{
63 std::shared_ptr<SmaccStateInfo> &parentState_;
64 AddSubState(std::shared_ptr<SmaccStateInfo> &parentState)
65 : parentState_(parentState)
66 {
67 }
68
69 template <typename T>
70 void operator()(T);
71};
72
73//---------------------------------------------
75{
76 std::shared_ptr<SmaccStateInfo> &currentState_;
77
78 AddTransition(std::shared_ptr<SmaccStateInfo> &currentState)
79 : currentState_(currentState)
80 {
81 }
82
83 template <template <typename, typename, typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename Tag, typename DestinyState>
84 void operator()(TTransition<EvType<TevSource>, DestinyState, Tag>);
85
86 template <template <typename, typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename DestinyState>
87 void operator()(TTransition<EvType<TevSource>, DestinyState>);
88
89 template <typename T>
90 void operator()(T);
91};
92
93//---------------------------------------------
94template <typename InitialStateType>
96{
97 static void walkStates(std::shared_ptr<SmaccStateInfo> &currentState, bool rootInitialNode);
98};
99
100//---------------------------------------------
101template <typename T>
103{
104 using type_t = typename T::type;
105 //auto childState = this->parentState_->createChildState<type_t>()
107}
108//--------------------------------------------
109template <typename T>
110typename disable_if<boost::mpl::is_sequence<T>>::type
111processSubState(std::shared_ptr<SmaccStateInfo> &parentState)
112{
113 WalkStatesExecutor<T>::walkStates(parentState, false);
114}
115
116//---------------------------------------------
117template <typename T>
118typename enable_if<boost::mpl::is_sequence<T>>::type
119processSubState(std::shared_ptr<SmaccStateInfo> &parentState)
120{
121 using boost::mpl::_1;
122 using wrappedList = typename boost::mpl::transform<T, add_type_wrapper<_1>>::type;
123 boost::mpl::for_each<wrappedList>(AddSubState(parentState));
124}
125
126//--------------------------------------------
127/*Iterate on All Transitions*/
128template <typename T>
129typename enable_if<boost::mpl::is_sequence<T>>::type
130processTransitions(std::shared_ptr<SmaccStateInfo> &sourceState)
131{
132
133 ROS_INFO_STREAM("State %s Walker has transition list");
134 using boost::mpl::_1;
135 using wrappedList = typename boost::mpl::transform<T, add_type_wrapper<_1>>::type;
136 boost::mpl::for_each<wrappedList>(AddTransition(sourceState));
137}
138
139template <typename Ev, typename Dst, typename Tag>
140void processTransition(smacc::Transition<Ev, boost::statechart::deep_history<Dst>, Tag> *, std::shared_ptr<SmaccStateInfo> &sourceState)
141{
142 auto transitionTypeInfo = TypeInfo::getTypeInfoFromType<smacc::Transition<Ev, boost::statechart::deep_history<Dst>, Tag>>();
144 processTransitionAux(mock, sourceState, true, transitionTypeInfo);
145}
146
147template <typename Ev, typename Dst, typename Tag>
148void processTransition(smacc::Transition<Ev, Dst, Tag> *t, std::shared_ptr<SmaccStateInfo> &sourceState)
149{
150 auto transitionTypeInfo = TypeInfo::getTypeInfoFromType<smacc::Transition<Ev, Dst, Tag>>();
151 processTransitionAux(t, sourceState, false, transitionTypeInfo);
152}
153
154template <typename Ev, typename Dst, typename Tag>
155void processTransitionAux(smacc::Transition<Ev, Dst, Tag> *, std::shared_ptr<SmaccStateInfo> &sourceState, bool history, TypeInfo::Ptr &transitionTypeInfo)
156{
157 ROS_INFO("State %s Walker transition: %s", sourceState->toShortName().c_str(), demangleSymbol(typeid(Ev).name()).c_str());
158 std::string transitionTag;
159 std::string transitionType;
160
161 if (typeid(Tag) != typeid(default_transition_name))
162 {
163 transitionTag = demangleSymbol<Tag>();
164 transitionType = getTransitionType<Tag>();
165 ROS_DEBUG_STREAM("TRANSITION TYPE:" << transitionType);
166 }
167 else
168 {
169 transitionTag = "";
170 automaticTransitionTag<Ev>(transitionTag);
171 automaticTransitionType<Ev>(transitionType);
172 }
173
174 ROS_INFO_STREAM("Transition tag: " << transitionTag);
175
176 if (!sourceState->stateMachine_->containsState<Dst>())
177 {
178 auto realparentState = sourceState->stateMachine_->getState<typename Dst::TContext>();
179 auto siblingnode = sourceState->stateMachine_->createState<Dst>(realparentState);
180
181 //auto siblingnode = sourceState->stateMachine_->createState<Dst>(sourceState->parentState_);
182 WalkStatesExecutor<Dst>::walkStates(siblingnode, true);
183 sourceState->declareTransition<Ev>(siblingnode, transitionTag, transitionType, history, transitionTypeInfo);
184 }
185 else
186 {
187 //auto realparentState = sourceState->stateMachine_->getState<typename Dst::TContext>();
188 //auto siblingnode = sourceState->stateMachine_->createState<Dst>(realparentState);
189
190 auto siblingnode = sourceState->stateMachine_->getState<Dst>();
191 sourceState->declareTransition<Ev>(siblingnode, transitionTag, transitionType, history, transitionTypeInfo);
192 }
193}
194
195//---------------------------------------------
196template <typename EvType>
197void SmaccStateInfo::declareTransition(std::shared_ptr<SmaccStateInfo> &dstState, std::string transitionTag, std::string transitionType, bool history, TypeInfo::Ptr transitionTypeInfo)
198{
199 auto evtype = demangledTypeName<EvType>();
200
201 SmaccTransitionInfo transitionInfo;
202 transitionInfo.index = transitions_.size();
203 transitionInfo.sourceState = shared_from_this();
204 transitionInfo.destinyState = dstState;
205 transitionInfo.transitionTypeInfo = transitionTypeInfo;
206
207 if (transitionTag != "")
208 transitionInfo.transitionTag = transitionTag;
209 else
210 transitionInfo.transitionTag = "Transition_" + std::to_string(transitionInfo.index);
211
212 transitionInfo.transitionType = transitionType;
213 transitionInfo.historyNode = history;
214
215 transitionInfo.eventInfo = std::make_shared<SmaccEventInfo>(transitionTypeInfo->templateParameters.front());
216
217 EventLabel<EvType>(transitionInfo.eventInfo->label);
218 ROS_DEBUG_STREAM("LABEL: " << transitionInfo.eventInfo->label);
219
220 transitions_.push_back(transitionInfo);
221}
222//---------------------------------------------
223
224// template <typename TevSource, template <typename> typename EvType>
225// void SmaccStateInfo::declareTransition(std::shared_ptr<SmaccStateInfo> &dstState, std::string transitionTag, std::string transitionType, bool history)
226// {
227// auto evtype = demangledTypeName<EvType<TevSource>>();
228
229// SmaccTransitionInfo transitionInfo;
230// transitionInfo.index = transitions_.size();
231// transitionInfo.sourceState = shared_from_this();
232// transitionInfo.destinyState = dstState;
233
234// if (transitionTag != "")
235// transitionInfo.transitionTag = transitionTag;
236// else
237// transitionInfo.transitionTag = "Transition_" + std::to_string(transitionInfo.index);
238
239// transitionInfo.transitionType = transitionType;
240
241// transitionInfo.eventInfo = std::make_shared<SmaccEventInfo>(TypeInfo::getTypeInfoFromString(demangleSymbol(typeid(EvType<TevSource>).name())));
242
243// EventLabel<EvType<TevSource>>(transitionInfo.eventInfo->label);
244// ROS_ERROR_STREAM("LABEL: " << transitionInfo.eventInfo->label);
245
246// transitions_.push_back(transitionInfo);
247// }
248
249//---------------------------------------------
250template <typename Ev, typename Dst>
251void processTransition(statechart::transition<Ev, Dst> *, std::shared_ptr<SmaccStateInfo> &sourceState)
252{
253 //ROS_INFO_STREAM("GOTCHA");
254}
255
256template <typename Ev>
257void processTransition(statechart::custom_reaction<Ev> *, std::shared_ptr<SmaccStateInfo> &sourceState)
258{
259 //ROS_INFO_STREAM("GOTCHA");
260}
261
262//---------------------------------------------
263// only reached if it is a leaf transition in the mpl::list
264
265template <typename T>
266typename disable_if<boost::mpl::is_sequence<T>>::type
267processTransitions(std::shared_ptr<SmaccStateInfo> &sourceState)
268{
269 //ROS_INFO_STREAM("state transition from: " << sourceState->demangledStateName << " of type: " << demangledTypeName<T>());
270 T *dummy;
271 processTransition(dummy, sourceState);
272}
273
274/*
275// only reached if it is a leaf transition in the mpl::list
276template <template <typename,typename,typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename Tag, typename DestinyState >
277typename disable_if<boost::mpl::is_sequence<TTransition<EvType<TevSource>,DestinyState, Tag>>>::type
278processTransitions(std::shared_ptr<SmaccStateInfo> &sourceState)
279{
280 ROS_INFO("DETECTED COMPLEX TRANSITION **************");
281 //ROS_INFO_STREAM("state transition from: " << sourceState->demangledStateName << " of type: " << demangledTypeName<T>());
282 TTransition<EvType<TevSource>,DestinyState, Tag> *dummy;
283 processTransition(dummy, sourceState);
284}
285
286template <template <typename,typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename DestinyState >
287typename disable_if<boost::mpl::is_sequence<TTransition<EvType<TevSource>,DestinyState>>>::type
288processTransitions(std::shared_ptr<SmaccStateInfo> &sourceState)
289{
290 ROS_INFO("DETECTED COMPLEX TRANSITION **************");
291 //ROS_INFO_STREAM("state transition from: " << sourceState->demangledStateName << " of type: " << demangledTypeName<T>());
292 TTransition<EvType<TevSource>,DestinyState> *dummy;
293 processTransition(dummy, sourceState);
294}
295*/
296
297//--------------------------------------------
298
299template <template <typename, typename, typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename Tag, typename DestinyState>
300void AddTransition::operator()(TTransition<EvType<TevSource>, DestinyState, Tag>)
301{
302 processTransitions<TTransition<EvType<TevSource>, DestinyState, Tag>>(currentState_);
303}
304
305//--------------------------------------------
306
307template <template <typename, typename> typename TTransition, typename TevSource, template <typename> typename EvType, typename DestinyState>
308void AddTransition::operator()(TTransition<EvType<TevSource>, DestinyState>)
309{
310 processTransitions<TTransition<EvType<TevSource>, DestinyState>>(currentState_);
311}
312
313template <typename TTrans>
315{
316 using type_t = typename TTrans::type;
317 processTransitions<type_t>(currentState_);
318}
319
320//------------------ staticConfigure -----------------------------
321
322// SFINAE test
323template <typename T>
325{
326private:
327 typedef char YesType[1];
328 typedef char NoType[2];
329
330 template <typename C>
331 static YesType &test(decltype(&C::staticConfigure));
332 template <typename C>
333 static NoType &test(...);
334
335public:
336 enum
337 {
338 value = sizeof(test<T>(0)) == sizeof(YesType)
339 };
340};
341
342template <typename T>
343typename std::enable_if<HasOnDefinition<T>::value, void>::type
345{
346 /* something when T has toString ... */
347 ROS_INFO_STREAM("EXECUTING ONDEFINITION: " << demangleSymbol(typeid(T).name()));
348 T::staticConfigure();
349}
350
351template <typename T>
352typename std::enable_if<!HasOnDefinition<T>::value, void>::type
354{
355 ROS_INFO_STREAM("static OnDefinition: dont exist for " << demangleSymbol(typeid(T).name()));
356 /* something when T has toString ... */
357}
358
359/*
360void CallOnDefinition(...)
361{
362
363}*/
364
365//-----------------------------------------------------------------------------------
366template <typename InitialStateType>
367void WalkStatesExecutor<InitialStateType>::walkStates(std::shared_ptr<SmaccStateInfo> &parentState, bool rootInitialNode)
368{
369 //ros::Duration(1).sleep();
370 auto currentname = demangledTypeName<InitialStateType>();
371
372 std::shared_ptr<SmaccStateInfo> targetState;
373
374 if (!rootInitialNode)
375 {
376 if (parentState->stateMachine_->containsState<InitialStateType>())
377 {
378 // it already exist: break;
379 return;
380 }
381
382 targetState = parentState->createChildState<InitialStateType>();
383 }
384 else
385 {
386 targetState = parentState;
387 }
388
389 CallOnDefinition<InitialStateType>();
390
391 typedef typename std::remove_pointer<decltype(InitialStateType::smacc_inner_type)>::type InnerType;
392 processSubState<InnerType>(targetState);
393
394 // -------------------- REACTIONS --------------------
395 typedef typename InitialStateType::reactions reactions;
396 //ROS_INFO_STREAM("state machine initial state reactions: "<< demangledTypeName<reactions>());
397
398 processTransitions<reactions>(targetState);
399}
400
401//------------------------------------------------
402
403template <typename InitialStateType>
405{
406 auto initialState = this->createState<InitialStateType>(nullptr);
408}
409
410template <typename StateType>
411std::shared_ptr<SmaccStateInfo> SmaccStateMachineInfo::createState(std::shared_ptr<SmaccStateInfo> parent)
412{
413 auto thisptr = this->shared_from_this();
414 auto *statetid = &(typeid(StateType));
415
416 auto demangledName = demangledTypeName<StateType>();
417 ROS_INFO_STREAM("Creating State Info: " << demangledName);
418
419 auto state = std::make_shared<SmaccStateInfo>(statetid, parent, thisptr);
420 state->demangledStateName = demangledName;
421 state->fullStateName = typeid(StateType).name();
422 state->stateIndex_ = states.size();
423
424 if (parent != nullptr)
425 {
426 parent->children_.push_back(state);
427 }
428
429 this->addState(state);
430
431 return state;
432}
433
434template <typename StateType>
435void SmaccStateMachineInfo::addState(std::shared_ptr<StateType> &state)
436{
437 states[state->fullStateName] = state;
438}
439
440template <typename StateType>
441std::shared_ptr<SmaccStateInfo> SmaccStateInfo::createChildState()
442{
443 auto realparentState = this->stateMachine_->getState<typename StateType::TContext>();
444
445 auto childState = this->stateMachine_->createState<StateType>(realparentState);
446
447 ROS_WARN_STREAM("Real parent state> " << demangleSymbol<typename StateType::TContext>());
448
449 /*auto contextInfo = TypeInfo::getTypeInfoFromType<InitialStateType>();
450 auto parentState2= getState<InitialStateType::TContext>();
451 parentState2->createChildState<InitialStateType>();*/
452
453 //this->stateMachine_->addState(childState);
454 //stateMachineInfo.addState(stateMachineInfo)
455 //stateNames.push_back(currentname);
456 //ROS_INFO("------------");
457 //ROS_INFO_STREAM("** STATE state: "<< this->demangledStateName);
458
459 return childState;
460}
461} // namespace introspection
462} // namespace smacc
static YesType & test(decltype(&C::staticConfigure))
std::shared_ptr< SmaccStateInfo > createChildState()
std::shared_ptr< SmaccStateMachineInfo > stateMachine_
void declareTransition(std::shared_ptr< SmaccStateInfo > &dstState, std::string transitionTag, std::string transitionType, bool history, TypeInfo::Ptr transitionTypeInfo)
std::vector< SmaccTransitionInfo > transitions_
std::vector< smacc_msgs::SmaccState > stateMsgs
std::shared_ptr< SmaccStateInfo > getState()
void addState(std::shared_ptr< StateType > &state)
std::shared_ptr< SmaccStateInfo > createState(std::shared_ptr< SmaccStateInfo > parentState)
std::map< std::string, std::shared_ptr< SmaccStateInfo > > states
std::shared_ptr< TypeInfo > Ptr
void processTransitionAux(smacc::Transition< Ev, Dst, Tag > *, std::shared_ptr< SmaccStateInfo > &sourceState, bool history, TypeInfo::Ptr &transitionTypeInfo)
std::enable_if< HasOnDefinition< T >::value, void >::type CallOnDefinition()
enable_if< boost::mpl::is_sequence< T > >::type processTransitions(std::shared_ptr< SmaccStateInfo > &sourceState)
void processTransition(smacc::Transition< Ev, boost::statechart::deep_history< Dst >, Tag > *, std::shared_ptr< SmaccStateInfo > &sourceState)
std::string demangleSymbol()
Definition: introspection.h:75
disable_if< boost::mpl::is_sequence< T > >::type processSubState(std::shared_ptr< SmaccStateInfo > &parentState)
std::shared_ptr< SmaccStateInfo > & parentState_
AddSubState(std::shared_ptr< SmaccStateInfo > &parentState)
void operator()(TTransition< EvType< TevSource >, DestinyState, Tag >)
std::shared_ptr< SmaccStateInfo > & currentState_
AddTransition(std::shared_ptr< SmaccStateInfo > &currentState)
std::shared_ptr< SmaccStateInfo > destinyState
std::shared_ptr< SmaccEventInfo > eventInfo
smacc::introspection::TypeInfo::Ptr transitionTypeInfo
std::shared_ptr< SmaccStateInfo > sourceState
static void walkStates(std::shared_ptr< SmaccStateInfo > &currentState, bool rootInitialNode)