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 #pragma once
32 
33 
34 #include <map>
35 #include <string>
36 #include <vector>
37 
38 #include <ros/console.h>
39 
42 
43 namespace hardware_interface
44 {
45 
46 namespace internal
47 {
48 
49 // SFINAE workaround, so that we have reflection inside the template functions
50 template <typename T>
52  // method called if C is a ResourceManager
53  template <typename C>
54  static void callCM(typename std::vector<C*>& managers, C* result, typename C::resource_manager_type*)
55  {
56  // We have to typecast back to base class
57  std::vector<typename C::resource_manager_type*> managers_in(managers.begin(), managers.end());
58  C::concatManagers(managers_in, result);
59  }
60 
61  // method called if C is not a ResourceManager
62  template <typename C>
63  static void callCM(typename std::vector<C*>& /*managers*/, C* /*result*/, ...) {}
64 
65  // calls ResourceManager::concatManagers if C is a ResourceManager
66  static void callConcatManagers(typename std::vector<T*>& managers, T* result)
67  { callCM<T>(managers, result, nullptr); }
68 
69 
70  // method called if C is a ResourceManager
71  template <typename C>
72  static void callGR(std::vector<std::string> &resources, C* iface, typename C::resource_manager_type*)
73  {
74  resources = iface->getNames();
75  }
76 
77  // method called if C is not a ResourceManager
78  template <typename C>
79  static void callGR(std::vector<std::string> &/*resources*/, T* /*iface*/, ...) { }
80 
81  // calls ResourceManager::concatManagers if C is a ResourceManager
82  static void callGetResources(std::vector<std::string> &resources, T* iface)
83  { return callGR<T>(resources, iface, nullptr); }
84 
85  template <typename C>
86  static T* newCI(std::vector<ResourceManagerBase*> &guards, typename C::resource_manager_type*)
87  {
88  T* iface_combo = new T;
89  // save the new interface pointer to allow for its correct destruction
90  guards.push_back(static_cast<ResourceManagerBase*>(iface_combo));
91  return iface_combo;
92  }
93 
94  // method called if C is not a ResourceManager
95  template <typename C>
96  static T* newCI(std::vector<ResourceManagerBase*> &/*guards*/, ...) {
97  // it is not a ResourceManager
98  ROS_ERROR("You cannot register multiple interfaces of the same type which are "
99  "not of type ResourceManager. There is no established protocol "
100  "for combining them.");
101  return nullptr;
102  }
103 
104  static T* newCombinedInterface(std::vector<ResourceManagerBase*> &guards)
105  {
106  return newCI<T>(guards, nullptr);
107  }
108 
109 };
110 
111 } // namespace internal
112 
123 {
124 public:
137  template<class T>
138  void registerInterface(T* iface)
139  {
140  const std::string iface_name = internal::demangledTypeName<T>();
141  if (interfaces_.find(iface_name) != interfaces_.end())
142  {
143  ROS_WARN_STREAM("Replacing previously registered interface '" << iface_name << "'.");
144  }
145  interfaces_[iface_name] = iface;
146  internal::CheckIsResourceManager<T>::callGetResources(resources_[iface_name], iface);
147  }
148 
158  {
159  interface_managers_.push_back(iface_man);
160  }
161 
182  template<class T>
183  T* get()
184  {
185  std::string type_name = internal::demangledTypeName<T>();
186  std::vector<T*> iface_list;
187 
188  // look for interfaces registered here
189  InterfaceMap::iterator it = interfaces_.find(type_name);
190  if (it != interfaces_.end()) {
191  T* iface = static_cast<T*>(it->second);
192  if (!iface) {
193  ROS_ERROR_STREAM("Failed reconstructing type T = '" << type_name.c_str() <<
194  "'. This should never happen");
195  return nullptr;
196  }
197  iface_list.push_back(iface);
198  }
199 
200  // look for interfaces registered in the registered hardware
201  for (const auto& interface_manager : interface_managers_) {
202  T* iface = interface_manager->get<T>();
203  if (iface)
204  iface_list.push_back(iface);
205  }
206 
207  if(iface_list.size() == 0)
208  return nullptr;
209 
210  if(iface_list.size() == 1)
211  return iface_list.front();
212 
213  // if we're here, we have multiple interfaces, and thus we must construct a new
214  // combined interface, or return one already constructed
215  T* iface_combo;
216  InterfaceMap::iterator it_combo = interfaces_combo_.find(type_name);
217  if(it_combo != interfaces_combo_.end() &&
218  num_ifaces_registered_[type_name] == iface_list.size()) {
219  // there exists a combined interface with the same number of interfaces combined
220  // (since you cannot unregister interfaces, this will be guaranteed to be the
221  // same interfaces from previous calls)
222  iface_combo = static_cast<T*>(it_combo->second);
223  } else {
224  // no existing combined interface
225  iface_combo = internal::CheckIsResourceManager<T>::newCombinedInterface(interface_destruction_list_);
226  if(iface_combo) {
227  // concat all of the resource managers together
229  // save the combined interface for if this is called again
230  interfaces_combo_[type_name] = iface_combo;
231  num_ifaces_registered_[type_name] = iface_list.size();
232  } else {
233  // Multiple interfaces of the same type which are not ResourceManager cannot be combined, so return
234  // nullptr
235  iface_combo = nullptr;
236  }
237  }
238  return iface_combo;
239  }
240 
250  std::vector<std::string> getNames() const
251  {
252  std::vector<std::string> out;
253  out.reserve(interfaces_.size());
254  for (const auto& interface : interfaces_)
255  {
256  out.push_back(interface.first);
257  }
258 
259  for (const auto& interface_manager : interface_managers_)
260  {
261  // Make sure interfaces appear only once, as they may have been combined
262  for (const auto& interface_name : interface_manager->getNames())
263  {
264  if (std::find(out.begin(), out.end(), interface_name) == out.end())
265  {
266  out.push_back(interface_name);
267  }
268  }
269  }
270 
271  return out;
272  }
273 
283  std::vector<std::string> getInterfaceResources(std::string iface_type) const
284  {
285  std::vector<std::string> out;
286  ResourceMap::const_iterator it = resources_.find(iface_type);
287  if(it != resources_.end())
288  {
289  out = it->second;
290  }
291 
292  for (const auto& interface_manager : interface_managers_)
293  {
294  std::vector<std::string> resources = interface_manager->getInterfaceResources(iface_type);
295  out.insert(out.end(), resources.begin(), resources.end());
296  }
297 
298  return out;
299  }
300 
301 protected:
302  typedef std::map<std::string, void*> InterfaceMap;
303  typedef std::vector<InterfaceManager*> InterfaceManagerVector;
304  typedef std::map<std::string, size_t> SizeMap;
305  typedef std::map<std::string, std::vector<std::string> > ResourceMap;
306 
307  InterfaceMap interfaces_;
308  InterfaceMap interfaces_combo_;
309  InterfaceManagerVector interface_managers_;
311  std::vector<ResourceManagerBase*> interface_destruction_list_;
313  ResourceMap resources_;
314 };
315 
316 } // namespace
void registerInterface(T *iface)
Register an interface.
std::map< std::string, size_t > SizeMap
static void callCM(typename std::vector< C *> &managers, C *result, typename C::resource_manager_type *)
void registerInterfaceManager(InterfaceManager *iface_man)
Register another interface manager.
std::vector< ResourceManagerBase * > interface_destruction_list_
std::vector< std::string > getInterfaceResources(std::string iface_type) const
Get the resource names registered to an interface, specified by type.
static void callCM(typename std::vector< C *> &, C *,...)
static T * newCI(std::vector< ResourceManagerBase *> &guards, typename C::resource_manager_type *)
static void callConcatManagers(typename std::vector< T *> &managers, T *result)
ResourceMap resources_
This will allow us to check the resources based on the demangled type name of the interface...
static T * newCI(std::vector< ResourceManagerBase *> &,...)
static T * newCombinedInterface(std::vector< ResourceManagerBase *> &guards)
std::vector< InterfaceManager * > InterfaceManagerVector
std::vector< std::string > getNames() const
Lists the demangled names of all registered interfaces.
InterfaceManagerVector interface_managers_
#define ROS_WARN_STREAM(args)
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 void callGetResources(std::vector< std::string > &resources, T *iface)
#define ROS_ERROR_STREAM(args)
Manager for hardware interface registrations.
#define ROS_ERROR(...)
static void callGR(std::vector< std::string > &, T *,...)
std::map< std::string, void * > InterfaceMap


hardware_interface
Author(s): Wim Meeussen, Adolfo Rodriguez Tsouroukdissian
autogenerated on Mon Feb 28 2022 23:30:10