controller_manager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Fetch Robotics Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Fetch Robotics Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL FETCH ROBOTICS INC. BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 // Author: Michael Ferguson
30 
31 #include <sstream>
33 
34 namespace robot_controllers
35 {
36 
38 {
39 }
40 
42 {
43  // Find and load default controllers
44  XmlRpc::XmlRpcValue controller_params;
45  if (nh.getParam("default_controllers", controller_params))
46  {
47  if (controller_params.getType() != XmlRpc::XmlRpcValue::TypeArray)
48  {
49  ROS_ERROR_NAMED("ControllerManager", "Parameter 'default_controllers' should be a list.");
50  return -1;
51  }
52  else
53  {
54  // Load each controller
55  for (int c = 0; c < controller_params.size(); c++)
56  {
57  // Make sure name is valid
58  XmlRpc::XmlRpcValue &controller_name = controller_params[c];
59  if (controller_name.getType() != XmlRpc::XmlRpcValue::TypeString)
60  {
61  ROS_WARN_NAMED("ControllerManager", "Controller name is not a string?");
62  continue;
63  }
64 
65  // Create controller (in a loader)
66  load(static_cast<std::string>(controller_name));
67  }
68  }
69  }
70  else
71  {
72  ROS_WARN_NAMED("ControllerManager", "No controllers loaded.");
73  return -1;
74  }
75 
76  // Setup actionlib server
77  server_.reset(new server_t(nh, "/query_controller_states",
78  boost::bind(&ControllerManager::execute, this, _1),
79  false));
80  server_->start();
81 
82  return 0;
83 }
84 
85 int ControllerManager::requestStart(const std::string& name)
86 {
87  // Find requested controller
88  ControllerLoaderPtr controller;
89  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
90  {
91  if ((*c)->getController()->getName() == name)
92  {
93  controller = *c;
94  break;
95  }
96  }
97 
98  // Does controller exist?
99  if (!controller)
100  {
101  ROS_ERROR_STREAM_NAMED("ControllerManager", "Unable to start " << name.c_str() << ": no such controller.");
102  return -1;
103  }
104 
105  // Is controller already running?
106  if (controller->isActive())
107  {
108  ROS_DEBUG_STREAM_NAMED("ControllerManager", "Unable to start " << name.c_str() << ": already running.");
109  return 0;
110  }
111 
112  // Check for conflicts
113  std::vector<std::string> names = controller->getController()->getCommandedNames();
114  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
115  {
116  // Only care about active controllers
117  if (!(*c)->isActive())
118  continue;
119 
120  std::vector<std::string> names2 = (*c)->getController()->getClaimedNames();
121  bool conflict = false;
122  for (size_t i = 0; i < names.size(); i++)
123  {
124  for (size_t i2 = 0; i2 < names2.size(); i2++)
125  {
126  if (names[i] == names2[i2])
127  {
128  conflict = true;
129  break;
130  }
131  }
132  if (conflict) break;
133  }
134  // Have conflict, try to stop controller (without force)
135  if (conflict)
136  {
137  if ((*c)->stop(false))
138  {
139  ROS_INFO_STREAM_NAMED("ControllerManager", "Stopped " << (*c)->getController()->getName().c_str());
140  }
141  else
142  {
143  // Unable to stop c, cannot start controller
144  ROS_ERROR_STREAM_NAMED("ControllerManager", "Unable to stop " <<
145  (*c)->getController()->getName().c_str() <<
146  " when trying to start " << name.c_str());
147  return -1;
148  }
149  }
150  }
151 
152  // Start controller
153  if (controller->start())
154  {
155  ROS_INFO_STREAM_NAMED("ControllerManager", "Started " << controller->getController()->getName().c_str());
156  return 0;
157  }
158 
159  return -1; // Unable to start
160 }
161 
162 int ControllerManager::requestStop(const std::string& name)
163 {
164  // Find controller
165  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
166  {
167  if ((*c)->getController()->getName() == name)
168  {
169  // Stop controller (with force)
170  if ((*c)->stop(true))
171  {
172  ROS_INFO_STREAM_NAMED("ControllerManager", "Stopped " << (*c)->getController()->getName().c_str());
173  return 0;
174  }
175  else
176  {
177  return -1; // controller decided not to stop
178  }
179  }
180  }
181  return -1; // no such controller
182 }
183 
185 {
186  // Reset handles
187  for (JointHandleList::iterator j = joints_.begin(); j != joints_.end(); j++)
188  (*j)->reset();
189 
190  // Update controllers
191  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
192  {
193  (*c)->update(time, dt);
194  }
195 }
196 
198 {
199  // Update controllers
200  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
201  {
202  (*c)->reset();
203  }
204 }
205 
207 {
208  // TODO: check for duplicate names?
209  joints_.push_back(j);
210  return true;
211 }
212 
214 {
215  // Try joints first
216  for (JointHandleList::iterator j = joints_.begin(); j != joints_.end(); j++)
217  {
218  if ((*j)->getName() == name)
219  return *j;
220  }
221 
222  // Then controllers
223  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
224  {
225  if ((*c)->getController()->getName() == name)
226  return (*c)->getController();
227  }
228 
229  // Not found
230  return HandlePtr();
231 }
232 
234 {
235  // Try joints first
236  for (JointHandleList::iterator j = joints_.begin(); j != joints_.end(); j++)
237  {
238  if ((*j)->getName() == name)
239  return *j;
240  }
241 
242  // Not found
243  return JointHandlePtr();
244 }
245 
246 void ControllerManager::execute(const robot_controllers_msgs::QueryControllerStatesGoalConstPtr& goal)
247 {
248  robot_controllers_msgs::QueryControllerStatesFeedback feedback;
249  robot_controllers_msgs::QueryControllerStatesResult result;
250 
251  for (size_t i = 0; i < goal->updates.size(); i++)
252  {
253  // Update this controller
254  robot_controllers_msgs::ControllerState state = goal->updates[i];
255 
256  // Make sure controller exists
257  bool in_controller_list = false;
258  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
259  {
260  if ((*c)->getController()->getName() == state.name)
261  {
262  if (state.type != "")
263  {
264  if (state.type == (*c)->getController()->getType())
265  {
266  in_controller_list = true;
267  break;
268  }
269  else
270  {
271  std::stringstream ss;
272  ss << "Controller " << state.name << " is of type " << (*c)->getController()->getType() << " not " << state.type;
273  getState(result);
274  server_->setAborted(result, ss.str());
275  return;
276  }
277  }
278  in_controller_list = true;
279  break;
280  }
281  }
282  if (!in_controller_list)
283  {
284  // Check if controller exists on parameter server
285  ros::NodeHandle nh;
286  if (nh.hasParam(state.name))
287  {
288  // Create controller (in a loader)
289  if (!load(static_cast<std::string>(state.name)))
290  {
291  std::stringstream ss;
292  ss << "Failed to load controller: " << state.name;
293  getState(result);
294  server_->setAborted(result, ss.str());
295  return;
296  }
297  }
298  else
299  {
300  std::stringstream ss;
301  ss << "No such controller to update: " << state.name;
302  getState(result);
303  server_->setAborted(result, ss.str());
304  return;
305  }
306  }
307 
308  // Update state
309  if (state.state == state.STOPPED)
310  {
311  if (requestStop(state.name) != 0)
312  {
313  std::stringstream ss;
314  ss << "Unable to stop " << state.name;
315  getState(result);
316  server_->setAborted(result, ss.str());
317  return;
318  }
319  }
320  else if (state.state == state.RUNNING)
321  {
322  if (requestStart(state.name) != 0)
323  {
324  std::stringstream ss;
325  ss << "Unable to start " << state.name;
326  getState(result);
327  server_->setAborted(result, ss.str());
328  return;
329  }
330  }
331  else
332  {
333  std::stringstream ss;
334  ss << "Invalid state for controller " << state.name << ": " << static_cast<int>(state.state);
335  getState(result);
336  server_->setAborted(result, ss.str());
337  return;
338  }
339  }
340 
341  // Send result
342  getState(result);
343  server_->setSucceeded(result);
344 }
345 
347  robot_controllers_msgs::QueryControllerStatesResult& result)
348 {
349  result.state.clear();
350  for (ControllerList::iterator c = controllers_.begin(); c != controllers_.end(); c++)
351  {
352  robot_controllers_msgs::ControllerState state;
353  state.name = (*c)->getController()->getName();
354  state.type = (*c)->getController()->getType();
355  if ((*c)->isActive())
356  {
357  state.state = state.RUNNING;
358  }
359  else
360  {
361  state.state = state.STOPPED;
362  }
363  result.state.push_back(state);
364  }
365 }
366 
367 // NOTE: this function should be called only by one thread
368 bool ControllerManager::load(const std::string& name)
369 {
370  // Create controller (in a loader)
371  ControllerLoaderPtr controller(new ControllerLoader());
372  // Push back controller (so that autostart will work)
373  controllers_.push_back(controller);
374  // Now initialize controller
375  if (!controller->init(name, this))
376  {
377  // Remove if init fails
378  controllers_.pop_back();
379  return false;
380  }
381  return true;
382 }
383 
384 } // namespace robot_controllers
virtual void reset()
Reset all controllers.
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
#define ROS_WARN_NAMED(name,...)
int size() const
bool load(const std::string &name)
Load a controller.
virtual int init(ros::NodeHandle &nh)
Startup the controller manager, loading default controllers.
virtual int requestStart(const std::string &name)
Start a controller.
actionlib::SimpleActionServer< robot_controllers_msgs::QueryControllerStatesAction > server_t
#define ROS_INFO_STREAM_NAMED(name, args)
Type const & getType() const
HandlePtr getHandle(const std::string &name)
Get the handle associated with a particular joint/controller name.
bool addJointHandle(JointHandlePtr &j)
Add a joint handle.
virtual int requestStop(const std::string &name)
Stop a controller.
boost::shared_ptr< JointHandle > JointHandlePtr
Definition: joint_handle.h:112
void execute(const robot_controllers_msgs::QueryControllerStatesGoalConstPtr &goal)
Action callback.
bool getParam(const std::string &key, std::string &s) const
#define ROS_ERROR_NAMED(name,...)
void getState(robot_controllers_msgs::QueryControllerStatesResult &result)
Fill in the current state of controllers.
boost::shared_ptr< server_t > server_
JointHandlePtr getJointHandle(const std::string &name)
Get the joint handle associated with a particular joint name.
Class for loading and managing a single controller.
bool hasParam(const std::string &key) const
virtual void update(const ros::Time &time, const ros::Duration &dt)
Update active controllers.
boost::shared_ptr< Handle > HandlePtr
Definition: handle.h:64


robot_controllers_interface
Author(s): Michael Ferguson
autogenerated on Sun Sep 27 2020 03:22:36