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 { rm = get_robot_module_from_lib(name, args...); }
106  setup_canonical(rm);
107  return rm;
108  }
109 
114  static RobotModulePtr get_robot_module(const std::vector<std::string> & args);
115 
116  template<typename RetT, typename... Args>
117  static void register_object(const std::string & name, std::function<RetT *(const Args &...)> callback)
118  {
119  std::unique_lock<std::mutex> guard{mtx};
120  init();
121  robot_loader->register_object(name, callback);
122  }
123 
127  static void update_robot_module_path(const std::vector<std::string> & paths);
128 
130  static inline void clear()
131  {
132  std::lock_guard<std::mutex> guard{mtx};
133  init(true);
134  robot_loader->clear();
135  aliases.clear();
136  }
137 
141  static inline bool has_robot(const std::string & name)
142  {
143  std::lock_guard<std::mutex> guard{mtx};
144  init();
145  return robot_loader->has_object(name) || aliases.count(name) != 0;
146  }
147 
148  static inline void set_verbosity(bool verbose)
149  {
150  std::lock_guard<std::mutex> guard{mtx};
151  verbose_ = verbose;
152  if(robot_loader) { robot_loader->set_verbosity(verbose); }
153  }
154 
156  static std::vector<std::string> available_robots();
157 
165  static void load_aliases(const std::string & fname);
166 
167 private:
168  static void init(bool skip_default_path = false);
169 
170  template<typename... Args>
171  static void fill_rm_parameters(mc_rbdyn::RobotModulePtr & rm, const std::string & arg0, const Args &... args)
172  {
173  rm->_parameters.push_back(arg0);
174  fill_rm_parameters(rm, args...);
175  }
176 
177  static inline void fill_rm_parameters(mc_rbdyn::RobotModulePtr &) {}
178 
179  template<typename... Args>
180  static mc_rbdyn::RobotModulePtr get_robot_module_from_lib(const std::string & name, const Args &... args)
181  {
182  if(!robot_loader->has_object(name))
183  {
184  mc_rtc::log::error("Cannot load the requested robot: {}\nIt is neither a valid alias nor a known exported robot",
185  name);
186  mc_rtc::log::info("Available robots:");
187  mtx.unlock();
188  for(const auto & r : available_robots()) { mc_rtc::log::info("- {}", r); }
189  mc_rtc::log::error_and_throw<mc_rtc::LoaderException>("Cannot load the requested robot: {}", name);
190  }
191  mc_rbdyn::RobotModulePtr rm = robot_loader->create_object(name, args...);
192  if(!rm) { mc_rtc::log::error_and_throw("Failed to load {}", name); }
193  rm->_parameters = {name};
194  fill_rm_parameters(rm, args...);
195  return rm;
196  }
197 
198  static std::unique_ptr<mc_rtc::ObjectLoader<mc_rbdyn::RobotModule>> robot_loader;
199  static bool verbose_;
200  static std::mutex mtx;
201  static std::map<std::string, std::vector<std::string>> aliases;
202 }; // namespace mc_rbdyn
203 
204 } // namespace mc_rbdyn
mc_rbdyn::RobotLoader::get_robot_module
static mc_rbdyn::RobotModulePtr get_robot_module(const std::string &name, const Args &... args)
Definition: RobotLoader.h:75
mc_rbdyn::RobotLoader
Load RobotModule instances from shared libraries.
Definition: RobotLoader.h:64
mc_rtc::io::to_string
std::string to_string(const Container &c, const std::string &delimiter=", ")
Definition: io_utils.h:31
mc_rbdyn::Robot
Definition: Robot.h:62
RobotModule.h
mc_rbdyn::RobotLoader::set_verbosity
static void set_verbosity(bool verbose)
Definition: RobotLoader.h:148
mc_rbdyn::details::are_strings
Definition: RobotLoader.h:28
io_utils.h
mc_rtc::log::error_and_throw
void error_and_throw(Args &&... args)
Definition: logging.h:47
Robot.h
mc_rbdyn::RobotLoader::clear
static void clear()
Definition: RobotLoader.h:130
MC_RBDYN_DLLAPI
#define MC_RBDYN_DLLAPI
Definition: api.h:50
RobotConverter.h
mc_rtc::log::info
void info(Args &&... args)
Definition: logging.h:75
mc_rbdyn::details::to_string
std::conditional< std::is_same< std::string, T >::value, const std::string &, std::string >::type to_string(const T &value)
Definition: RobotLoader.h:51
mc_rtc::log::error
void error(Args &&... args)
Definition: logging.h:63
loader.h
ltdl wrapper for mc_rtc purpose
mc_rbdyn::RobotModulePtr
std::shared_ptr< RobotModule > RobotModulePtr
Definition: RobotModule.h:629
mc_rbdyn
Definition: generic_gripper.h:14
mc_rbdyn::RobotLoader::has_robot
static bool has_robot(const std::string &name)
Definition: RobotLoader.h:141
mc_rbdyn::RobotLoader::register_object
static void register_object(const std::string &name, std::function< RetT *(const Args &...)> callback)
Definition: RobotLoader.h:117