rotate_recovery.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 #include <tf2/utils.h>
41 #include <ros/ros.h>
42 #include <geometry_msgs/Twist.h>
43 #include <geometry_msgs/Point.h>
44 #include <angles/angles.h>
45 #include <algorithm>
46 #include <string>
47 
48 
49 // register this planner as a RecoveryBehavior plugin
51 
52 namespace rotate_recovery
53 {
54 RotateRecovery::RotateRecovery(): local_costmap_(NULL), initialized_(false), world_model_(NULL)
55 {
56 }
57 
58 void RotateRecovery::initialize(std::string name, tf2_ros::Buffer*,
60 {
61  if (!initialized_)
62  {
63  local_costmap_ = local_costmap;
64 
65  // get some parameters from the parameter server
66  ros::NodeHandle private_nh("~/" + name);
67  ros::NodeHandle blp_nh("~/TrajectoryPlannerROS");
68 
69  // we'll simulate every degree by default
70  private_nh.param("sim_granularity", sim_granularity_, 0.017);
71  private_nh.param("frequency", frequency_, 20.0);
72 
73  acc_lim_th_ = nav_core::loadParameterWithDeprecation(blp_nh, "acc_lim_theta", "acc_lim_th", 3.2);
74  max_rotational_vel_ = nav_core::loadParameterWithDeprecation(blp_nh, "max_vel_theta", "max_rotational_vel", 1.0);
75  min_rotational_vel_ = nav_core::loadParameterWithDeprecation(blp_nh, "min_in_place_vel_theta", "min_in_place_rotational_vel", 0.4);
76  blp_nh.param("yaw_goal_tolerance", tolerance_, 0.10);
77 
78  world_model_ = new base_local_planner::CostmapModel(*local_costmap_->getCostmap());
79 
80  initialized_ = true;
81  }
82  else
83  {
84  ROS_ERROR("You should not call initialize twice on this object, doing nothing");
85  }
86 }
87 
88 RotateRecovery::~RotateRecovery()
89 {
90  delete world_model_;
91 }
92 
93 void RotateRecovery::runBehavior()
94 {
95  if (!initialized_)
96  {
97  ROS_ERROR("This object must be initialized before runBehavior is called");
98  return;
99  }
100 
101  if (local_costmap_ == NULL)
102  {
103  ROS_ERROR("The costmap passed to the RotateRecovery object cannot be NULL. Doing nothing.");
104  return;
105  }
106  ROS_WARN("Rotate recovery behavior started.");
107 
108  ros::Rate r(frequency_);
109  ros::NodeHandle n;
110  ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 10);
111 
112  geometry_msgs::PoseStamped global_pose;
113  local_costmap_->getRobotPose(global_pose);
114 
115  double current_angle = tf2::getYaw(global_pose.pose.orientation);
116  double start_angle = current_angle;
117 
118  bool got_180 = false;
119 
120  while (n.ok() &&
121  (!got_180 ||
122  std::fabs(angles::shortest_angular_distance(current_angle, start_angle)) > tolerance_))
123  {
124  // Update Current Angle
125  local_costmap_->getRobotPose(global_pose);
126  current_angle = tf2::getYaw(global_pose.pose.orientation);
127 
128  // compute the distance left to rotate
129  double dist_left;
130  if (!got_180)
131  {
132  // If we haven't hit 180 yet, we need to rotate a half circle plus the distance to the 180 point
133  double distance_to_180 = std::fabs(angles::shortest_angular_distance(current_angle, start_angle + M_PI));
134  dist_left = M_PI + distance_to_180;
135 
136  if (distance_to_180 < tolerance_)
137  {
138  got_180 = true;
139  }
140  }
141  else
142  {
143  // If we have hit the 180, we just have the distance back to the start
144  dist_left = std::fabs(angles::shortest_angular_distance(current_angle, start_angle));
145  }
146 
147  double x = global_pose.pose.position.x, y = global_pose.pose.position.y;
148 
149  // check if that velocity is legal by forward simulating
150  double sim_angle = 0.0;
151  while (sim_angle < dist_left)
152  {
153  double theta = current_angle + sim_angle;
154 
155  // make sure that the point is legal, if it isn't... we'll abort
156  double footprint_cost = world_model_->footprintCost(x, y, theta, local_costmap_->getRobotFootprint(), 0.0, 0.0);
157  if (footprint_cost < 0.0)
158  {
159  ROS_ERROR("Rotate recovery can't rotate in place because there is a potential collision. Cost: %.2f",
160  footprint_cost);
161  return;
162  }
163 
164  sim_angle += sim_granularity_;
165  }
166 
167  // compute the velocity that will let us stop by the time we reach the goal
168  double vel = sqrt(2 * acc_lim_th_ * dist_left);
169 
170  // make sure that this velocity falls within the specified limits
171  vel = std::min(std::max(vel, min_rotational_vel_), max_rotational_vel_);
172 
173  geometry_msgs::Twist cmd_vel;
174  cmd_vel.linear.x = 0.0;
175  cmd_vel.linear.y = 0.0;
176  cmd_vel.angular.z = vel;
177 
178  vel_pub.publish(cmd_vel);
179 
180  r.sleep();
181  }
182 }
183 }; // namespace rotate_recovery
nav_core::loadParameterWithDeprecation
param_t loadParameterWithDeprecation(const ros::NodeHandle &nh, const std::string current_name, const std::string old_name, const param_t &default_value)
angles::shortest_angular_distance
static double shortest_angular_distance(double from, double to)
rotate_recovery::RotateRecovery::RotateRecovery
RotateRecovery()
Constructor, make sure to call initialize in addition to actually initialize the object.
Definition: rotate_recovery.cpp:89
rotate_recovery
Definition: rotate_recovery.h:45
ros::Publisher
tf2::getYaw
double getYaw(const A &a)
utils.h
ros.h
rotate_recovery.h
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
base_local_planner::CostmapModel
PLUGINLIB_EXPORT_CLASS
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
ROS_WARN
#define ROS_WARN(...)
tf2_ros::Buffer
ros::Rate::sleep
bool sleep()
ros::NodeHandle::ok
bool ok() const
ROS_ERROR
#define ROS_ERROR(...)
rotate_recovery::RotateRecovery
A recovery behavior that rotates the robot in-place to attempt to clear out space.
Definition: rotate_recovery.h:86
class_list_macros.hpp
ros::Rate
costmap_2d::Costmap2DROS
nav_core::RecoveryBehavior
ros::NodeHandle
angles.h
parameter_magic.h


rotate_recovery
Author(s): Eitan Marder-Eppstein, contradict@gmail.com
autogenerated on Mon Mar 6 2023 03:50:43