SMACC
Loading...
Searching...
No Matches
introspection.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 <boost/statechart/state.hpp>
10#include <boost/statechart/simple_state.hpp>
11#include <boost/statechart/event.hpp>
12
13#include <ros/ros.h>
14#include <typeinfo>
15#include <boost/mpl/list.hpp>
16#include <boost/mpl/for_each.hpp>
17#include <boost/mpl/transform.hpp>
18
19#include <smacc/smacc_types.h>
22
23#include <smacc_msgs/SmaccTransition.h>
24
25namespace sc = boost::statechart;
26
27namespace smacc
28{
29namespace introspection
30{
31using namespace boost;
32using namespace smacc::default_transition_tags;
33
34void transitionInfoToMsg(const SmaccTransitionInfo &transition, smacc_msgs::SmaccTransition &transitionMsg);
35
36typedef std::allocator<void> SmaccAllocator;
37
38template <class T>
39auto optionalNodeHandle(boost::intrusive_ptr<T> &obj)
40 -> ros::NodeHandle
41{
42 return obj->getROSNode();
43}
44
45template <class T>
46auto optionalNodeHandle(T *) -> ros::NodeHandle
47{
48 return ros::NodeHandle("");
49}
50
51inline std::string demangleSymbol(const std::string &name)
52{
53 return demangleSymbol(name.c_str());
54}
55
56inline std::string demangleSymbol(const char *name)
57{
58#if (__GNUC__ && __cplusplus && __GNUC__ >= 3)
59 int status;
60 char *res = abi::__cxa_demangle(name, 0, 0, &status);
61 if (res)
62 {
63 const std::string demangled_name(res);
64 std::free(res);
65 return demangled_name;
66 }
67 // Demangling failed, fallback to mangled name
68 return std::string(name);
69#else
70 return std::string(name);
71#endif
72}
73
74template <typename T>
75inline std::string demangleSymbol()
76{
77 return demangleSymbol(typeid(T).name());
78}
79
80template <class T>
81inline std::string demangledTypeName()
82{
83 return demangleSymbol(typeid(T).name());
84}
85
86inline std::string demangleType(const std::type_info* tinfo)
87{
88 return demangleSymbol(tinfo->name());
89}
90
91inline std::string demangleType(const std::type_info &tinfo)
92{
93 return demangleSymbol(tinfo.name());
94}
95
96template <typename...>
98{
99};
100
101//-------------------------------------------------------------------------
102template <typename T>
104{
105private:
106 typedef char YesType[1];
107 typedef char NoType[2];
108
109 template <typename C>
110 static YesType &test(decltype(&C::getEventLabel));
111 template <typename C>
112 static NoType &test(...);
113
114public:
115 enum
116 {
117 value = sizeof(test<T>(0)) == sizeof(YesType)
118 };
119};
120
121template <typename T>
122typename std::enable_if<HasEventLabel<T>::value, void>::type
123EventLabel(std::string &label)
124{
125 label = T::getEventLabel();
126}
127
128template <typename T>
129typename std::enable_if<!HasEventLabel<T>::value, void>::type
130EventLabel(std::string &label)
131{
132 label = "";
133}
134//-----------------------------------------------------------------------
135
136template <typename T>
138{
139private:
140 typedef char YesType[1];
141 typedef char NoType[2];
142
143 template <typename C>
144 static YesType &test(decltype(&C::getDefaultTransitionTag));
145 template <typename C>
146 static NoType &test(...);
147
148public:
149 enum
150 {
151 value = sizeof(test<T>(0)) == sizeof(YesType)
152 };
153};
154
155template <typename T>
156typename std::enable_if<HasAutomaticTransitionTag<T>::value, void>::type
157automaticTransitionTag(std::string &transition_name)
158{
159 transition_name = T::getDefaultTransitionTag();
160}
161
162template <typename T>
163typename std::enable_if<!HasAutomaticTransitionTag<T>::value, void>::type
164automaticTransitionTag(std::string &transition_name)
165{
166 transition_name = "";
167}
168
169//-------------------------------------------------
170template <typename T>
172{
173private:
174 typedef char YesType[1];
175 typedef char NoType[2];
176
177 template <typename C>
178 static YesType &test(decltype(&C::getDefaultTransitionType));
179 template <typename C>
180 static NoType &test(...);
181
182public:
183 enum
184 {
185 value = sizeof(test<T>(0)) == sizeof(YesType)
186 };
187};
188
189template <typename T>
190typename std::enable_if<HasAutomaticTransitionType<T>::value, void>::type
191automaticTransitionType(std::string &transition_type)
192{
193 transition_type = T::getDefaultTransitionType();
194}
195
196template <typename T>
197typename std::enable_if<!HasAutomaticTransitionType<T>::value, void>::type
198automaticTransitionType(std::string &transition_type)
199{
200 transition_type = demangledTypeName<DEFAULT>();
201}
202
203// there are many ways to implement this, for instance adding static methods to the types
204typedef boost::mpl::list<SUCCESS, ABORT, PREEMPT, CONTINUELOOP, ENDLOOP> DEFAULT_TRANSITION_TYPES;
205
206//--------------------------------
207
208template <typename T>
209struct type_
210{
211 using type = T;
212};
213
214//---------------------------------------------
215template <typename T>
217{
218 using type = type_<T>;
219};
220
221template <typename TTransition>
223{
225 {
226 this->transitionTypeName = transitionTypeName;
227 }
228
229 std::string *transitionTypeName;
230 template <typename T>
232 {
233 //ROS_INFO_STREAM("comparing.."<< demangleSymbol<T>() <<" vs " << demangleSymbol<TTransition>() );
234 if (std::is_base_of<T, TTransition>::value || std::is_same<T, TTransition>::value)
235 {
236 *(this->transitionTypeName) = demangledTypeName<T>();
237 //ROS_INFO("YESS!");
238 }
239 }
240};
241
242template <typename TTransition>
243static std::string getTransitionType()
244{
245 std::string output;
246 CheckType<TTransition> op(&output);
247 using boost::mpl::_1;
248 using wrappedList = typename boost::mpl::transform<DEFAULT_TRANSITION_TYPES, _1>::type;
249
250 boost::mpl::for_each<wrappedList>(op);
251 return output;
252};
253
254// // BASE CASE
255// template <typename T>
256// static void walkStateReactorsSources(SmaccStateReactorInfo &sbinfo, typelist<T>)
257// {
258// auto sourceType = TypeInfo::getFromStdTypeInfo(typeid(T));
259// auto evinfo = std::make_shared<SmaccEventInfo>(sourceType);
260// EventLabel<T>(evinfo->label);
261// sbinfo.sourceEventTypes.push_back(evinfo);
262// ROS_INFO_STREAM("event: " << sourceType->getFullName());
263// ROS_INFO_STREAM("event parameters: " << sourceType->templateParameters.size());
264// }
265
266// // RECURSIVE CASE
267// template <typename TEvHead, typename... TEvArgs>
268// static void walkStateReactorsSources(SmaccStateReactorInfo &sbinfo, typelist<TEvHead, TEvArgs...>)
269// {
270// auto sourceType = TypeInfo::getFromStdTypeInfo(typeid(TEvHead));
271// auto evinfo = std::make_shared<SmaccEventInfo>(sourceType);
272// EventLabel<TEvHead>(evinfo->label);
273// sbinfo.sourceEventTypes.push_back(evinfo);
274// ROS_INFO_STREAM("event: " << sourceType->getFullName());
275// ROS_INFO_STREAM("event parameters: " << sourceType->templateParameters.size());
276// walkStateReactorsSources(sbinfo, typelist<TEvArgs...>());
277// }
278
279} // namespace introspection
280} // namespace smacc
static YesType & test(decltype(&C::getDefaultTransitionTag))
static YesType & test(decltype(&C::getDefaultTransitionType))
static YesType & test(decltype(&C::getEventLabel))
std::enable_if< HasAutomaticTransitionType< T >::value, void >::type automaticTransitionType(std::string &transition_type)
static std::string getTransitionType()
std::string demangleType(const std::type_info *tinfo)
Definition: introspection.h:86
void transitionInfoToMsg(const SmaccTransitionInfo &transition, smacc_msgs::SmaccTransition &transitionMsg)
Definition: reflection.cpp:9
std::enable_if< HasAutomaticTransitionTag< T >::value, void >::type automaticTransitionTag(std::string &transition_name)
auto optionalNodeHandle(boost::intrusive_ptr< T > &obj) -> ros::NodeHandle
Definition: introspection.h:39
std::allocator< void > SmaccAllocator
Definition: introspection.h:36
std::string demangleSymbol()
Definition: introspection.h:75
std::enable_if< HasEventLabel< T >::value, void >::type EventLabel(std::string &label)
boost::mpl::list< SUCCESS, ABORT, PREEMPT, CONTINUELOOP, ENDLOOP > DEFAULT_TRANSITION_TYPES
std::string demangledTypeName()
Definition: introspection.h:81
CheckType(std::string *transitionTypeName)