diff --git a/controller_interface/include/controller_interface/controller.h b/controller_interface/include/controller_interface/controller.h index 2a0195b35..604ba31ee 100644 --- a/controller_interface/include/controller_interface/controller.h +++ b/controller_interface/include/controller_interface/controller.h @@ -1,5 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2012, hiDOF INC. +// Copyright (C) 2015, PAL Robotics S.L. +// Copyright (C) 2018, Clearpath Robotics. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: @@ -8,7 +10,7 @@ // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// * Neither the name of hiDOF, Inc. nor the names of its +// * Neither the names of the copyright holders or the names of their // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -25,41 +27,150 @@ // POSSIBILITY OF SUCH DAMAGE. ////////////////////////////////////////////////////////////////////////////// -/* - * Author: Wim Meeussen - */ +/** + * \author Wim Meeussen + * \author Adolfo Rodríguez Tsouroukdissian + * \author Mike Purvis + * */ #ifndef CONTROLLER_INTERFACE_CONTROLLER_H #define CONTROLLER_INTERFACE_CONTROLLER_H #include -#include +#include #include #include -#include - +#include namespace controller_interface { -/** \brief %Controller with a specific hardware interface +/** + * \brief %Controller is able to claim resources from multiple hardware interfaces. + * + * This controller implementation allows to claim resources from one or + * more different hardware interfaces. The types of these hardware interfaces + * are specified as template parameters. + * + * An example multi-interface controller could claim, for instance, resources + * from a position-controlled arm and velocity-controlled wheels. Another + * example would be a controller claiming both position and effort interfaces + * for the same robot resources, but this would require a robot with a custom + * (non-exclusive) resource handling policy. + * + * By default, all specified hardware interfaces are required, and their + * existence will be enforced by \ref initRequest. It is possible to make hardware + * interfaces optional by means of the \c allow_optional_interfaces + * \ref Controller::Controller "constructor" parameter. + * This allows to write controllers where some interfaces are mandatory, and + * others, if present, improve controller performance, but whose absence does not + * prevent the controller from running. + * + * The following is an example of a controller claiming resources from velocity- + * and effort-controlled joints. + * + * \code + * #include + * #include + * + * using namespace hardware_interface; + * class VelEffController : public + * controller_interface::Controller + * { + * public: + * VelEffController() {} + * + * bool init(VelocityJointInterface* v, EffortJointInterface* e, ros::NodeHandle &n) + * // v and e are guaranteed to be valid. Fetch resources from them, + * // perform rest of initialization + * + * return true; + * } + * void starting(const ros::Time& time); + * void update(const ros::Time& time, const ros::Duration& period); + * void stopping(const ros::Time& time); + * }; + * \endcode + * + * The following fragment is a modified version of the above example, where + * controller interfaces are not required. It is left to the controller + * implementer to verify interface validity. Only the initialization code is + * shown. * - * \tparam T The hardware interface type used by this controller. This enforces - * semantic compatibility between the controller and the hardware it's meant to - * control. + * \code + * class VelEffController : public + * controller_interface::Controller + * { + * public: + * // Note true flag passed to parent class, allowing requested hardware + * // interfaces to be optional + * VelEffController() + * : controller_interface::Controller (true) + * {} + * + * bool init(VelocityJointInterface* v, EffortJointInterface* e, ros::NodeHandle &n) + * { + * // v is a required interface + * if (!v) + * { + * return false; + * } + * + * // e is an optional interface. If present, additional features are enabled. + * // Controller can still function if interface or some of its resources are + * // absent + * if (e) + * { + * // ... + * } + * + * // Fetch resources from interfaces, perform rest of initialization + * // ... + * + * return true; + * } + * ... + * }; + * \endcode + * + * \tparam T... Hardware interface types. + * This parameter is \e required. */ -template +template class Controller: public virtual ControllerBase { public: - Controller() {state_ = CONSTRUCTED;} - virtual ~Controller(){} + /** + * \param allow_optional_interfaces If set to true, \ref initRequest will + * not fail if one or more of the requested interfaces is not present. + * If set to false (the default), all requested interfaces are required. + */ + Controller(bool allow_optional_interfaces = false) + : allow_optional_interfaces_(allow_optional_interfaces) + {state_ = CONSTRUCTED;} - /** \brief The init function is called to initialize the controller from a - * non-realtime thread with a pointer to the hardware interface, itself, - * instead of a pointer to a RobotHW. + virtual ~Controller() {} + + /** \name Non Real-Time Safe Functions + *\{*/ + + /** + * \brief Custom controller initialization logic. + * + * In this method resources from different interfaces are claimed, and other + * non real-time initialization is performed, such as setup of ROS interfaces + * and resource pre-allocation. * - * \param hw The specific hardware interface used by this controller. + * \param interfaces Pointers to the hardware interfaces used by this + * controller, as specified in the template parameter pack. + * If \ref Controller::Controller was called with \c allow_optional_interfaces + * set to \c false (the default), all pointers will be valid and non-NULL. + * If \c allow_optional_interfaces was set to \c true, some or all of the + * interface pointers may be NULL, and must be individually checked. + * Please refer to the code examples in the \ref Controller class description. * * \param controller_nh A NodeHandle in the namespace from which the controller * should read its configuration, and where it should set up its ROS @@ -68,13 +179,26 @@ class Controller: public virtual ControllerBase * \returns True if initialization was successful and the controller * is ready to be started. */ - virtual bool init(T* /*hw*/, ros::NodeHandle& /*controller_nh*/) {return true;}; + virtual bool init(Interfaces*... /*interfaces*/, + ros::NodeHandle& /*controller_nh*/) + { + return true; + } - /** \brief The init function is called to initialize the controller from a - * non-realtime thread with a pointer to the hardware interface, itself, - * instead of a pointer to a RobotHW. + /** + * \brief Custom controller initialization logic. + * + * In this method resources from different interfaces are claimed, and other + * non real-time initialization is performed, such as setup of ROS interfaces + * and resource pre-allocation. * - * \param hw The specific hardware interface used by this controller. + * \param interfaces Pointers to the hardware interfaces used by this + * controller, as specified in the template parameter pack. + * If \ref Controller::Controller was called with \c allow_optional_interfaces + * set to \c false (the default), all pointers will be valid and non-NULL. + * If \c allow_optional_interfaces was set to \c true, some or all of the + * interface pointers may be NULL, and must be individually checked. + * Please refer to the code examples in the \ref Controller class description. * * \param root_nh A NodeHandle in the root of the controller manager namespace. * This is where the ROS interfaces are setup (publishers, subscribers, services). @@ -85,65 +209,106 @@ class Controller: public virtual ControllerBase * \returns True if initialization was successful and the controller * is ready to be started. */ - virtual bool init(T* /*hw*/, ros::NodeHandle& /*root_nh*/, ros::NodeHandle& /*controller_nh*/) {return true;}; + virtual bool init(Interfaces*... /*interfaces*/, + ros::NodeHandle& /*root_nh*/, + ros::NodeHandle& /*controller_nh*/) + { + return true; + } protected: - /** \brief Initialize the controller from a RobotHW pointer + /** + * \brief Initialize the controller from a RobotHW pointer. + * + * This calls the user-supplied \ref init method with the hardware interfaces + * from the \c robot_hw pointer, some or all of which may be NULL, depending + * on the value of \c allow_optional_interfaces passed to the constructor. + * + * \param robot_hw The robot hardware abstraction. + * + * \param root_nh A NodeHandle in the root of the controller manager namespace. + * This is where the ROS interfaces are setup (publishers, subscribers, services). + * + * \param controller_nh A NodeHandle in the namespace of the controller. + * This is where the controller-specific configuration resides. * - * This calls \ref init with the hardware interface for this controller if it - * can extract the correct interface from \c robot_hw. + * \param[out] claimed_resources The resources claimed by this controller. + * They can belong to multiple hardware interfaces. * + * \returns True if initialization was successful and the controller + * is ready to be started. */ virtual bool initRequest(hardware_interface::RobotHW* robot_hw, ros::NodeHandle& root_nh, ros::NodeHandle& controller_nh, ClaimedResources& claimed_resources) { - // check if construction finished cleanly + // Check if construction finished cleanly. if (state_ != CONSTRUCTED){ - ROS_ERROR("Cannot initialize this controller because it failed to be constructed"); + ROS_ERROR("Cannot initialize this controller because it failed to be constructed."); return false; } - // get a pointer to the hardware interface - T* hw = robot_hw->get(); - if (!hw) + // Check for required hardware interfaces. + if (!allow_optional_interfaces_ && !internal::hasInterfaces(robot_hw)) { - ROS_ERROR("This controller requires a hardware interface of type '%s'." - " Make sure this is registered in the hardware_interface::RobotHW class.", - getHardwareInterfaceType().c_str()); + // Error message has already been sent by the checking function. return false; } - // return which resources are claimed by this controller - hw->clearClaims(); - if (!init(hw, controller_nh) || !init(hw, root_nh, controller_nh)) + // Custom controller initialization. + if (!init(robot_hw->get()..., controller_nh) || + !init(robot_hw->get()..., root_nh, controller_nh)) { - ROS_ERROR("Failed to initialize the controller"); + ROS_ERROR("Failed to initialize the controller."); return false; } - hardware_interface::InterfaceResources iface_res(getHardwareInterfaceType(), hw->getClaims()); - claimed_resources.assign(1, iface_res); - hw->clearClaims(); - // success + // Populate claimed resources. + claimed_resources.clear(); + internal::populateClaimedResources(robot_hw, claimed_resources); + internal::clearClaims(robot_hw); + // NOTE: Above, claims are cleared since we only want to know what they are and report them back + // as an output parameter. Actual resource claiming by the controller is done when the controller + // is start()ed + + // Initialization has succeeded. state_ = INITIALIZED; return true; } - /// Get the name of this controller's hardware interface type - std::string getHardwareInterfaceType() const + /** + * This is provided for compatibility with Controller from when it only took a single hardware + * interface. It can't be used when Controller has more than on interface type. + */ + ROS_DEPRECATED std::string getHardwareInterfaceType() const { - return hardware_interface::internal::demangledTypeName(); + return hardware_interface::internal::demangledTypeName(); } + /*\}*/ + private: - Controller(const Controller &c); - Controller& operator =(const Controller &c); + /** Flag to indicate if hardware interfaces are considered optional (i.e. non-required). */ + bool allow_optional_interfaces_; + + /** + * Construction by copying prohibited. Controllers are not copyable. + */ + Controller(const Controller& c); + + /** + * Construction by assignment prohibited. Controllers are not copyable. + */ + Controller& operator =(const Controller& c); + // Everything other than this line actually compiles just fine under gcc without -std=c++11, + // barring warnings about varidic templates being unsupported. This guard can be removed in Melodic + // when the compiler is c++14 by default. + static_assert(sizeof...(Interfaces) >= 1, "Controller must have at least one hardware interface."); }; -} +} // namespace #endif diff --git a/controller_interface/include/controller_interface/internal/robothw_interfaces.h b/controller_interface/include/controller_interface/internal/robothw_interfaces.h index 46dfda02e..c47d36914 100644 --- a/controller_interface/include/controller_interface/internal/robothw_interfaces.h +++ b/controller_interface/include/controller_interface/internal/robothw_interfaces.h @@ -56,14 +56,14 @@ inline std::string enumerateElements(const T& val, const std::string sdp = suffix+delimiter+prefix; std::stringstream ss; ss << prefix; - std::copy(val.begin(), val.end(), std::ostream_iterator(ss, sdp.c_str())); + std::copy(val.begin(), val.end(), std::ostream_iterator(ss, sdp.c_str())); ret = ss.str(); if (!ret.empty()) {ret.erase(ret.size() - delimiter.size() - prefix.size());} return ret; } -template +template inline bool hasInterfaces(hardware_interface::RobotHW* robot_hw) { T* hw = robot_hw->get(); @@ -78,14 +78,14 @@ inline bool hasInterfaces(hardware_interface::RobotHW* robot_hw) return true; } -template +template inline bool hasInterfaces(hardware_interface::RobotHW* robot_hw) { return hasInterfaces(robot_hw) && hasInterfaces(robot_hw); } -template +template void clearClaims(hardware_interface::RobotHW* robot_hw) { T* hw = robot_hw->get(); @@ -95,7 +95,7 @@ void clearClaims(hardware_interface::RobotHW* robot_hw) } } -template +template void clearClaims(hardware_interface::RobotHW* robot_hw) { clearClaims(robot_hw); @@ -103,7 +103,7 @@ void clearClaims(hardware_interface::RobotHW* robot_hw) } -template +template inline void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in, hardware_interface::RobotHW* robot_hw_out) { @@ -111,7 +111,7 @@ inline void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in, if (hw) {robot_hw_out->registerInterface(hw);} } -template +template inline void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in, hardware_interface::RobotHW* robot_hw_out) { @@ -120,7 +120,24 @@ inline void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in, } -template +template +inline void populateInterfaces(hardware_interface::RobotHW* robot_hw, T hw) +{ + if (hw) + { + robot_hw->registerInterface(hw); + } +} + +template +inline void populateInterfaces(hardware_interface::RobotHW* robot_hw, T hw, More... more) +{ + populateInterfaces(robot_hw, hw); + populateInterfaces(robot_hw, more...); +} + + +template inline void populateClaimedResources(hardware_interface::RobotHW* robot_hw, ControllerBase::ClaimedResources& claimed_resources) { @@ -134,7 +151,7 @@ inline void populateClaimedResources(hardware_interface::RobotHW* robot_hw, } } -template +template inline void populateClaimedResources(hardware_interface::RobotHW* robot_hw, ControllerBase::ClaimedResources& claimed_resources) { diff --git a/controller_interface/include/controller_interface/multi_interface_controller.h b/controller_interface/include/controller_interface/multi_interface_controller.h index dbc8e5d79..e5768eda4 100644 --- a/controller_interface/include/controller_interface/multi_interface_controller.h +++ b/controller_interface/include/controller_interface/multi_interface_controller.h @@ -25,325 +25,73 @@ // POSSIBILITY OF SUCH DAMAGE. ////////////////////////////////////////////////////////////////////////////// -/** \author Adolfo Rodríguez Tsouroukdissian */ +/** \author Mike Purvis */ #ifndef CONTROLLER_INTERFACE_MULTI_INTERFACE_CONTROLLER_H #define CONTROLLER_INTERFACE_MULTI_INTERFACE_CONTROLLER_H -#include +#warning MultiInterfaceController is deprecated. Please use Controller instead. + +#include #include -#include -#include -#include #include namespace controller_interface { /** - * \brief %Controller able to claim resources from multiple hardware interfaces. - * - * This particular controller implementation allows to claim resources from one - * up to four different hardware interfaces. The types of these hardware - * interfaces are specified as template parameters. - * - * An example multi-interface controller could claim, for instance, resources - * from a position-controlled arm and velocity-controlled wheels. Another - * example would be a controller claiming both position and effort interfaces - * for the same robot resources, but this would require a robot with a custom - * (non-exclusive) resource handling policy. - * - * By default, all specified hardware interfaces are required, and their - * existence will be enforced by \ref initRequest. It is possible to make hardware - * interfaces optional by means of the \c allow_optional_interfaces - * \ref MultiInterfaceController::MultiInterfaceController "constructor" parameter. - * This allows to write controllers where some interfaces are mandatory, and - * others, if present, improve controller performance, but whose absence does not - * prevent the controller from running. - * - * The following is an example of a controller claiming resources from velocity- - * and effort-controlled joints. - * - * \code - * #include - * #include - * - * using namespace hardware_interface; - * class VelEffController : public - * controller_interface::MultiInterfaceController - * { - * public: - * VelEffController() {} - * - * bool init(hardware_interface::RobotHW* robot_hw, ros::NodeHandle &n) - * { - * // robot_hw pointer only contains the two interfaces requested by the - * // controller. It is a subset of the entire robot, which may have more - * // hardware interfaces - * - * // v and e below are guarranteed to be valid - * VelocityJointInterface* v = robot_hw->get(); - * EffortJointInterface* e = robot_hw->get(); - * - * // Fetch resources from interfaces, perform rest of initialization - * //... - * - * return true; - * } - * void starting(const ros::Time& time); - * void update(const ros::Time& time, const ros::Duration& period); - * void stopping(const ros::Time& time); - * }; - * \endcode - * - * The following fragment is a modified version of the above example, where - * controller interfaces are not required. It is left to the controller - * implementer to verify interface validity. Only the initialization code is - * shown. - * - * \code - * class VelEffController : public - * controller_interface::MultiInterfaceController - * { - * public: - * // Note true flag passed to parent class, allowing requested hardware - * // interfaces to be optional - * VelEffController() - * : controller_interface::MultiInterfaceController (true) - * {} - * - * bool init(hardware_interface::RobotHW* robot_hw, ros::NodeHandle &n) - * { - * // robot_hw pointer contains at most the two interfaces requested by the - * // controller. It may have none, only one or both, depending on whether the - * // robot exposes them - * - * // v is a required interface - * VelocityJointInterface* v = robot_hw->get(); - * if (!v) - * { - * return false; - * } - * - * // e is an optional interface. If present, additional features are enabled. - * // Controller can still function if interface or some of its resources are - * // absent - * EffortJointInterface* e = robot_hw->get(); - * - * // Fetch resources from interfaces, perform rest of initialization - * //... - * - * return true; - * } - * ... - * }; - * \endcode - * - * \tparam T... Hardware interface types. - * This parameter is \e required. + * \brief Adapter class providing the old MultiInterfaceController API. */ -template -class MultiInterfaceController: public virtual ControllerBase +template +class MultiInterfaceController: public Controller { public: - /** - * \param allow_optional_interfaces If set to true, \ref initRequest will - * not fail if one or more of the requested interfaces is not present. - * If set to false (the default), all requested interfaces are required. - */ - MultiInterfaceController(bool allow_optional_interfaces = false) - : allow_optional_interfaces_(allow_optional_interfaces) - {state_ = CONSTRUCTED;} - - virtual ~MultiInterfaceController() {} + using Controller::Controller; /** \name Non Real-Time Safe Functions *\{*/ - /** - * \brief Custom controller initialization logic. - * - * In this method resources from different interfaces are claimed, and other - * non real-time initialization is performed, such as setup of ROS interfaces - * and resource pre-allocation. - * - * \param robot_hw Robot hardware abstraction containing a subset of the entire - * robot. If \ref MultiInterfaceController::MultiInterfaceController - * "MultiInterfaceController" was called with \c allow_optional_interfaces set - * to \c false (the default), this parameter contains all the interfaces - * requested by the controller. - * If \c allow_optional_interfaces was set to \c false, this parameter may - * contain none, some or all interfaces requested by the controller, depending - * on whether the robot exposes them. Please refer to the code examples in the - * \ref MultiInterfaceController "class description". - * - * \param controller_nh A NodeHandle in the namespace from which the controller - * should read its configuration, and where it should set up its ROS - * interface. - * - * \returns True if initialization was successful and the controller - * is ready to be started. - */ virtual bool init(hardware_interface::RobotHW* /*robot_hw*/, - ros::NodeHandle& /*controller_nh*/) - {return true;} - - /** - * \brief Custom controller initialization logic. - * - * In this method resources from different interfaces are claimed, and other - * non real-time initialization is performed, such as setup of ROS interfaces - * and resource pre-allocation. - * - * \param robot_hw Robot hardware abstraction containing a subset of the entire - * robot. If \ref MultiInterfaceController::MultiInterfaceController - * "MultiInterfaceController" was called with \c allow_optional_interfaces set - * to \c false (the default), this parameter contains all the interfaces - * requested by the controller. - * If \c allow_optional_interfaces was set to \c false, this parameter may - * contain none, some or all interfaces requested by the controller, depending - * on whether the robot exposes them. Please refer to the code examples in the - * \ref MultiInterfaceController "class description". - * - * \param root_nh A NodeHandle in the root of the controller manager namespace. - * This is where the ROS interfaces are setup (publishers, subscribers, services). - * - * \param controller_nh A NodeHandle in the namespace of the controller. - * This is where the controller-specific configuration resides. - * - * \returns True if initialization was successful and the controller - * is ready to be started. - */ - virtual bool init(hardware_interface::RobotHW* /*robot_hw*/, - ros::NodeHandle& /*root_nh*/, - ros::NodeHandle& /*controller_nh*/) - {return true;} - -protected: - /** - * \brief Initialize the controller from a RobotHW pointer. - * - * This calls \ref init with a RobotHW that is a subset of the input - * \c robot_hw parameter, containing only the requested hardware interfaces - * (all or some, depending on the value of \c allow_optional_interfaces passed - * to the constructor). - * - * \param robot_hw The robot hardware abstraction. - * - * \param root_nh A NodeHandle in the root of the controller manager namespace. - * This is where the ROS interfaces are setup (publishers, subscribers, services). - * - * \param controller_nh A NodeHandle in the namespace of the controller. - * This is where the controller-specific configuration resides. - * - * \param[out] claimed_resources The resources claimed by this controller. - * They can belong to multiple hardware interfaces. - * - * \returns True if initialization was successful and the controller - * is ready to be started. - */ - virtual bool initRequest(hardware_interface::RobotHW* robot_hw, - ros::NodeHandle& root_nh, - ros::NodeHandle& controller_nh, - ClaimedResources& claimed_resources) + ros::NodeHandle& /*controller_nh*/) { - // check if construction finished cleanly - if (state_ != CONSTRUCTED){ - ROS_ERROR("Cannot initialize this controller because it failed to be constructed"); - return false; - } - - // check for required hardware interfaces - if (!allow_optional_interfaces_ && !hasRequiredInterfaces(robot_hw)) {return false;} - - // populate robot hardware abstraction containing only controller hardware interfaces (subset of robot) - hardware_interface::RobotHW* robot_hw_ctrl_p = &robot_hw_ctrl_; - extractInterfaceResources(robot_hw, robot_hw_ctrl_p); - - // custom controller initialization - clearClaims(robot_hw_ctrl_p); // claims will be populated on controller init - if (!init(robot_hw_ctrl_p, controller_nh) || !init(robot_hw_ctrl_p, root_nh, controller_nh)) - { - ROS_ERROR("Failed to initialize the controller"); - return false; - } - - // populate claimed resources - claimed_resources.clear(); - populateClaimedResources(robot_hw_ctrl_p, claimed_resources); - clearClaims(robot_hw_ctrl_p); - // NOTE: Above, claims are cleared since we only want to know what they are and report them back - // as an output parameter. Actual resource claiming by the controller is done when the controller - // is start()ed - - // initialization successful - state_ = INITIALIZED; return true; } - /*\}*/ - - /** - * \brief Check if robot hardware abstraction contains all required interfaces. - * \param robot_hw Robot hardware abstraction. - * \return true if all required hardware interfaces are exposed by \c robot_hw, - * false otherwise. - */ - static bool hasRequiredInterfaces(hardware_interface::RobotHW* robot_hw) + virtual bool init(hardware_interface::RobotHW* /*robot_hw*/, + ros::NodeHandle& /*root_nh*/, + ros::NodeHandle& /*controller_nh*/) { - return internal::hasInterfaces(robot_hw); + return true; } +private: /** - * \brief Clear claims from all hardware interfaces requested by this controller. - * \param robot_hw Robot hardware abstraction containing the interfaces whose - * claims will be cleared. + * \brief Overrides the new-API init function in the base class, + * and calls through to the virtual method with the old API. */ - static void clearClaims(hardware_interface::RobotHW* robot_hw) + bool init(Interfaces*... interfaces, + ros::NodeHandle& controller_nh) override { - internal::clearClaims(robot_hw); + internal::populateInterfaces(&robot_hw_ctrl_, interfaces...); + return init(&robot_hw_ctrl_, controller_nh); } /** - * \brief Extract all hardware interfaces requested by this controller from - * \c robot_hw_in, and add them also to \c robot_hw_out. - * \param[in] robot_hw_in Robot hardware abstraction containing the interfaces - * requested by this controller, and potentially others. - * \param[out] robot_hw_out Robot hardware abstraction containing \e only the - * interfaces requested by this controller. + * \brief Overrides the new-API init function in the base class, + * and calls through to the virtual method with the old API. */ - static void extractInterfaceResources(hardware_interface::RobotHW* robot_hw_in, - hardware_interface::RobotHW* robot_hw_out) + bool init(Interfaces*... interfaces, + ros::NodeHandle& root_nh, + ros::NodeHandle& controller_nh) override { - internal::extractInterfaceResources(robot_hw_in, robot_hw_out); + internal::populateInterfaces(&robot_hw_ctrl_, interfaces...); + return init(&robot_hw_ctrl_, root_nh, controller_nh); } /** - * \brief Extract all hardware interfaces requested by this controller from - * \c robot_hw_in, and add them also to \c robot_hw_out. - * \param[in] robot_hw_in Robot hardware abstraction containing the interfaces - * requested by this controller, and potentially others. - * \param[out] claimed_resources The resources claimed by this controller. - * They can belong to multiple hardware interfaces. + * Robot hardware abstraction containing only the subset of interfaces requested by the controller. */ - static void populateClaimedResources(hardware_interface::RobotHW* robot_hw, - ClaimedResources& claimed_resources) - { - internal::populateClaimedResources(robot_hw, claimed_resources); - } - - /** Robot hardware abstraction containing only the subset of interfaces requested by the controller. */ hardware_interface::RobotHW robot_hw_ctrl_; - - /** Flag to indicate if hardware interfaces are considered optional (i.e. non-required). */ - bool allow_optional_interfaces_; - -private: - MultiInterfaceController(const MultiInterfaceController& c); - MultiInterfaceController& operator =(const MultiInterfaceController& c); }; } // namespace diff --git a/controller_interface/package.xml b/controller_interface/package.xml index ddfe6f362..0f4b4e4bc 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -15,7 +15,7 @@ Wim Meeussen catkin - + hardware_interface pluginlib roscpp