move_slow_and_clear.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * Software License Agreement (BSD License)
4 *
5 * Copyright (c) 2009, 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 Willow Garage, Inc. 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 * Author: Eitan Marder-Eppstein
36 *********************************************************************/
40 
42 
43 namespace move_slow_and_clear
44 {
45  MoveSlowAndClear::MoveSlowAndClear():global_costmap_(NULL), local_costmap_(NULL),
46  initialized_(false), remove_limit_thread_(NULL), limit_set_(false){}
47 
49  {
50  delete remove_limit_thread_;
51  }
52 
54  costmap_2d::Costmap2DROS* global_costmap,
55  costmap_2d::Costmap2DROS* local_costmap)
56  {
57  global_costmap_ = global_costmap;
58  local_costmap_ = local_costmap;
59 
60  ros::NodeHandle private_nh_("~/" + n);
61  private_nh_.param("clearing_distance", clearing_distance_, 0.5);
62  private_nh_.param("limited_trans_speed", limited_trans_speed_, 0.25);
63  private_nh_.param("limited_rot_speed", limited_rot_speed_, 0.45);
64  private_nh_.param("limited_distance", limited_distance_, 0.3);
65  private_nh_.param("max_trans_param_name", max_trans_param_name_, std::string("max_trans_vel"));
66  private_nh_.param("max_rot_param_name", max_rot_param_name_, std::string("max_rot_vel"));
67 
68  std::string planner_namespace;
69  private_nh_.param("planner_namespace", planner_namespace, std::string("DWAPlannerROS"));
70  planner_nh_ = ros::NodeHandle("~/" + planner_namespace);
71  planner_dynamic_reconfigure_service_ = planner_nh_.serviceClient<dynamic_reconfigure::Reconfigure>("set_parameters", true);
72  initialized_ = true;
73  }
74 
76  {
77  if(!initialized_)
78  {
79  ROS_ERROR("This recovery behavior has not been initialized, doing nothing.");
80  return;
81  }
82  ROS_WARN("Move slow and clear recovery behavior started.");
83  geometry_msgs::PoseStamped global_pose, local_pose;
84  global_costmap_->getRobotPose(global_pose);
85  local_costmap_->getRobotPose(local_pose);
86 
87  std::vector<geometry_msgs::Point> global_poly, local_poly;
88  geometry_msgs::Point pt;
89 
90  for(int i = -1; i <= 1; i+=2)
91  {
92  pt.x = global_pose.pose.position.x + i * clearing_distance_;
93  pt.y = global_pose.pose.position.y + i * clearing_distance_;
94  global_poly.push_back(pt);
95 
96  pt.x = global_pose.pose.position.x + i * clearing_distance_;
97  pt.y = global_pose.pose.position.y + -1.0 * i * clearing_distance_;
98  global_poly.push_back(pt);
99 
100  pt.x = local_pose.pose.position.x + i * clearing_distance_;
101  pt.y = local_pose.pose.position.y + i * clearing_distance_;
102  local_poly.push_back(pt);
103 
104  pt.x = local_pose.pose.position.x + i * clearing_distance_;
105  pt.y = local_pose.pose.position.y + -1.0 * i * clearing_distance_;
106  local_poly.push_back(pt);
107  }
108 
109  //clear the desired space in the costmaps
110  std::vector<boost::shared_ptr<costmap_2d::Layer> >* plugins = global_costmap_->getLayeredCostmap()->getPlugins();
111  for (std::vector<boost::shared_ptr<costmap_2d::Layer> >::iterator pluginp = plugins->begin(); pluginp != plugins->end(); ++pluginp) {
112  boost::shared_ptr<costmap_2d::Layer> plugin = *pluginp;
113  if(plugin->getName().find("obstacles")!=std::string::npos){
115  costmap = boost::static_pointer_cast<costmap_2d::ObstacleLayer>(plugin);
116  costmap->setConvexPolygonCost(global_poly, costmap_2d::FREE_SPACE);
117  }
118  }
119 
121  for (std::vector<boost::shared_ptr<costmap_2d::Layer> >::iterator pluginp = plugins->begin(); pluginp != plugins->end(); ++pluginp) {
122  boost::shared_ptr<costmap_2d::Layer> plugin = *pluginp;
123  if(plugin->getName().find("obstacles")!=std::string::npos){
125  costmap = boost::static_pointer_cast<costmap_2d::ObstacleLayer>(plugin);
126  costmap->setConvexPolygonCost(local_poly, costmap_2d::FREE_SPACE);
127  }
128  }
129 
130  //lock... just in case we're already speed limited
131  boost::mutex::scoped_lock l(mutex_);
132 
133  //get the old maximum speed for the robot... we'll want to set it back
134  if(!limit_set_)
135  {
137  {
138  ROS_ERROR("The planner %s, does not have the parameter %s", planner_nh_.getNamespace().c_str(), max_trans_param_name_.c_str());
139  }
140 
142  {
143  ROS_ERROR("The planner %s, does not have the parameter %s", planner_nh_.getNamespace().c_str(), max_rot_param_name_.c_str());
144  }
145  }
146 
147  //we also want to save our current position so that we can remove the speed limit we impose later on
148  speed_limit_pose_ = global_pose;
149 
150  //limit the speed of the robot until it moves a certain distance
152  limit_set_ = true;
154  }
155 
157  {
158  geometry_msgs::PoseStamped global_pose;
159  global_costmap_->getRobotPose(global_pose);
160  double x1 = global_pose.pose.position.x;
161  double y1 = global_pose.pose.position.y;
162 
163  double x2 = speed_limit_pose_.pose.position.x;
164  double y2 = speed_limit_pose_.pose.position.y;
165 
166  return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
167  }
168 
170  {
172  {
173  ROS_INFO("Moved far enough, removing speed limit.");
174  //have to do this because a system call within a timer cb does not seem to play nice
176  {
177  remove_limit_thread_->join();
178  delete remove_limit_thread_;
179  }
180  remove_limit_thread_ = new boost::thread(boost::bind(&MoveSlowAndClear::removeSpeedLimit, this));
181 
183  }
184  }
185 
187  {
188  boost::mutex::scoped_lock l(mutex_);
190  limit_set_ = false;
191  }
192 
193  void MoveSlowAndClear::setRobotSpeed(double trans_speed, double rot_speed)
194  {
195 
196  {
197  dynamic_reconfigure::Reconfigure vel_reconfigure;
198  dynamic_reconfigure::DoubleParameter new_trans;
199  new_trans.name = max_trans_param_name_;
200  new_trans.value = trans_speed;
201  vel_reconfigure.request.config.doubles.push_back(new_trans);
202  try {
204  ROS_INFO_STREAM("Recovery setting trans vel: " << trans_speed);
205  }
206  catch(...) {
207  ROS_ERROR("Something went wrong in the service call to dynamic_reconfigure");
208  }
209  }
210  {
211  dynamic_reconfigure::Reconfigure rot_reconfigure;
212  dynamic_reconfigure::DoubleParameter new_rot;
213  new_rot.name = max_rot_param_name_;
214  new_rot.value = rot_speed;
215  rot_reconfigure.request.config.doubles.push_back(new_rot);
216  try {
218  ROS_INFO_STREAM("Recovery setting rot vel: " << rot_speed);
219  }
220  catch(...) {
221  ROS_ERROR("Something went wrong in the service call to dynamic_reconfigure");
222  }
223  }
224  }
225 };
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
costmap_2d::Costmap2DROS * local_costmap_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void stop()
bool call(MReq &req, MRes &res)
std::vector< boost::shared_ptr< Layer > > * getPlugins()
static const unsigned char FREE_SPACE
#define ROS_WARN(...)
void setRobotSpeed(double trans_speed, double rot_speed)
void distanceCheck(const ros::TimerEvent &e)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void initialize(std::string n, tf2_ros::Buffer *tf, costmap_2d::Costmap2DROS *global_costmap, costmap_2d::Costmap2DROS *local_costmap)
Initialize the parameters of the behavior.
#define ROS_INFO(...)
bool getParam(const std::string &key, std::string &s) const
costmap_2d::Costmap2DROS * global_costmap_
geometry_msgs::PoseStamped speed_limit_pose_
bool getRobotPose(geometry_msgs::PoseStamped &global_pose) const
ros::ServiceClient planner_dynamic_reconfigure_service_
#define ROS_INFO_STREAM(args)
const std::string & getNamespace() const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
LayeredCostmap * getLayeredCostmap()


move_slow_and_clear
Author(s): Eitan Marder-Eppstein, contradict@gmail.com
autogenerated on Wed Jun 22 2022 02:07:17