multi_interface_controller.h
Go to the documentation of this file.
00001 
00002 // Copyright (C) 2015, PAL Robotics S.L.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are met:
00006 //   * Redistributions of source code must retain the above copyright notice,
00007 //     this list of conditions and the following disclaimer.
00008 //   * Redistributions in binary form must reproduce the above copyright
00009 //     notice, this list of conditions and the following disclaimer in the
00010 //     documentation and/or other materials provided with the distribution.
00011 //   * Neither the names of PAL Robotics S.L. nor the names of its
00012 //     contributors may be used to endorse or promote products derived from
00013 //     this software without specific prior written permission.
00014 //
00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00019 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025 // POSSIBILITY OF SUCH DAMAGE.
00027 
00031 /* CAUTION: This code was just modified to be build in indigo for personal use.
00032  * multi_interface_controller is not officially support in indito.*/
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 } // namespace
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* /*robot_hw*/,
00240                     ros::NodeHandle&             /*controller_nh*/)
00241   {return true;}
00242 
00269   virtual bool init(hardware_interface::RobotHW* /*robot_hw*/,
00270                     ros::NodeHandle&             /*root_nh*/,
00271                     ros::NodeHandle&             /*controller_nh*/)
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     // check if construction finished cleanly
00303     if (state_ != CONSTRUCTED){
00304       ROS_ERROR("Cannot initialize this controller because it failed to be constructed");
00305       return false;
00306     }
00307 
00308     // check for required hardware interfaces
00309     if (!allow_optional_interfaces_ && !hasRequiredInterfaces(robot_hw)) {return false;}
00310 
00311     // populate robot hardware abstraction containing only controller hardware interfaces (subset of robot)
00312     hardware_interface::RobotHW* robot_hw_ctrl_p = &robot_hw_ctrl_;
00313     extractInterfaceResources(robot_hw, robot_hw_ctrl_p);
00314 
00315     // custom controller initialization
00316     clearClaims(robot_hw_ctrl_p); // claims will be populated on controller init
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     // populate claimed resources
00324     claimed_resources.clear();
00325     populateClaimedResources(robot_hw_ctrl_p, claimed_resources);
00326     clearClaims(robot_hw_ctrl_p);
00327     // NOTE: Above, claims are cleared since we only want to know what they are and report them back
00328     // as an output parameter. Actual resource claiming by the controller is done when the controller
00329     // is start()ed
00330 
00331     // initialization successful
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.");// Available interfaces in robot:\n" <<
00432                      //enumerateElements(robot_hw->getNames(), "\n", "- '", "'")); // delimiter, prefix, suffux
00433     return false;
00434   }
00435   return true;
00436 }
00437 
00438 // Specialization for unused template parameters defaulting to void
00439 template <>
00440 inline bool hasInterface<void>(hardware_interface::RobotHW* /*robot_hw*/) {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 // Specialization for unused template parameters defaulting to void
00450 template <>
00451 inline void clearClaims<void>(hardware_interface::RobotHW* /*robot_hw*/) {}
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 // Specialization for unused template parameters defaulting to void
00462 template <>
00463 inline void extractInterfaceResources<void>(hardware_interface::RobotHW* /*robot_hw_in*/,
00464                                             hardware_interface::RobotHW* /*robot_hw_out*/) {}
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     //hardware_interface::InterfaceResources iface_res;
00474     //iface_res.hardware_interface = hardware_interface::internal::demangledTypeName<T>();
00475     //iface_res.resources = hw->getClaims();
00476     //claimed_resources.push_back(iface_res);
00477 
00478     // TODO: must be fixed so that all claims to be registered
00479     claimed_resources = hw->getClaims();
00480   }
00481 }
00482 
00483 // Specialization for unused template parameters defaulting to void
00484 template <>
00485 inline void populateClaimedResources<void>(hardware_interface::RobotHW*      /*robot_hw*/,
00486                                             std::set<std::string>& /*claimed_resources*/) {}
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 } // namespace
00507 
00508 } // namespace
00509 
00510 #endif


steer_drive_controller
Author(s): CIR-KIT , Masaru Morita
autogenerated on Sat Jun 8 2019 19:20:25