Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027
00031
00032
00033
00034 #ifndef CONTROLLER_INTERFACE_MULTI_INTERFACE_CONTROLLER_H
00035 #define CONTROLLER_INTERFACE_MULTI_INTERFACE_CONTROLLER_H
00036
00037 #include <algorithm>
00038 #include <sstream>
00039
00040 #include <controller_interface/controller_base.h>
00041 #include <hardware_interface/internal/demangle_symbol.h>
00042 #include <hardware_interface/robot_hw.h>
00043 #include <hardware_interface/hardware_interface.h>
00044 #include <ros/ros.h>
00045
00046 namespace controller_interface
00047 {
00048
00050 namespace internal
00051 {
00052
00053 template <class T>
00054 bool hasInterface(hardware_interface::RobotHW* robot_hw);
00055
00056 template <class T>
00057 void clearClaims(hardware_interface::RobotHW* robot_hw);
00058
00059 template <class T>
00060 void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in,
00061 hardware_interface::RobotHW* robot_hw_out);
00062
00063 template <class T>
00064 void populateClaimedResources(hardware_interface::RobotHW* robot_hw,
00065 std::set<std::string>& claimed_resources);
00066
00067 template <class T>
00068 std::string enumerateElements(const T& val,
00069 const std::string& delimiter = ", ",
00070 const std::string& prefix = "",
00071 const std::string& suffix = "");
00072
00073 }
00197 template <class T1, class T2 = void, class T3 = void, class T4 = void>
00198 class MultiInterfaceController: public ControllerBase
00199 {
00200 public:
00206 MultiInterfaceController(bool allow_optional_interfaces = false)
00207 : allow_optional_interfaces_(allow_optional_interfaces)
00208 {state_ = CONSTRUCTED;}
00209
00210 virtual ~MultiInterfaceController() {}
00211
00239 virtual bool init(hardware_interface::RobotHW* ,
00240 ros::NodeHandle& )
00241 {return true;}
00242
00269 virtual bool init(hardware_interface::RobotHW* ,
00270 ros::NodeHandle& ,
00271 ros::NodeHandle& )
00272 {return true;}
00273
00274 protected:
00297 virtual bool initRequest(hardware_interface::RobotHW* robot_hw,
00298 ros::NodeHandle& root_nh,
00299 ros::NodeHandle& controller_nh,
00300 std::set<std::string>& claimed_resources)
00301 {
00302
00303 if (state_ != CONSTRUCTED){
00304 ROS_ERROR("Cannot initialize this controller because it failed to be constructed");
00305 return false;
00306 }
00307
00308
00309 if (!allow_optional_interfaces_ && !hasRequiredInterfaces(robot_hw)) {return false;}
00310
00311
00312 hardware_interface::RobotHW* robot_hw_ctrl_p = &robot_hw_ctrl_;
00313 extractInterfaceResources(robot_hw, robot_hw_ctrl_p);
00314
00315
00316 clearClaims(robot_hw_ctrl_p);
00317 if (!init(robot_hw_ctrl_p, controller_nh) || !init(robot_hw_ctrl_p, root_nh, controller_nh))
00318 {
00319 ROS_ERROR("Failed to initialize the controller");
00320 return false;
00321 }
00322
00323
00324 claimed_resources.clear();
00325 populateClaimedResources(robot_hw_ctrl_p, claimed_resources);
00326 clearClaims(robot_hw_ctrl_p);
00327
00328
00329
00330
00331
00332 state_ = INITIALIZED;
00333 return true;
00334 }
00335
00336
00337
00338 virtual std::string getHardwareInterfaceType() const
00339 {
00340 return hardware_interface::internal::demangledTypeName<T1>();
00341 }
00342
00349 static bool hasRequiredInterfaces(hardware_interface::RobotHW* robot_hw)
00350 {
00351 using internal::hasInterface;
00352 return hasInterface<T1>(robot_hw) &&
00353 hasInterface<T2>(robot_hw) &&
00354 hasInterface<T3>(robot_hw) &&
00355 hasInterface<T4>(robot_hw);
00356 }
00357
00363 static void clearClaims(hardware_interface::RobotHW* robot_hw)
00364 {
00365 using internal::clearClaims;
00366 clearClaims<T1>(robot_hw);
00367 clearClaims<T2>(robot_hw);
00368 clearClaims<T3>(robot_hw);
00369 clearClaims<T4>(robot_hw);
00370 }
00371
00380 static void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in,
00381 hardware_interface::RobotHW* robot_hw_out)
00382 {
00383 using internal::extractInterfaceResources;
00384 extractInterfaceResources<T1>(robot_hw_in, robot_hw_out);
00385 extractInterfaceResources<T2>(robot_hw_in, robot_hw_out);
00386 extractInterfaceResources<T3>(robot_hw_in, robot_hw_out);
00387 extractInterfaceResources<T4>(robot_hw_in, robot_hw_out);
00388 }
00389
00398 static void populateClaimedResources(hardware_interface::RobotHW* robot_hw,
00399 std::set<std::string>& claimed_resources)
00400 {
00401 using internal::populateClaimedResources;
00402 populateClaimedResources<T1>(robot_hw, claimed_resources);
00403 populateClaimedResources<T2>(robot_hw, claimed_resources);
00404 populateClaimedResources<T3>(robot_hw, claimed_resources);
00405 populateClaimedResources<T4>(robot_hw, claimed_resources);
00406 }
00407
00409 hardware_interface::RobotHW robot_hw_ctrl_;
00410
00412 bool allow_optional_interfaces_;
00413
00414 private:
00415 MultiInterfaceController(const MultiInterfaceController& c);
00416 MultiInterfaceController& operator =(const MultiInterfaceController& c);
00417 };
00418
00419
00420 namespace internal
00421 {
00422
00423 template <class T>
00424 inline bool hasInterface(hardware_interface::RobotHW* robot_hw)
00425 {
00426 T* hw = robot_hw->get<T>();
00427 if (!hw)
00428 {
00429 const std::string hw_name = hardware_interface::internal::demangledTypeName<T>();
00430 ROS_ERROR_STREAM("This controller requires a hardware interface of type '" << hw_name << "', " <<
00431 "but is not exposed by the robot.");
00432
00433 return false;
00434 }
00435 return true;
00436 }
00437
00438
00439 template <>
00440 inline bool hasInterface<void>(hardware_interface::RobotHW* ) {return true;}
00441
00442 template <class T>
00443 void clearClaims(hardware_interface::RobotHW* robot_hw)
00444 {
00445 T* hw = robot_hw->get<T>();
00446 if (hw) {hw->clearClaims();}
00447 }
00448
00449
00450 template <>
00451 inline void clearClaims<void>(hardware_interface::RobotHW* ) {}
00452
00453 template <class T>
00454 inline void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in,
00455 hardware_interface::RobotHW* robot_hw_out)
00456 {
00457 T* hw = robot_hw_in->get<T>();
00458 if (hw) {robot_hw_out->registerInterface(hw);}
00459 }
00460
00461
00462 template <>
00463 inline void extractInterfaceResources<void>(hardware_interface::RobotHW* ,
00464 hardware_interface::RobotHW* ) {}
00465
00466 template <class T>
00467 inline void populateClaimedResources(hardware_interface::RobotHW* robot_hw,
00468 std::set<std::string>& claimed_resources)
00469 {
00470 T* hw = robot_hw->get<T>();
00471 if (hw)
00472 {
00473
00474
00475
00476
00477
00478
00479 claimed_resources = hw->getClaims();
00480 }
00481 }
00482
00483
00484 template <>
00485 inline void populateClaimedResources<void>(hardware_interface::RobotHW* ,
00486 std::set<std::string>& ) {}
00487
00488 template <class T>
00489 inline std::string enumerateElements(const T& val,
00490 const std::string& delimiter,
00491 const std::string& prefix,
00492 const std::string& suffix)
00493 {
00494 std::string ret;
00495 if (val.empty()) {return ret;}
00496
00497 const std::string sdp = suffix+delimiter+prefix;
00498 std::stringstream ss;
00499 ss << prefix;
00500 std::copy(val.begin(), val.end(), std::ostream_iterator<typename T::value_type>(ss, sdp.c_str()));
00501 ret = ss.str();
00502 if (!ret.empty()) {ret.erase(ret.size() - delimiter.size() - prefix.size());}
00503 return ret;
00504 }
00505
00506 }
00507
00508 }
00509
00510 #endif