controller_manager_plugin.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2015, Fraunhofer IPA
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Fraunhofer IPA nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Mathias Lüdtke */
36 
37 #include <ros/ros.h>
38 
40 
42 
44 
45 #include <controller_manager_msgs/ListControllers.h>
46 #include <controller_manager_msgs/SwitchController.h>
47 
50 
51 #include <boost/bimap.hpp>
52 
53 #include <map>
54 #include <memory>
55 
57 {
65 bool checkTimeout(ros::Time& t, double timeout, bool force = false)
66 {
68  if (force || (now - t) >= ros::Duration(timeout))
69  {
70  t = now;
71  return true;
72  }
73  return false;
74 }
75 
76 MOVEIT_CLASS_FORWARD(MoveItControllerManager); // Defines MoveItControllerManagerPtr, ConstPtr, WeakPtr... etc
77 
84 class MoveItControllerManager : public moveit_controller_manager::MoveItControllerManager
85 {
86  const std::string ns_;
88  typedef std::map<std::string, controller_manager_msgs::ControllerState> ControllersMap;
91  typedef std::map<std::string, ControllerHandleAllocatorPtr> AllocatorsMap;
93 
94  typedef std::map<std::string, moveit_controller_manager::MoveItControllerHandlePtr> HandleMap;
96 
98  boost::mutex controllers_mutex_;
99 
105  static bool isActive(const controller_manager_msgs::ControllerState& s)
106  {
107  return s.state == std::string("running");
108  }
109 
116  void discover(bool force = false)
117  {
118  if (!checkTimeout(controllers_stamp_, 1.0, force))
119  return;
120 
121  controller_manager_msgs::ListControllers srv;
122  if (!ros::service::call(getAbsName("controller_manager/list_controllers"), srv))
123  {
124  ROS_WARN_STREAM("Failed to read controllers from " << ns_ << "controller_manager/list_controllers");
125  }
128  for (const controller_manager_msgs::ControllerState& controller : srv.response.controller)
129  {
130  if (isActive(controller))
131  {
132  active_controllers_.insert(std::make_pair(controller.name, controller)); // without namespace
133  }
134  if (loader_.isClassAvailable(controller.type))
135  {
136  std::string absname = getAbsName(controller.name);
137  managed_controllers_.insert(std::make_pair(absname, controller)); // with namespace
138  allocate(absname, controller);
139  }
140  }
141  }
142 
149  void allocate(const std::string& name, const controller_manager_msgs::ControllerState& controller)
150  {
151  if (handles_.find(name) == handles_.end())
152  {
153  const std::string& type = controller.type;
154  AllocatorsMap::iterator alloc_it = allocators_.find(type);
155  if (alloc_it == allocators_.end())
156  { // create allocator is needed
157  alloc_it = allocators_.insert(std::make_pair(type, loader_.createUniqueInstance(type))).first;
158  }
159 
160  std::vector<std::string> resources;
161  // Collect claimed resources across different hardware interfaces
162  for (const controller_manager_msgs::HardwareInterfaceResources& claimed_resource : controller.claimed_resources)
163  {
164  for (const std::string& resource : claimed_resource.resources)
165  {
166  resources.push_back(resource);
167  }
168  }
169 
170  moveit_controller_manager::MoveItControllerHandlePtr handle =
171  alloc_it->second->alloc(name, resources); // allocate handle
172  if (handle)
173  handles_.insert(std::make_pair(name, handle));
174  }
175  }
176 
182  std::string getAbsName(const std::string& name)
183  {
184  return ros::names::append(ns_, name);
185  }
186 
187 public:
192  : ns_(ros::NodeHandle("~").param("ros_control_namespace", std::string("/")))
193  , loader_("moveit_ros_control_interface", "moveit_ros_control_interface::ControllerHandleAllocator")
194  {
195  ROS_INFO_STREAM("Started moveit_ros_control_interface::MoveItControllerManager for namespace " << ns_);
196  }
197 
202  MoveItControllerManager(const std::string& ns)
203  : ns_(ns), loader_("moveit_ros_control_interface", "moveit_ros_control_interface::ControllerHandleAllocator")
204  {
205  }
206 
212  moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string& name) override
213  {
214  boost::mutex::scoped_lock lock(controllers_mutex_);
215  HandleMap::iterator it = handles_.find(name);
216  if (it != handles_.end())
217  { // controller is is manager by this interface
218  return it->second;
219  }
220  return moveit_controller_manager::MoveItControllerHandlePtr();
221  }
222 
227  void getControllersList(std::vector<std::string>& names) override
228  {
229  boost::mutex::scoped_lock lock(controllers_mutex_);
230  discover();
231 
232  for (std::pair<const std::string, controller_manager_msgs::ControllerState>& managed_controller :
234  {
235  names.push_back(managed_controller.first);
236  }
237  }
238 
243  void getActiveControllers(std::vector<std::string>& names) override
244  {
245  boost::mutex::scoped_lock lock(controllers_mutex_);
246  discover();
247 
248  for (std::pair<const std::string, controller_manager_msgs::ControllerState>& managed_controller :
250  {
251  if (isActive(managed_controller.second))
252  names.push_back(managed_controller.first);
253  }
254  }
255 
261  void getControllerJoints(const std::string& name, std::vector<std::string>& joints) override
262  {
263  boost::mutex::scoped_lock lock(controllers_mutex_);
264  ControllersMap::iterator it = managed_controllers_.find(name);
265  if (it != managed_controllers_.end())
266  {
267  for (controller_manager_msgs::HardwareInterfaceResources& claimed_resource : it->second.claimed_resources)
268  {
269  std::vector<std::string>& resources = claimed_resource.resources;
270  joints.insert(joints.end(), resources.begin(), resources.end());
271  }
272  }
273  }
274 
280  ControllerState getControllerState(const std::string& name) override
281  {
282  boost::mutex::scoped_lock lock(controllers_mutex_);
283  discover();
284 
285  ControllerState c;
286  ControllersMap::iterator it = managed_controllers_.find(name);
287  if (it != managed_controllers_.end())
288  {
289  c.active_ = isActive(it->second);
290  }
291  return c;
292  }
293 
301  bool switchControllers(const std::vector<std::string>& activate, const std::vector<std::string>& deactivate) override
302  {
303  boost::mutex::scoped_lock lock(controllers_mutex_);
304  discover(true);
305 
306  typedef boost::bimap<std::string, std::string> resources_bimap;
307 
308  resources_bimap claimed_resources;
309 
310  // fill bimap with active controllers and their resources
311  for (std::pair<const std::string, controller_manager_msgs::ControllerState>& active_controller : active_controllers_)
312  {
313  for (std::vector<controller_manager_msgs::HardwareInterfaceResources>::iterator hir =
314  active_controller.second.claimed_resources.begin();
315  hir != active_controller.second.claimed_resources.end(); ++hir)
316  {
317  for (std::string& resource : hir->resources)
318  {
319  claimed_resources.insert(resources_bimap::value_type(active_controller.second.name, resource));
320  }
321  }
322  }
323 
324  controller_manager_msgs::SwitchController srv;
325 
326  for (const std::string& it : deactivate)
327  {
328  ControllersMap::iterator c = managed_controllers_.find(it);
329  if (c != managed_controllers_.end())
330  { // controller belongs to this manager
331  srv.request.stop_controllers.push_back(c->second.name);
332  claimed_resources.right.erase(c->second.name); // remove resources
333  }
334  }
335 
336  for (const std::string& it : activate)
337  {
338  ControllersMap::iterator c = managed_controllers_.find(it);
339  if (c != managed_controllers_.end())
340  { // controller belongs to this manager
341  srv.request.start_controllers.push_back(c->second.name);
342  for (controller_manager_msgs::HardwareInterfaceResources& claimed_resource : c->second.claimed_resources)
343  {
344  for (const std::string& resource : claimed_resource.resources)
345  { // for all claimed resource
346  resources_bimap::right_const_iterator res = claimed_resources.right.find(resource);
347  if (res != claimed_resources.right.end())
348  { // resource is claimed
349  srv.request.stop_controllers.push_back(res->second); // add claiming controller to stop list
350  claimed_resources.left.erase(res->second); // remove claimed resources
351  }
352  }
353  }
354  }
355  }
356  srv.request.strictness = srv.request.STRICT;
357 
358  if (!srv.request.start_controllers.empty() || !srv.request.stop_controllers.empty())
359  { // something to switch?
360  if (!ros::service::call(getAbsName("controller_manager/switch_controller"), srv))
361  {
362  ROS_ERROR_STREAM("Could switch controllers at " << ns_);
363  }
364  discover(true);
365  return srv.response.ok;
366  }
367  return true;
368  }
369 };
374 class MoveItMultiControllerManager : public moveit_controller_manager::MoveItControllerManager
375 {
376  typedef std::map<std::string, moveit_ros_control_interface::MoveItControllerManagerPtr> ControllerManagersMap;
379  boost::mutex controller_managers_mutex_;
380 
385  void discover()
386  {
388  return;
389 
390  XmlRpc::XmlRpcValue args, result, system_state;
392 
393  if (!ros::master::execute("getSystemState", args, result, system_state, true))
394  {
395  return;
396  }
397 
398  // refer to http://wiki.ros.org/ROS/Master_API#Name_service_and_system_state
399  XmlRpc::XmlRpcValue services = system_state[2];
400 
401  for (int i = 0; i < services.size(); ++i) // NOLINT(modernize-loop-convert)
402  {
403  std::string service = services[i][0];
404  std::size_t found = service.find("controller_manager/list_controllers");
405  if (found != std::string::npos)
406  {
407  std::string ns = service.substr(0, found);
409  { // create MoveItControllerManager if it does not exists
410  ROS_INFO_STREAM("Adding controller_manager interface for node at namespace " << ns);
412  std::make_pair(ns, std::make_shared<moveit_ros_control_interface::MoveItControllerManager>(ns)));
413  }
414  }
415  }
416  }
417 
423  static std::string getNamespace(const std::string& name)
424  {
425  size_t pos = name.find('/', 1);
426  if (pos == std::string::npos)
427  pos = 0;
428  return name.substr(0, pos + 1);
429  }
430 
431 public:
437  moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string& name) override
438  {
439  boost::mutex::scoped_lock lock(controller_managers_mutex_);
440 
441  std::string ns = getNamespace(name);
442  ControllerManagersMap::iterator it = controller_managers_.find(ns);
443  if (it != controller_managers_.end())
444  {
445  return it->second->getControllerHandle(name);
446  }
447  return moveit_controller_manager::MoveItControllerHandlePtr();
448  }
449 
454  void getControllersList(std::vector<std::string>& names) override
455  {
456  boost::mutex::scoped_lock lock(controller_managers_mutex_);
457  discover();
458 
459  for (std::pair<const std::string, moveit_ros_control_interface::MoveItControllerManagerPtr>& controller_manager :
461  {
462  controller_manager.second->getControllersList(names);
463  }
464  }
465 
470  void getActiveControllers(std::vector<std::string>& names) override
471  {
472  boost::mutex::scoped_lock lock(controller_managers_mutex_);
473  discover();
474 
475  for (std::pair<const std::string, moveit_ros_control_interface::MoveItControllerManagerPtr>& controller_manager :
477  {
478  controller_manager.second->getActiveControllers(names);
479  }
480  }
481 
487  void getControllerJoints(const std::string& name, std::vector<std::string>& joints) override
488  {
489  boost::mutex::scoped_lock lock(controller_managers_mutex_);
490 
491  std::string ns = getNamespace(name);
492  ControllerManagersMap::iterator it = controller_managers_.find(ns);
493  if (it != controller_managers_.end())
494  {
495  it->second->getControllerJoints(name, joints);
496  }
497  }
498 
504  ControllerState getControllerState(const std::string& name) override
505  {
506  boost::mutex::scoped_lock lock(controller_managers_mutex_);
507 
508  std::string ns = getNamespace(name);
509  ControllerManagersMap::iterator it = controller_managers_.find(ns);
510  if (it != controller_managers_.end())
511  {
512  return it->second->getControllerState(name);
513  }
514  return ControllerState();
515  }
516 
523  bool switchControllers(const std::vector<std::string>& activate, const std::vector<std::string>& deactivate) override
524  {
525  boost::mutex::scoped_lock lock(controller_managers_mutex_);
526 
527  for (std::pair<const std::string, moveit_ros_control_interface::MoveItControllerManagerPtr>& controller_manager :
529  {
530  if (!controller_manager.second->switchControllers(activate, deactivate))
531  return false;
532  }
533  return true;
534  }
535 };
536 
537 } // namespace moveit_ros_control_interface
538 
541 
moveit_ros_control_interface::MoveItMultiControllerManager::getControllerJoints
void getControllerJoints(const std::string &name, std::vector< std::string > &joints) override
Find appropriate interface and delegate joints query.
Definition: controller_manager_plugin.cpp:519
XmlRpc::XmlRpcValue::size
int size() const
moveit_ros_control_interface::MoveItMultiControllerManager::controller_managers_
ControllerManagersMap controller_managers_
Definition: controller_manager_plugin.cpp:409
moveit_ros_control_interface::MoveItControllerManager::allocate
void allocate(const std::string &name, const controller_manager_msgs::ControllerState &controller)
Allocates a MoveItControllerHandle instance for the given controller Might create allocator object fi...
Definition: controller_manager_plugin.cpp:181
ros::service::call
bool call(const std::string &service_name, MReq &req, MRes &res)
moveit_ros_control_interface::MoveItControllerManager::discover
void discover(bool force=false)
Call list_controllers and populate managed_controllers_ and active_controllers_. Allocates handles if...
Definition: controller_manager_plugin.cpp:148
moveit_ros_control_interface::checkTimeout
bool checkTimeout(ros::Time &t, double timeout, bool force=false)
check for timeout
Definition: controller_manager_plugin.cpp:97
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
moveit_ros_control_interface
Definition: ControllerHandle.h:42
moveit_ros_control_interface::MoveItControllerManager::getActiveControllers
void getActiveControllers(std::vector< std::string > &names) override
Refresh controller list and output all active, managed controllers.
Definition: controller_manager_plugin.cpp:275
moveit_ros_control_interface::MoveItControllerManager
moveit_controller_manager::MoveItControllerManager sub class that interfaces one ros_control controll...
Definition: controller_manager_plugin.cpp:116
s
XmlRpcServer s
ros
moveit_ros_control_interface::MoveItMultiControllerManager
MoveItMultiControllerManager discovers all running ros_control node and delegates member function to ...
Definition: controller_manager_plugin.cpp:406
moveit_ros_control_interface::MoveItMultiControllerManager::ControllerManagersMap
std::map< std::string, moveit_ros_control_interface::MoveItControllerManagerPtr > ControllerManagersMap
Definition: controller_manager_plugin.cpp:408
ros.h
moveit_ros_control_interface::MoveItMultiControllerManager::getActiveControllers
void getActiveControllers(std::vector< std::string > &names) override
Read all active, managed controllers from discovered interfaces.
Definition: controller_manager_plugin.cpp:502
moveit_ros_control_interface::MoveItControllerManager::ns_
const std::string ns_
Definition: controller_manager_plugin.cpp:118
moveit_ros_control_interface::MoveItControllerManager::getControllersList
void getControllersList(std::vector< std::string > &names) override
Refresh controller list and output all managed controllers.
Definition: controller_manager_plugin.cpp:259
moveit_ros_control_interface::MoveItMultiControllerManager::discover
void discover()
Poll ROS master for services and filters all controller_manager/list_controllers instances Throttled ...
Definition: controller_manager_plugin.cpp:417
moveit_ros_control_interface::MoveItControllerManager::active_controllers_
ControllersMap active_controllers_
Definition: controller_manager_plugin.cpp:122
moveit_ros_control_interface::MoveItMultiControllerManager::getNamespace
static std::string getNamespace(const std::string &name)
Get namespace (including leading and trailing slashes) from controller name.
Definition: controller_manager_plugin.cpp:455
moveit_ros_control_interface::MoveItMultiControllerManager::getControllerHandle
moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string &name) override
Find appropriate interface and delegate handle creation.
Definition: controller_manager_plugin.cpp:469
controller_manager.h
moveit_ros_control_interface::MoveItMultiControllerManager::getControllerState
ControllerState getControllerState(const std::string &name) override
Find appropriate interface and delegate state query.
Definition: controller_manager_plugin.cpp:536
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
moveit_ros_control_interface::MoveItControllerManager::AllocatorsMap
std::map< std::string, ControllerHandleAllocatorPtr > AllocatorsMap
Definition: controller_manager_plugin.cpp:123
moveit_ros_control_interface::MoveItControllerManager::handles_
HandleMap handles_
Definition: controller_manager_plugin.cpp:127
name
std::string name
moveit_ros_control_interface::MoveItControllerManager::managed_controllers_
ControllersMap managed_controllers_
Definition: controller_manager_plugin.cpp:121
moveit_ros_control_interface::MoveItControllerManager::controllers_stamp_
ros::Time controllers_stamp_
Definition: controller_manager_plugin.cpp:129
moveit_ros_control_interface::MoveItControllerManager::getControllerJoints
void getControllerJoints(const std::string &name, std::vector< std::string > &joints) override
Read resources from cached controller states.
Definition: controller_manager_plugin.cpp:293
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(moveit_ros_control_interface::MoveItControllerManager, moveit_controller_manager::MoveItControllerManager)
moveit_ros_control_interface::MoveItControllerManager::controllers_mutex_
boost::mutex controllers_mutex_
Definition: controller_manager_plugin.cpp:130
moveit_ros_control_interface::MoveItMultiControllerManager::switchControllers
bool switchControllers(const std::vector< std::string > &activate, const std::vector< std::string > &deactivate) override
delegates switch to all known interfaces. Stops on first failing switch.
Definition: controller_manager_plugin.cpp:555
moveit_ros_control_interface::MoveItMultiControllerManager::controller_managers_stamp_
ros::Time controller_managers_stamp_
Definition: controller_manager_plugin.cpp:410
moveit_controller_manager::MoveItControllerManager
moveit_ros_control_interface::MoveItMultiControllerManager::controller_managers_mutex_
boost::mutex controller_managers_mutex_
Definition: controller_manager_plugin.cpp:411
pluginlib::ClassLoader
class_loader.hpp
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
moveit_ros_control_interface::MoveItControllerManager::switchControllers
bool switchControllers(const std::vector< std::string > &activate, const std::vector< std::string > &deactivate) override
Filter lists for managed controller and computes switching set. Stopped list might be extended by uns...
Definition: controller_manager_plugin.cpp:333
moveit_ros_control_interface::MoveItControllerManager::MoveItControllerManager
MoveItControllerManager()
The default constructor. Reads the namespace from ~ros_control_namespace param and defaults to /.
Definition: controller_manager_plugin.cpp:223
moveit_ros_control_interface::MoveItControllerManager::ControllersMap
std::map< std::string, controller_manager_msgs::ControllerState > ControllersMap
Definition: controller_manager_plugin.cpp:120
ros::master::execute
ROSCPP_DECL bool execute(const std::string &method, const XmlRpc::XmlRpcValue &request, XmlRpc::XmlRpcValue &response, XmlRpc::XmlRpcValue &payload, bool wait_for_master)
moveit_ros_control_interface::MoveItControllerManager::loader_
pluginlib::ClassLoader< ControllerHandleAllocator > loader_
Definition: controller_manager_plugin.cpp:119
moveit_ros_control_interface::MoveItControllerManager::getAbsName
std::string getAbsName(const std::string &name)
get fully qualified name
Definition: controller_manager_plugin.cpp:214
moveit_ros_control_interface::MoveItControllerManager::getControllerState
ControllerState getControllerState(const std::string &name) override
Refresh controller state and output the state of the given one, only active_ will be set.
Definition: controller_manager_plugin.cpp:312
ros::this_node::getName
const ROSCPP_DECL std::string & getName()
moveit_ros_control_interface::MoveItMultiControllerManager::getControllersList
void getControllersList(std::vector< std::string > &names) override
Read all managed controllers from discovered interfaces.
Definition: controller_manager_plugin.cpp:486
now
FCL_EXPORT point now(void)
moveit_ros_control_interface::MoveItControllerManager::allocators_
AllocatorsMap allocators_
Definition: controller_manager_plugin.cpp:124
ros::names::append
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
ros::Time
class_forward.h
std
moveit_ros_control_interface::MOVEIT_CLASS_FORWARD
MOVEIT_CLASS_FORWARD(ControllerHandleAllocator)
class_list_macros.hpp
moveit_ros_control_interface::MoveItControllerManager::HandleMap
std::map< std::string, moveit_controller_manager::MoveItControllerHandlePtr > HandleMap
Definition: controller_manager_plugin.cpp:126
param
T param(const std::string &param_name, const T &default_val)
args
moveit_ros_control_interface::MoveItControllerManager::getControllerHandle
moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string &name) override
Find and return the pre-allocated handle for the given controller.
Definition: controller_manager_plugin.cpp:244
ControllerHandle.h
ros::Duration
t
geometry_msgs::TransformStamped t
moveit_ros_control_interface::MoveItControllerManager::isActive
static bool isActive(const controller_manager_msgs::ControllerState &s)
Check if given controller is active.
Definition: controller_manager_plugin.cpp:137
XmlRpc::XmlRpcValue
ros::Time::now
static Time now()


moveit_ros_control_interface
Author(s): Mathias Lüdtke
autogenerated on Sat May 3 2025 02:28:17