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