mc_rtc  2.14.0
RobotLoader.h
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2019 CNRS-UM LIRMM, CNRS-AIST JRL
3  */
4 
5 #pragma once
6 
9 #include <mc_rbdyn/Robot.h>
11 #include <mc_rbdyn/RobotModule.h>
12 #include <mc_rtc/io_utils.h>
13 
14 #include <mc_rtc/config.h>
15 #include <mc_rtc/loader.h>
16 
17 #include <map>
18 #include <memory>
19 #include <mutex>
20 
21 namespace mc_rbdyn
22 {
23 
24 namespace details
25 {
26 
27 template<typename... Args>
28 struct are_strings : std::true_type
29 {
30 };
31 
32 template<typename T>
33 struct are_strings<T> : std::is_same<std::string, T>
34 {
35 };
36 
37 template<typename T, typename... Args>
38 struct are_strings<T, Args...> : std::integral_constant<bool, are_strings<T>::value && are_strings<Args...>::value>
39 {
40 };
41 
42 static_assert(are_strings<>::value, "OK");
43 static_assert(are_strings<std::string>::value, "OK");
46 static_assert(!are_strings<const char *>::value, "OK");
48 
49 // Construct a string from a provided argument if it's not one, otherwise just return the string
50 template<typename T>
51 typename std::conditional<std::is_same<std::string, T>::value, const std::string &, std::string>::type to_string(
52  const T & value)
53 {
54  static_assert(!std::is_integral<T>::value,
55  "Passing integral value here would create empty strings of the provided size");
56  return value;
57 }
58 
59 } // namespace details
60 
65 {
66 public:
74  template<typename... Args>
75  static mc_rbdyn::RobotModulePtr get_robot_module(const std::string & name, const Args &... args)
76  {
77  if(!details::are_strings<Args...>::value) { return get_robot_module(name, details::to_string(args)...); }
78  std::unique_lock<std::mutex> guard{mtx};
79  init();
80  mc_rbdyn::RobotModulePtr rm = nullptr;
81  auto setup_canonical = [](mc_rbdyn::RobotModulePtr rm)
82  {
83  assert(rm);
84  if(rm->_canonicalParameters.empty()) { rm->_canonicalParameters = rm->_parameters; }
85  if(!rm->controlToCanonicalPostProcess)
86  {
87  rm->controlToCanonicalPostProcess = [](const mc_rbdyn::Robot &, mc_rbdyn::Robot &) {};
88  }
89  };
90  if(aliases.count(name))
91  {
92  const auto & params = aliases[name];
93  if(params.size() == 1) { rm = get_robot_module_from_lib(params[0]); }
94  else if(params.size() == 2) { rm = get_robot_module_from_lib(params[0], params[1]); }
95  else if(params.size() == 3) { rm = get_robot_module_from_lib(params[0], params[1], params[2]); }
96  else
97  {
98  mc_rtc::log::error_and_throw<mc_rtc::LoaderException>(
99  "Aliases can only handle 1 to 3 parameters, {} provided ({})", params.size(),
100  mc_rtc::io::to_string(params));
101  }
102  rm->_parameters.resize(1);
103  rm->_parameters[0] = name;
104  }
105  else
106  {
107  rm = get_robot_module_from_lib(name, args...);
108  }
109  setup_canonical(rm);
110  return rm;
111  }
112 
117  static RobotModulePtr get_robot_module(const std::vector<std::string> & args);
118 
119  template<typename RetT, typename... Args>
120  static void register_object(const std::string & name, std::function<RetT *(const Args &...)> callback)
121  {
122  std::unique_lock<std::mutex> guard{mtx};
123  init();
124  robot_loader->register_object(name, callback);
125  }
126 
130  static void update_robot_module_path(const std::vector<std::string> & paths);
131 
133  static inline void clear()
134  {
135  std::lock_guard<std::mutex> guard{mtx};
136  init(true);
137  robot_loader->clear();
138  aliases.clear();
139  }
140 
144  static inline bool has_robot(const std::string & name)
145  {
146  std::lock_guard<std::mutex> guard{mtx};
147  init();
148  return robot_loader->has_object(name) || aliases.count(name) != 0;
149  }
150 
151  static inline void set_verbosity(bool verbose)
152  {
153  std::lock_guard<std::mutex> guard{mtx};
154  verbose_ = verbose;
155  if(robot_loader) { robot_loader->set_verbosity(verbose); }
156  }
157 
159  static std::vector<std::string> available_robots();
160 
168  static void load_aliases(const std::string & fname);
169 
170 private:
171  static void init(bool skip_default_path = false);
172 
173  template<typename... Args>
174  static void fill_rm_parameters(mc_rbdyn::RobotModulePtr & rm, const std::string & arg0, const Args &... args)
175  {
176  rm->_parameters.push_back(arg0);
177  fill_rm_parameters(rm, args...);
178  }
179 
180  static inline void fill_rm_parameters(mc_rbdyn::RobotModulePtr &) {}
181 
182  template<typename... Args>
183  static mc_rbdyn::RobotModulePtr get_robot_module_from_lib(const std::string & name, const Args &... args)
184  {
185  if(!robot_loader->has_object(name))
186  {
187  mc_rtc::log::error("Cannot load the requested robot: {}\nIt is neither a valid alias nor a known exported robot",
188  name);
189  mc_rtc::log::info("Available robots:");
190  mtx.unlock();
191  for(const auto & r : available_robots()) { mc_rtc::log::info("- {}", r); }
192  mc_rtc::log::error_and_throw<mc_rtc::LoaderException>("Cannot load the requested robot: {}", name);
193  }
194  mc_rbdyn::RobotModulePtr rm = robot_loader->create_object(name, args...);
195  if(!rm) { mc_rtc::log::error_and_throw("Failed to load {}", name); }
196  rm->_parameters = {name};
197  fill_rm_parameters(rm, args...);
198  return rm;
199  }
200 
201  static std::unique_ptr<mc_rtc::ObjectLoader<mc_rbdyn::RobotModule>> robot_loader;
202  static bool verbose_;
203  static std::mutex mtx;
204  static std::map<std::string, std::vector<std::string>> aliases;
205 }; // namespace mc_rbdyn
206 
207 } // namespace mc_rbdyn
#define MC_RBDYN_DLLAPI
Definition: api.h:50
ltdl wrapper for mc_rtc purpose
std::conditional< std::is_same< std::string, T >::value, const std::string &, std::string >::type to_string(const T &value)
Definition: RobotLoader.h:51
Definition: generic_gripper.h:15
std::shared_ptr< RobotModule > RobotModulePtr
Definition: RobotModule.h:632
std::string to_string(const Container &c, const std::string &delimiter=", ")
Definition: io_utils.h:31
void info(Args &&... args)
Definition: logging.h:75
void error_and_throw(Args &&... args)
Definition: logging.h:47
void error(Args &&... args)
Definition: logging.h:63
Load RobotModule instances from shared libraries.
Definition: RobotLoader.h:65
static RobotModulePtr get_robot_module(const std::vector< std::string > &args)
static void register_object(const std::string &name, std::function< RetT *(const Args &...)> callback)
Definition: RobotLoader.h:120
static bool has_robot(const std::string &name)
Definition: RobotLoader.h:144
static void update_robot_module_path(const std::vector< std::string > &paths)
static void set_verbosity(bool verbose)
Definition: RobotLoader.h:151
static void load_aliases(const std::string &fname)
static void clear()
Definition: RobotLoader.h:133
static std::vector< std::string > available_robots()
static mc_rbdyn::RobotModulePtr get_robot_module(const std::string &name, const Args &... args)
Definition: RobotLoader.h:75
Definition: Robot.h:63
Definition: RobotLoader.h:29