interface_manager.h
Go to the documentation of this file.
1 // Copyright (C) 2013, PAL Robotics S.L.
3 // Copyright (C) 2012, hiDOF INC.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of hiDOF, Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived from
14 // this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
28 
30 
31 #ifndef HARDWARE_INTERFACE_INTERFACE_MANAGER_H
32 #define HARDWARE_INTERFACE_INTERFACE_MANAGER_H
33 
34 #include <map>
35 #include <string>
36 #include <vector>
37 #include <boost/ptr_container/ptr_vector.hpp>
38 
39 #include <ros/console.h>
40 
43 
44 namespace hardware_interface
45 {
46 
47 namespace internal
48 {
49 
50 // SFINAE workaround, so that we have reflection inside the template functions
51 template <typename T>
53  // method called if C is a ResourceManager
54  template <typename C>
55  static void callCM(typename std::vector<C*>& managers, C* result, typename C::resource_manager_type*)
56  {
57  std::vector<typename C::resource_manager_type*> managers_in;
58  // we have to typecase back to base class
59  for(typename std::vector<C*>::iterator it = managers.begin(); it != managers.end(); ++it)
60  managers_in.push_back(static_cast<typename C::resource_manager_type*>(*it));
61  C::concatManagers(managers_in, result);
62  }
63 
64  // method called if C is not a ResourceManager
65  template <typename C>
66  static void callCM(typename std::vector<C*>& managers, C* result, ...) {}
67 
68  // calls ResourceManager::concatManagers if C is a ResourceManager
69  static const void callConcatManagers(typename std::vector<T*>& managers, T* result)
70  { callCM<T>(managers, result, 0); }
71 
72 
73  // method called if C is a ResourceManager
74  template <typename C>
75  static void callGR(std::vector<std::string> &resources, C* iface, typename C::resource_manager_type*)
76  {
77  resources = iface->getNames();
78  }
79 
80  // method called if C is not a ResourceManager
81  template <typename C>
82  static void callGR(std::vector<std::string> &resources, T* iface, ...) { }
83 
84  // calls ResourceManager::concatManagers if C is a ResourceManager
85  static void callGetResources(std::vector<std::string> &resources, T* iface)
86  { return callGR<T>(resources, iface, 0); }
87 
88  template <typename C>
89  static T* newCI(boost::ptr_vector<ResourceManagerBase> &guards, typename C::resource_manager_type*)
90  {
91  T* iface_combo = new T;
92  // save the new interface pointer to allow for its correct destruction
93  guards.push_back(static_cast<ResourceManagerBase*>(iface_combo));
94  return iface_combo;
95  }
96 
97  // method called if C is not a ResourceManager
98  template <typename C>
99  static T* newCI(boost::ptr_vector<ResourceManagerBase> &guards, ...) {
100  // it is not a ResourceManager
101  ROS_ERROR("You cannot register multiple interfaces of the same type which are "
102  "not of type ResourceManager. There is no established protocol "
103  "for combining them.");
104  return NULL;
105  }
106 
107  static T* newCombinedInterface(boost::ptr_vector<ResourceManagerBase> &guards)
108  {
109  return newCI<T>(guards, 0);
110  }
111 
112 };
113 
114 } // namespace internal
115 
117 {
118 public:
128  template<class T>
129  void registerInterface(T* iface)
130  {
131  const std::string iface_name = internal::demangledTypeName<T>();
132  if (interfaces_.find(iface_name) != interfaces_.end())
133  {
134  ROS_WARN_STREAM("Replacing previously registered interface '" << iface_name << "'.");
135  }
136  interfaces_[iface_name] = iface;
137  internal::CheckIsResourceManager<T>::callGetResources(resources_[iface_name], iface);
138  }
139 
141  {
142  interface_managers_.push_back(iface_man);
143  }
144 
155  template<class T>
156  T* get()
157  {
158  std::string type_name = internal::demangledTypeName<T>();
159  std::vector<T*> iface_list;
160 
161  // look for interfaces registered here
162  InterfaceMap::iterator it = interfaces_.find(type_name);
163  if (it != interfaces_.end()) {
164  T* iface = static_cast<T*>(it->second);
165  if (!iface) {
166  ROS_ERROR_STREAM("Failed reconstructing type T = '" << type_name.c_str() <<
167  "'. This should never happen");
168  return NULL;
169  }
170  iface_list.push_back(iface);
171  }
172 
173  // look for interfaces registered in the registered hardware
174  for(InterfaceManagerVector::iterator it = interface_managers_.begin();
175  it != interface_managers_.end(); ++it) {
176  T* iface = (*it)->get<T>();
177  if (iface)
178  iface_list.push_back(iface);
179  }
180 
181  if(iface_list.size() == 0)
182  return NULL;
183 
184  if(iface_list.size() == 1)
185  return iface_list.front();
186 
187  // if we're here, we have multiple interfaces, and thus we must construct a new
188  // combined interface, or return one already constructed
189  T* iface_combo;
190  InterfaceMap::iterator it_combo = interfaces_combo_.find(type_name);
191  if(it_combo != interfaces_combo_.end() &&
192  num_ifaces_registered_[type_name] == iface_list.size()) {
193  // there exists a combined interface with the same number of interfaces combined
194  // (since you cannot unregister interfaces, this will be guaranteed to be the
195  // same interfaces from previous calls)
196  iface_combo = static_cast<T*>(it_combo->second);
197  } else {
198  // no existing combined interface
199  iface_combo = internal::CheckIsResourceManager<T>::newCombinedInterface(interface_destruction_list_);
200  if(iface_combo) {
201  // concat all of the resource managers together
203  // save the combined interface for if this is called again
204  interfaces_combo_[type_name] = iface_combo;
205  num_ifaces_registered_[type_name] = iface_list.size();
206  } else {
207  // it is not a ResourceManager
208  ROS_ERROR("You cannot register multiple interfaces of the same type which are "
209  "not of type ResourceManager. There is no established protocol "
210  "for combining them.");
211  iface_combo = NULL;
212  }
213  }
214  return iface_combo;
215  }
216 
218  std::vector<std::string> getNames() const
219  {
220  std::vector<std::string> out;
221  out.reserve(interfaces_.size());
222  for(InterfaceMap::const_iterator it = interfaces_.begin(); it != interfaces_.end(); ++it)
223  {
224  out.push_back(it->first);
225  }
226  return out;
227  }
228 
236  std::vector<std::string> getInterfaceResources(std::string iface_type) const
237  {
238  std::vector<std::string> out;
239  ResourceMap::const_iterator it = resources_.find(iface_type);
240  if(it != resources_.end())
241  {
242  out = it->second;
243  }
244  return out;
245  }
246 
247 protected:
248  typedef std::map<std::string, void*> InterfaceMap;
249  typedef std::vector<InterfaceManager*> InterfaceManagerVector;
250  typedef std::map<std::string, size_t> SizeMap;
251  typedef std::map<std::string, std::vector<std::string> > ResourceMap;
252 
253  InterfaceMap interfaces_;
254  InterfaceMap interfaces_combo_;
255  InterfaceManagerVector interface_managers_;
257  boost::ptr_vector<ResourceManagerBase> interface_destruction_list_;
259  ResourceMap resources_;
260 };
261 
262 } // namespace
263 
264 #endif // header guard
void registerInterface(T *iface)
Register an interface.
std::map< std::string, size_t > SizeMap
static T * newCI(boost::ptr_vector< ResourceManagerBase > &guards, typename C::resource_manager_type *)
static T * newCombinedInterface(boost::ptr_vector< ResourceManagerBase > &guards)
void registerInterfaceManager(InterfaceManager *iface_man)
std::vector< std::string > getNames() const
boost::ptr_vector< ResourceManagerBase > interface_destruction_list_
static T * newCI(boost::ptr_vector< ResourceManagerBase > &guards,...)
static void callCM(typename std::vector< C * > &managers, C *result, typename C::resource_manager_type *)
ResourceMap resources_
This will allow us to check the resources based on the demangled type name of the interface...
std::vector< InterfaceManager * > InterfaceManagerVector
InterfaceManagerVector interface_managers_
#define ROS_WARN_STREAM(args)
static void callCM(typename std::vector< C * > &managers, C *result,...)
static void callGR(std::vector< std::string > &resources, C *iface, typename C::resource_manager_type *)
std::map< std::string, std::vector< std::string > > ResourceMap
static const void callConcatManagers(typename std::vector< T * > &managers, T *result)
static void callGetResources(std::vector< std::string > &resources, T *iface)
std::vector< std::string > getInterfaceResources(std::string iface_type) const
Get the resource names registered to an interface, specified by type (as this class only stores one i...
#define ROS_ERROR_STREAM(args)
static void callGR(std::vector< std::string > &resources, T *iface,...)
#define ROS_ERROR(...)
std::map< std::string, void * > InterfaceMap


hardware_interface
Author(s): Wim Meeussen, Adolfo Rodriguez Tsouroukdissian
autogenerated on Mon Apr 20 2020 03:52:05