abstract_navigation_server.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, Magazino GmbH, Sebastian Pütz, Jorge Santos Simón
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided
14  * with the distribution.
15  *
16  * 3. Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * abstract_navigation_server.cpp
34  *
35  * authors:
36  * Sebastian Pütz <spuetz@uni-osnabrueck.de>
37  * Jorge Santos Simón <santos@magazino.eu>
38  *
39  */
40 
41 #include <nav_msgs/Path.h>
42 #include <sstream>
44 
45 namespace mbf_abstract_nav
46 {
47 
49  : tf_listener_ptr_(tf_listener_ptr), private_nh_("~"),
50  planner_plugin_manager_("planners",
51  boost::bind(&AbstractNavigationServer::loadPlannerPlugin, this, _1),
52  boost::bind(&AbstractNavigationServer::initializePlannerPlugin, this, _1, _2)),
53  controller_plugin_manager_("controllers",
54  boost::bind(&AbstractNavigationServer::loadControllerPlugin, this, _1),
55  boost::bind(&AbstractNavigationServer::initializeControllerPlugin, this, _1, _2)),
56  recovery_plugin_manager_("recovery_behaviors",
57  boost::bind(&AbstractNavigationServer::loadRecoveryPlugin, this, _1),
58  boost::bind(&AbstractNavigationServer::initializeRecoveryPlugin, this, _1, _2)),
59  tf_timeout_(private_nh_.param<double>("tf_timeout", 3.0)),
60  global_frame_(private_nh_.param<std::string>("global_frame", "map")),
61  robot_frame_(private_nh_.param<std::string>("robot_frame", "base_link")),
62  robot_info_(*tf_listener_ptr, global_frame_, robot_frame_, tf_timeout_),
63  controller_action_(name_action_exe_path, robot_info_),
64  planner_action_(name_action_get_path, robot_info_),
65  recovery_action_(name_action_recovery, robot_info_),
66  move_base_action_(name_action_move_base, robot_info_, recovery_plugin_manager_.getLoadedNames())
67 {
68  ros::NodeHandle nh;
69 
70  // oscillation timeout and distance
71  double oscillation_timeout;
72  private_nh_.param("oscillation_timeout", oscillation_timeout, 0.0);
73  oscillation_timeout_ = ros::Duration(oscillation_timeout);
74  private_nh_.param("oscillation_distance", oscillation_distance_, 0.02);
75 
76  goal_pub_ = nh.advertise<geometry_msgs::PoseStamped>("current_goal", 1);
77 
78  // init cmd_vel publisher for the robot velocity
79  vel_pub_ = nh.advertise<geometry_msgs::Twist>("cmd_vel", 1);
80 
87  false));
88 
95  false));
96 
103  false));
104 
107  private_nh_,
111  false));
112 
113  // XXX note that we don't start a dynamic reconfigure server, to avoid colliding with the one possibly created by
114  // the base class. If none, it should call startDynamicReconfigureServer method to start the one defined here for
115  // providing just the abstract server parameters
116 }
117 
119 {
123 }
124 
126 {
127 
128 }
129 
131 {
132  const mbf_msgs::GetPathGoal &goal = *(goal_handle.getGoal().get());
133  const geometry_msgs::Point &p = goal.target_pose.pose.position;
134 
135  std::string planner_name;
137  {
138  planner_name = goal.planner.empty() ? planner_plugin_manager_.getLoadedNames().front() : goal.planner;
139  }
140  else
141  {
142  mbf_msgs::GetPathResult result;
143  result.outcome = mbf_msgs::GetPathResult::INVALID_PLUGIN;
144  result.message = "No plugins loaded at all!";
145  ROS_WARN_STREAM_NAMED("get_path", result.message);
146  goal_handle.setRejected(result, result.message);
147  return;
148  }
149 
150  if(!planner_plugin_manager_.hasPlugin(planner_name))
151  {
152  mbf_msgs::GetPathResult result;
153  result.outcome = mbf_msgs::GetPathResult::INVALID_PLUGIN;
154  result.message = "No plugin loaded with the given name \"" + goal.planner + "\"!";
155  ROS_WARN_STREAM_NAMED("get_path", result.message);
156  goal_handle.setRejected(result, result.message);
157  return;
158  }
159 
161  ROS_INFO_STREAM_NAMED("get_path", "Start action \"get_path\" using planner \"" << planner_name
162  << "\" of type \"" << planner_plugin_manager_.getType(planner_name) << "\"");
163 
164 
165  if(planner_plugin)
166  {
168  = newPlannerExecution(planner_name, planner_plugin);
169 
170  //start another planning action
171  planner_action_.start(goal_handle, planner_execution);
172  }
173  else
174  {
175  mbf_msgs::GetPathResult result;
176  result.outcome = mbf_msgs::GetPathResult::INTERNAL_ERROR;
177  result.message = "Internal Error: \"planner_plugin\" pointer should not be a null pointer!";
178  ROS_FATAL_STREAM_NAMED("get_path", result.message);
179  goal_handle.setRejected(result, result.message);
180  }
181 }
182 
184 {
185  ROS_INFO_STREAM_NAMED("get_path", "Cancel action \"get_path\"");
186  planner_action_.cancel(goal_handle);
187 }
188 
190 {
191  const mbf_msgs::ExePathGoal &goal = *(goal_handle.getGoal().get());
192 
193  std::string controller_name;
195  {
196  controller_name = goal.controller.empty() ? controller_plugin_manager_.getLoadedNames().front() : goal.controller;
197  }
198  else
199  {
200  mbf_msgs::ExePathResult result;
201  result.outcome = mbf_msgs::ExePathResult::INVALID_PLUGIN;
202  result.message = "No plugins loaded at all!";
203  ROS_WARN_STREAM_NAMED("exe_path", result.message);
204  goal_handle.setRejected(result, result.message);
205  return;
206  }
207 
208  if(!controller_plugin_manager_.hasPlugin(controller_name))
209  {
210  mbf_msgs::ExePathResult result;
211  result.outcome = mbf_msgs::ExePathResult::INVALID_PLUGIN;
212  result.message = "No plugin loaded with the given name \"" + goal.controller + "\"!";
213  ROS_WARN_STREAM_NAMED("exe_path", result.message);
214  goal_handle.setRejected(result, result.message);
215  return;
216  }
217 
219  ROS_INFO_STREAM_NAMED("exe_path", "Start action \"exe_path\" using controller \"" << controller_name
220  << "\" of type \"" << controller_plugin_manager_.getType(controller_name) << "\"");
221 
222 
223  if(controller_plugin)
224  {
226  = newControllerExecution(controller_name, controller_plugin);
227 
228  // starts another controller action
229  controller_action_.start(goal_handle, controller_execution);
230  }
231  else
232  {
233  mbf_msgs::ExePathResult result;
234  result.outcome = mbf_msgs::ExePathResult::INTERNAL_ERROR;
235  result.message = "Internal Error: \"controller_plugin\" pointer should not be a null pointer!";
236  ROS_FATAL_STREAM_NAMED("exe_path", result.message);
237  goal_handle.setRejected(result, result.message);
238  }
239 }
240 
242 {
243  ROS_INFO_STREAM_NAMED("exe_path", "Cancel action \"exe_path\"");
244  controller_action_.cancel(goal_handle);
245 }
246 
248 {
249  const mbf_msgs::RecoveryGoal &goal = *(goal_handle.getGoal().get());
250 
251  std::string recovery_name;
252 
254  {
255  recovery_name = goal.behavior.empty() ? recovery_plugin_manager_.getLoadedNames().front() : goal.behavior;
256  }
257  else
258  {
259  mbf_msgs::RecoveryResult result;
260  result.outcome = mbf_msgs::RecoveryResult::INVALID_PLUGIN;
261  result.message = "No plugins loaded at all!";
262  ROS_WARN_STREAM_NAMED("recovery", result.message);
263  goal_handle.setRejected(result, result.message);
264  return;
265  }
266 
267  if(!recovery_plugin_manager_.hasPlugin(recovery_name))
268  {
269  mbf_msgs::RecoveryResult result;
270  result.outcome = mbf_msgs::RecoveryResult::INVALID_PLUGIN;
271  result.message = "No plugin loaded with the given name \"" + goal.behavior + "\"!";
272  ROS_WARN_STREAM_NAMED("recovery", result.message);
273  goal_handle.setRejected(result, result.message);
274  return;
275  }
276 
278  ROS_INFO_STREAM_NAMED("recovery", "Start action \"recovery\" using recovery \"" << recovery_name
279  << "\" of type \"" << recovery_plugin_manager_.getType(recovery_name) << "\"");
280 
281 
282  if(recovery_plugin)
283  {
285  = newRecoveryExecution(recovery_name, recovery_plugin);
286 
287  recovery_action_.start(goal_handle, recovery_execution);
288  }
289  else
290  {
291  mbf_msgs::RecoveryResult result;
292  result.outcome = mbf_msgs::RecoveryResult::INTERNAL_ERROR;
293  result.message = "Internal Error: \"recovery_plugin\" pointer should not be a null pointer!";
294  ROS_FATAL_STREAM_NAMED("recovery", result.message);
295  goal_handle.setRejected(result, result.message);
296  }
297 }
298 
300 {
301  ROS_INFO_STREAM_NAMED("recovery", "Cancel action \"recovery\"");
302  recovery_action_.cancel(goal_handle);
303 }
304 
306 {
307  ROS_INFO_STREAM_NAMED("move_base", "Start action \"move_base\"");
308  move_base_action_.start(goal_handle);
309 }
310 
312 {
313  ROS_INFO_STREAM_NAMED("move_base", "Cancel action \"move_base\"");
315 }
316 
318  const std::string name,
320 {
321  return boost::make_shared<mbf_abstract_nav::AbstractPlannerExecution>(name, plugin_ptr, last_config_,
322  boost::function<void()>(),
323  boost::function<void()>());
324 }
325 
327  const std::string name,
329 {
330  return boost::make_shared<mbf_abstract_nav::AbstractControllerExecution>(name, plugin_ptr, vel_pub_, goal_pub_,
331  tf_listener_ptr_, last_config_, boost::function<void()>(), boost::function<void()>());
332 }
333 
335  const std::string name,
337 {
338  return boost::make_shared<mbf_abstract_nav::AbstractRecoveryExecution>(name, plugin_ptr, tf_listener_ptr_, last_config_,
339  boost::function<void()>(),
340  boost::function<void()>());
341 }
342 
344 {
349 }
350 
352 {
353  // dynamic reconfigure server
354  dsrv_ = boost::make_shared<dynamic_reconfigure::Server<mbf_abstract_nav::MoveBaseFlexConfig> >(private_nh_);
355  dsrv_->setCallback(boost::bind(&AbstractNavigationServer::reconfigure, this, _1, _2));
356 }
357 
359  mbf_abstract_nav::MoveBaseFlexConfig &config, uint32_t level)
360 {
361  boost::lock_guard<boost::mutex> guard(configuration_mutex_);
362 
363  // Make sure we have the original configuration the first time we're called, so we can restore it if needed
364  if (!setup_reconfigure_)
365  {
366  default_config_ = config;
367  setup_reconfigure_ = true;
368  }
369 
370  if (config.restore_defaults)
371  {
372  config = default_config_;
373  // if someone sets restore defaults on the parameter server, prevent looping
374  config.restore_defaults = false;
375  }
376  planner_action_.reconfigureAll(config, level);
377  controller_action_.reconfigureAll(config, level);
378  recovery_action_.reconfigureAll(config, level);
379  move_base_action_.reconfigure(config, level);
380 
381  last_config_ = config;
382 }
383 
389 }
390 
391 } /* namespace mbf_abstract_nav */
ActionServerRecoveryPtr action_server_recovery_ptr_
shared pointer to the Recovery action server
actionlib::ActionServer< mbf_msgs::MoveBaseAction > ActionServerMoveBase
MoveBase action server.
bool param(const std::string &param_name, T &param_val, const T &default_val)
actionlib::ActionServer< mbf_msgs::RecoveryAction > ActionServerRecovery
Recovery action server.
ros::Publisher goal_pub_
current_goal publisher for all controller execution objects
virtual void cancelActionRecovery(ActionServerRecovery::GoalHandle goal_handle)
const TFPtr tf_listener_ptr_
shared pointer to the common TransformListener
boost::shared_ptr< ActionServerMoveBase > ActionServerMoveBasePtr
PluginType::Ptr getPlugin(const std::string &name)
AbstractPluginManager< mbf_abstract_core::AbstractController > controller_plugin_manager_
virtual void startDynamicReconfigureServer()
Start a dynamic reconfigure server. This must be called only if the extending doesn&#39;t create its own...
virtual mbf_abstract_nav::AbstractControllerExecution::Ptr newControllerExecution(const std::string plugin_name, const mbf_abstract_core::AbstractController::Ptr plugin_ptr)
shared pointer to a new ControllerExecution
const std::string name_action_get_path
GetPath action topic name.
void setRejected(const Result &result=Result(), const std::string &text=std::string(""))
boost::shared_ptr< const Goal > getGoal() const
The AbstractNavigationServer is the abstract base class for all navigation servers in move_base_flex ...
virtual void cancelActionMoveBase(ActionServerMoveBase::GoalHandle goal_handle)
#define ROS_INFO_STREAM_NAMED(name, args)
virtual void reconfigure(mbf_abstract_nav::MoveBaseFlexConfig &config, uint32_t level)
Reconfiguration method called by dynamic reconfigure.
actionlib::ActionServer< mbf_msgs::GetPathAction > ActionServerGetPath
GetPath action server.
actionlib::ActionServer< mbf_msgs::ExePathAction > ActionServerExePath
ExePath action server.
virtual void callActionExePath(ActionServerExePath::GoalHandle goal_handle)
ExePath action execution method. This method will be called if the action server receives a goal...
ActionServerGetPathPtr action_server_get_path_ptr_
shared pointer to the GetPath action server
const std::string name_action_exe_path
ExePath action topic name.
const std::vector< std::string > & getLoadedNames()
void reconfigure(mbf_abstract_nav::MoveBaseFlexConfig &config, uint32_t level)
virtual void cancel(GoalHandle &goal_handle)
AbstractPluginManager< mbf_abstract_core::AbstractPlanner > planner_plugin_manager_
bool setup_reconfigure_
true, if the dynamic reconfigure has been setup.
#define ROS_FATAL_STREAM_NAMED(name, args)
mbf_abstract_nav::MoveBaseFlexConfig default_config_
the default parameter configuration save
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void start(GoalHandle &goal_handle, typename AbstractControllerExecution::Ptr execution_ptr)
Start controller action. Override abstract action version to allow updating current plan without stop...
virtual void callActionRecovery(ActionServerRecovery::GoalHandle goal_handle)
Recovery action execution method. This method will be called if the action server receives a goal...
AbstractNavigationServer(const TFPtr &tf_listener_ptr)
Constructor, reads all parameters and initializes all action servers and creates the plugin instances...
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::Publisher vel_pub_
cmd_vel publisher for all controller execution objects
virtual void cancelActionExePath(ActionServerExePath::GoalHandle goal_handle)
bool hasPlugin(const std::string &name)
boost::shared_ptr< ActionServerGetPath > ActionServerGetPathPtr
virtual void callActionMoveBase(ActionServerMoveBase::GoalHandle goal_handle)
MoveBase action execution method. This method will be called if the action server receives a goal...
mbf_abstract_nav::MoveBaseFlexConfig last_config_
last configuration save
ActionServerMoveBasePtr action_server_move_base_ptr_
shared pointer to the MoveBase action server
virtual mbf_abstract_nav::AbstractPlannerExecution::Ptr newPlannerExecution(const std::string plugin_name, const mbf_abstract_core::AbstractPlanner::Ptr plugin_ptr)
shared pointer to a new PlannerExecution
boost::shared_ptr< ActionServerExePath > ActionServerExePathPtr
virtual void reconfigureAll(mbf_abstract_nav::MoveBaseFlexConfig &config, uint32_t level)
ActionServerExePathPtr action_server_exe_path_ptr_
shared pointer to the ExePath action server
const std::string name_action_recovery
Recovery action topic name.
virtual void callActionGetPath(ActionServerGetPath::GoalHandle goal_handle)
GetPath action execution method. This method will be called if the action server receives a goal...
boost::mutex configuration_mutex_
configuration mutex for derived classes and other threads.
AbstractPluginManager< mbf_abstract_core::AbstractRecovery > recovery_plugin_manager_
virtual void cancelActionGetPath(ActionServerGetPath::GoalHandle goal_handle)
virtual void startActionServers()
starts all action server.
const std::string name_action_move_base
MoveBase action topic name.
virtual void start(GoalHandle &goal_handle, typename Execution::Ptr execution_ptr)
ros::Duration oscillation_timeout_
timeout after a oscillation is detected
DynamicReconfigureServer dsrv_
dynamic reconfigure server
virtual void initializeServerComponents()
initializes all server components. Initializing the plugins of the Planner, the Controller, and the Recovery Behavior.
double oscillation_distance_
minimal move distance to not detect an oscillation
boost::shared_ptr< ActionServerRecovery > ActionServerRecoveryPtr
void start(GoalHandle &goal_handle)
ros::NodeHandle private_nh_
Private node handle.
#define ROS_WARN_STREAM_NAMED(name, args)
std::string getType(const std::string &name)
virtual mbf_abstract_nav::AbstractRecoveryExecution::Ptr newRecoveryExecution(const std::string plugin_name, const mbf_abstract_core::AbstractRecovery::Ptr plugin_ptr)
shared pointer to a new RecoveryExecution


mbf_abstract_nav
Author(s): Sebastian Pütz
autogenerated on Tue Jun 18 2019 19:34:34