car_maneuver_recovery.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2016, George Kouros.
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 the copyright holder 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: George Kouros
36  *********************************************************************/
37 
39 #include <pluginlib/class_list_macros.h>
40 #include <geometry_msgs/Point.h>
41 #include <boost/foreach.hpp>
42 
43 // register this class as a recovery behavior plugin
44 PLUGINLIB_DECLARE_CLASS(car_maneuver_recovery, CarManeuverRecovery,
45  car_maneuver_recovery::CarManeuverRecovery, nav_core::RecoveryBehavior)
46 
47 namespace car_maneuver_recovery
48 {
49 
50  CarManeuverRecovery::CarManeuverRecovery()
51  : tfListener_(NULL), globalCostmapROS_(NULL), localCostmapROS_(NULL)
52  , worldModel_(NULL), initialized_(false)
53  {
54  }
55 
56 
57  CarManeuverRecovery::~CarManeuverRecovery()
58  {
59  delete worldModel_;
60  }
61 
62 
63  void CarManeuverRecovery::initialize(std::string name,
64  tf::TransformListener* tfListener,
65  costmap_2d::Costmap2DROS* globalCostmapROS,
66  costmap_2d::Costmap2DROS* localCostmapROS)
67  {
68  if (initialized_)
69  {
70  ROS_ERROR("Plugin already initialized. Doing nothing.");
71  return;
72  }
73 
74  // store arguments
75  name_ = name;
76  tfListener_ = tfListener;
77  globalCostmapROS_ = globalCostmapROS;
78  localCostmapROS_ = localCostmapROS;
79 
80  // load parameters
81  ros::NodeHandle pnh("~/" + name);
82 
83  pnh.param("recovery_speed", recoverySpeed_, 0.5);
84  pnh.param("recovery_steering_angle", recoverySteeringAngle_, 0.5);
85  pnh.param("wheelbase", wheelbase_, 0.5);
86  pnh.param<bool>("four_wheel_steering", fourWheelSteering_, false);
87  pnh.param<bool>("crab_steering", crabSteering_, false);
88  pnh.param<double>("timeout", timeout_, 5.0);
89 
90  twistPub_ = pnh.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
91 
92  // get world model
93  worldModel_ = new base_local_planner::CostmapModel(
94  *localCostmapROS_->getCostmap());
95 
96  // set initialization state
97  initialized_ = true;
98  }
99 
100 
101  void CarManeuverRecovery::runBehavior()
102  {
103  if (!initialized_)
104  {
105  ROS_ERROR("Plugin must be initialized before recovery behavior is run!");
106  return;
107  }
108 
109  if(globalCostmapROS_ == NULL || localCostmapROS_ == NULL)
110  {
111  ROS_ERROR("The costmaps passed to the CarManeuverRecovery object cannot "
112  "be NULL. Doing nothing.");
113  return;
114  }
115 
116  ROS_WARN("Car Maneuver recovery behavior started.");
117 
118  ros::Rate loopRate(5);
119  ros::Time time = ros::Time::now();
120 
121  while (ros::ok() && (ros::Time::now() - time).toSec() < timeout_)
122  {
123  // get robot footprint
124  std::vector<geometry_msgs::Point> footprint;
125  localCostmapROS_->getOrientedFootprint(footprint);
126 
127  double frontLineCost = lineCost(footprint[2], footprint[3]);
128  double rearLineCost = lineCost(footprint[0], footprint[1]);
129  double leftLineCost = lineCost(footprint[1], footprint[2]);
130  double rightLineCost = lineCost(footprint[0], footprint[3]);
131 
132  ROS_DEBUG("Front side cost: %f", frontLineCost);
133  ROS_DEBUG("Rear side cost: %f", rearLineCost);
134  ROS_DEBUG("Left side cost: %f", leftLineCost);
135  ROS_DEBUG("Right side cost: %f", rightLineCost);
136 
137  int front = frontLineCost < 128;
138  int rear = rearLineCost < 128;
139  int left = leftLineCost < 128;
140  int right = rightLineCost < 128;
141 
142  if (front && rear && left && right) // robot is free
143  break;
144  else if (!front && !rear) // robot cannot go sideways or turn in place
145  {
146  ROS_FATAL("Unable to recover!");
147  break;
148  }
149 
150  geometry_msgs::Twist cmd;
151 
152  double speed;
153 
154  if (front && rear)
155  speed = recoverySpeed_ * ((frontLineCost > rearLineCost) ? 1 : -1);
156  else
157  speed = (front - rear) * recoverySpeed_;
158 
159  if (fourWheelSteering_) // 4WS steering
160  {
161  cmd.linear.x = speed;
162 
163  if (crabSteering_) // 4WS crab steering
164  cmd.linear.y = (left - right) * fabs(speed)
165  * tan(recoverySteeringAngle_);
166  else // 4WS counter steering
167  {
168  double fsa =
169  (speed > 0.0) ? (left - right) * recoverySteeringAngle_ : 0.0;
170  double rsa =
171  (speed < 0.0) ? (right - left) * recoverySteeringAngle_ : 0.0;
172  double beta = atan((tan(fsa) + tan(rsa)) / 2);
173  cmd.linear.x = speed;
174  cmd.linear.y = cmd.linear.x * tan(beta);
175  cmd.angular.z = speed * cos(beta) * (tan(fsa) - tan(rsa))/ wheelbase_;
176  }
177  }
178  else // ackermann steering
179  {
180  double fsa = (left - right) * recoverySteeringAngle_;
181  double beta = atan(tan(fsa) / 2);
182  cmd.linear.x = speed * sqrt(1 / (1 + pow(tan(beta), 2)));
183  cmd.linear.y = cmd.linear.x * tan(beta);
184  cmd.angular.z = speed * cos(beta) * tan(fsa) / wheelbase_;
185  }
186 
187  // publish cmd
188  twistPub_.publish(cmd);
189 
190  loopRate.sleep();
191  }
192 
193  if ((ros::Time::now() - time).toSec() < timeout_)
194  ROS_WARN("Car Maneuver recovery behavior timed out!");
195 
196  ROS_WARN("Car maneuver recovery behavior finished.");
197  }
198 
199 
200  double CarManeuverRecovery::lineCost(geometry_msgs::Point point1,
201  geometry_msgs::Point point2)
202  {
203  unsigned int x[2], y[2];
204  localCostmapROS_->getCostmap()->worldToMap(point1.x, point1.y, x[0], y[0]);
205  localCostmapROS_->getCostmap()->worldToMap(point2.x, point2.y, x[1], y[1]);
206 
207  double cost = 0.0;
208 
209  for (unsigned int i = 0; i < 2; i++)
210  cost += localCostmapROS_->getCostmap()->getCost(x[i], y[i]) / 2;
211 
212  return cost;
213  }
214 
215 } // namespace car_maneuver_recovery
PLUGINLIB_DECLARE_CLASS(car_maneuver_recovery, CarManeuverRecovery, car_maneuver_recovery::CarManeuverRecovery, nav_core::RecoveryBehavior) namespace car_maneuver_recovery
A move base plugin that implements car like maneuvers as a recovery behavior.


car-maneuver-recovery
Author(s): George Kouros
autogenerated on Mon Aug 1 2016 17:52:25