moveit2
The MoveIt Motion Planning Framework for ROS 2.
moveit_simple_controller_manager.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, Unbounded Robotics Inc.
5  * Copyright (c) 2012, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the Willow Garage nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 /* Author: Michael Ferguson, Ioan Sucan, E. Gil Jones */
37 
41 #include <boost/algorithm/string/join.hpp>
42 #include <pluginlib/class_list_macros.hpp>
43 #include <rclcpp/logger.hpp>
44 #include <rclcpp/logging.hpp>
45 #include <rclcpp/node.hpp>
46 #include <rclcpp/parameter.hpp>
47 #include <rclcpp/parameter_value.hpp>
48 #include <algorithm>
49 #include <map>
50 #include <moveit/utils/logger.hpp>
51 
52 namespace
53 {
60 template <typename... T>
61 std::string concatenateWithSeparator(char separator, T... content)
62 {
63  std::string result;
64  (result.append(content).append({ separator }), ...);
65  result.erase(result.end() - 1); // delete trailing separator
66  return result;
67 }
68 
76 template <typename... T>
77 std::string makeParameterName(T... strings)
78 {
79  return concatenateWithSeparator<T...>('.', strings...);
80 }
81 
82 } // namespace
83 
85 {
86 namespace
87 {
88 rclcpp::Logger getLogger()
89 {
90  return moveit::getLogger("moveit_simple_controller_manager");
91 }
92 } // namespace
93 static const std::string PARAM_BASE_NAME = "moveit_simple_controller_manager";
95 {
96 public:
98 
99  ~MoveItSimpleControllerManager() override = default;
100 
101  void initialize(const rclcpp::Node::SharedPtr& node) override
102  {
103  node_ = node;
104  if (!node_->has_parameter(makeParameterName(PARAM_BASE_NAME, "controller_names")))
105  {
106  RCLCPP_ERROR_STREAM(getLogger(), "No controller_names specified.");
107  return;
108  }
109  rclcpp::Parameter controller_names_param;
110  node_->get_parameter(makeParameterName(PARAM_BASE_NAME, "controller_names"), controller_names_param);
111  if (controller_names_param.get_type() != rclcpp::ParameterType::PARAMETER_STRING_ARRAY)
112  {
113  RCLCPP_ERROR(getLogger(), "Parameter controller_names should be specified as a string array");
114  return;
115  }
116  std::vector<std::string> controller_names = controller_names_param.as_string_array();
117  /* actually create each controller */
118  for (const std::string& controller_name : controller_names)
119  {
120  try
121  {
122  std::string action_ns;
123  const std::string& action_ns_param = makeParameterName(PARAM_BASE_NAME, controller_name, "action_ns");
124  if (!node_->get_parameter(action_ns_param, action_ns))
125  {
126  RCLCPP_ERROR_STREAM(getLogger(), "No action namespace specified for controller `"
127  << controller_name << "` through parameter `" << action_ns_param << '`');
128  continue;
129  }
130 
131  std::string type;
132  if (!node_->get_parameter(makeParameterName(PARAM_BASE_NAME, controller_name, "type"), type))
133  {
134  RCLCPP_ERROR_STREAM(getLogger(), "No type specified for controller " << controller_name);
135  continue;
136  }
137 
138  std::vector<std::string> controller_joints;
139  if (!node_->get_parameter(makeParameterName(PARAM_BASE_NAME, controller_name, "joints"), controller_joints) ||
140  controller_joints.empty())
141  {
142  RCLCPP_ERROR_STREAM(getLogger(), "No joints specified for controller " << controller_name);
143  continue;
144  }
145 
146  ActionBasedControllerHandleBasePtr new_handle;
147  if (type == "GripperCommand")
148  {
149  double max_effort;
150  const std::string& max_effort_param = makeParameterName(PARAM_BASE_NAME, controller_name, "max_effort");
151  if (!node->get_parameter(max_effort_param, max_effort))
152  {
153  RCLCPP_INFO_STREAM(getLogger(), "Max effort set to 0.0");
154  max_effort = 0.0;
155  }
156 
157  new_handle = std::make_shared<GripperControllerHandle>(node_, controller_name, action_ns, max_effort);
158  bool parallel_gripper = false;
159  if (node_->get_parameter(makeParameterName(PARAM_BASE_NAME, "parallel"), parallel_gripper) && parallel_gripper)
160  {
161  if (controller_joints.size() != 2)
162  {
163  RCLCPP_ERROR_STREAM(getLogger(), "Parallel Gripper requires exactly two joints, "
164  << controller_joints.size() << " are specified");
165  continue;
166  }
167  static_cast<GripperControllerHandle*>(new_handle.get())
168  ->setParallelJawGripper(controller_joints[0], controller_joints[1]);
169  }
170  else
171  {
172  std::string command_joint;
173  if (!node_->get_parameter(makeParameterName(PARAM_BASE_NAME, "command_joint"), command_joint))
174  command_joint = controller_joints[0];
175 
176  static_cast<GripperControllerHandle*>(new_handle.get())->setCommandJoint(command_joint);
177  }
178 
179  bool allow_failure;
180  node_->get_parameter_or(makeParameterName(PARAM_BASE_NAME, "allow_failure"), allow_failure, false);
181  static_cast<GripperControllerHandle*>(new_handle.get())->allowFailure(allow_failure);
182 
183  RCLCPP_INFO_STREAM(getLogger(), "Added GripperCommand controller for " << controller_name);
184  controllers_[controller_name] = new_handle;
185  }
186  else if (type == "FollowJointTrajectory")
187  {
188  new_handle = std::make_shared<FollowJointTrajectoryControllerHandle>(node_, controller_name, action_ns);
189  RCLCPP_INFO_STREAM(getLogger(), "Added FollowJointTrajectory controller for " << controller_name);
190  controllers_[controller_name] = new_handle;
191  }
192  else
193  {
194  RCLCPP_ERROR_STREAM(getLogger(), "Unknown controller type: " << type);
195  continue;
196  }
197  if (!controllers_[controller_name])
198  {
199  controllers_.erase(controller_name);
200  continue;
201  }
202 
204  node_->get_parameter_or(makeParameterName(PARAM_BASE_NAME, controller_name, "default"), state.default_, false);
205  state.active_ = true;
206 
207  controller_states_[controller_name] = state;
208 
209  /* add list of joints, used by controller manager and MoveIt */
210  for (const std::string& controller_joint : controller_joints)
211  new_handle->addJoint(controller_joint);
212  }
213  catch (...)
214  {
215  RCLCPP_ERROR_STREAM(getLogger(), "Caught unknown exception while parsing controller information");
216  }
217  }
218  }
219  /*
220  * Get a controller, by controller name (which was specified in the controllers.yaml
221  */
222  moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string& name) override
223  {
224  std::map<std::string, ActionBasedControllerHandleBasePtr>::const_iterator it = controllers_.find(name);
225  if (it != controllers_.end())
226  {
227  return static_cast<moveit_controller_manager::MoveItControllerHandlePtr>(it->second);
228  }
229  else
230  {
231  RCLCPP_FATAL_STREAM(getLogger(), "No such controller: " << name);
232  }
233  return moveit_controller_manager::MoveItControllerHandlePtr();
234  }
235 
236  /*
237  * Get the list of controller names.
238  */
239  void getControllersList(std::vector<std::string>& names) override
240  {
241  for (std::map<std::string, ActionBasedControllerHandleBasePtr>::const_iterator it = controllers_.begin();
242  it != controllers_.end(); ++it)
243  names.push_back(it->first);
244  RCLCPP_INFO_STREAM(getLogger(), "Returned " << names.size() << " controllers in list");
245  }
246 
247  /*
248  * This plugin assumes that all controllers are already active -- and if they are not, well, it has no way to deal
249  * with it anyways!
250  */
251  void getActiveControllers(std::vector<std::string>& names) override
252  {
253  getControllersList(names);
254  }
255 
256  /*
257  * Controller must be loaded to be active, see comment above about active controllers...
258  */
259  virtual void getLoadedControllers(std::vector<std::string>& names)
260  {
261  getControllersList(names);
262  }
263 
264  /*
265  * Get the list of joints that a controller can control.
266  */
267  void getControllerJoints(const std::string& name, std::vector<std::string>& joints) override
268  {
269  std::map<std::string, ActionBasedControllerHandleBasePtr>::const_iterator it = controllers_.find(name);
270  if (it != controllers_.end())
271  {
272  it->second->getJoints(joints);
273  }
274  else
275  {
276  RCLCPP_WARN(getLogger(),
277  "The joints for controller '%s' are not known. Perhaps the controller configuration is "
278  "not loaded on the param server?",
279  name.c_str());
280  joints.clear();
281  }
282  }
283 
285  getControllerState(const std::string& name) override
286  {
287  return controller_states_[name];
288  }
289 
290  /* Cannot switch our controllers */
291  bool switchControllers(const std::vector<std::string>& /* activate */,
292  const std::vector<std::string>& /* deactivate */) override
293  {
294  return false;
295  }
296 
297 protected:
298  rclcpp::Node::SharedPtr node_;
299  std::map<std::string, ActionBasedControllerHandleBasePtr> controllers_;
300  std::map<std::string, moveit_controller_manager::MoveItControllerManager::ControllerState> controller_states_;
301 };
302 
303 } // end namespace moveit_simple_controller_manager
304 
MoveIt does not enforce how controllers are implemented. To make your controllers usable by MoveIt,...
bool switchControllers(const std::vector< std::string > &, const std::vector< std::string > &) override
Activate and deactivate controllers.
void getControllerJoints(const std::string &name, std::vector< std::string > &joints) override
Report the joints a controller operates on, given the controller name.
void getActiveControllers(std::vector< std::string > &names) override
Get the list of active controllers.
moveit_controller_manager::MoveItControllerHandlePtr getControllerHandle(const std::string &name) override
Return a given named controller.
std::map< std::string, moveit_controller_manager::MoveItControllerManager::ControllerState > controller_states_
std::map< std::string, ActionBasedControllerHandleBasePtr > controllers_
moveit_controller_manager::MoveItControllerManager::ControllerState getControllerState(const std::string &name) override
Report the state of a controller, given its name.
void getControllersList(std::vector< std::string > &names) override
Get the list of known controller names.
PLUGINLIB_EXPORT_CLASS(moveit_simple_controller_manager::MoveItSimpleControllerManager, moveit_controller_manager::MoveItControllerManager)
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition: logger.cpp:79
name
Definition: setup.py:7
Each controller known to MoveIt has a state. This structure describes that controller's state.
bool default_
It is often the case that multiple controllers could be used to execute a motion. Marking a controlle...
bool active_
A controller can be active or inactive. This means that MoveIt could activate the controller when nee...