base_local_planner
map_grid.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
35 #include <costmap_2d/cost_values.h>
36 using namespace std;
37 
38 namespace base_local_planner{
39 
40  MapGrid::MapGrid()
41  : size_x_(0), size_y_(0)
42  {
43  }
44 
45  MapGrid::MapGrid(unsigned int size_x, unsigned int size_y)
46  : size_x_(size_x), size_y_(size_y)
47  {
48  commonInit();
49  }
50 
52  size_y_ = mg.size_y_;
53  size_x_ = mg.size_x_;
54  map_ = mg.map_;
55  }
56 
58  //don't allow construction of zero size grid
59  ROS_ASSERT(size_y_ != 0 && size_x_ != 0);
60 
61  map_.resize(size_y_ * size_x_);
62 
63  //make each cell aware of its location in the grid
64  for(unsigned int i = 0; i < size_y_; ++i){
65  for(unsigned int j = 0; j < size_x_; ++j){
66  unsigned int id = size_x_ * i + j;
67  map_[id].cx = j;
68  map_[id].cy = i;
69  }
70  }
71  }
72 
73  size_t MapGrid::getIndex(int x, int y){
74  return size_x_ * y + x;
75  }
76 
78  size_y_ = mg.size_y_;
79  size_x_ = mg.size_x_;
80  map_ = mg.map_;
81  return *this;
82  }
83 
84  void MapGrid::sizeCheck(unsigned int size_x, unsigned int size_y){
85  if(map_.size() != size_x * size_y)
86  map_.resize(size_x * size_y);
87 
88  if(size_x_ != size_x || size_y_ != size_y){
89  size_x_ = size_x;
90  size_y_ = size_y;
91 
92  for(unsigned int i = 0; i < size_y_; ++i){
93  for(unsigned int j = 0; j < size_x_; ++j){
94  int index = size_x_ * i + j;
95  map_[index].cx = j;
96  map_[index].cy = i;
97  }
98  }
99  }
100  }
101 
102 
103  inline bool MapGrid::updatePathCell(MapCell* current_cell, MapCell* check_cell,
104  const costmap_2d::Costmap2D& costmap){
105 
106  //if the cell is an obstacle set the max path distance
107  unsigned char cost = costmap.getCost(check_cell->cx, check_cell->cy);
108  if(! getCell(check_cell->cx, check_cell->cy).within_robot &&
109  (cost == costmap_2d::LETHAL_OBSTACLE ||
111  check_cell->target_dist = obstacleCosts();
112  return false;
113  }
114 
115  double new_target_dist = current_cell->target_dist + 1;
116  if (new_target_dist < check_cell->target_dist) {
117  check_cell->target_dist = new_target_dist;
118  }
119  return true;
120  }
121 
122 
123  //reset the path_dist and goal_dist fields for all cells
125  for(unsigned int i = 0; i < map_.size(); ++i) {
126  map_[i].target_dist = unreachableCellCosts();
127  map_[i].target_mark = false;
128  map_[i].within_robot = false;
129  }
130  }
131 
133  std::vector<geometry_msgs::PoseStamped>& global_plan_out, double resolution) {
134  if (global_plan_in.size() == 0) {
135  return;
136  }
137  double last_x = global_plan_in[0].pose.position.x;
138  double last_y = global_plan_in[0].pose.position.y;
139  global_plan_out.push_back(global_plan_in[0]);
140 
141  double min_sq_resolution = resolution * resolution;
142 
143  for (unsigned int i = 1; i < global_plan_in.size(); ++i) {
144  double loop_x = global_plan_in[i].pose.position.x;
145  double loop_y = global_plan_in[i].pose.position.y;
146  double sqdist = (loop_x - last_x) * (loop_x - last_x) + (loop_y - last_y) * (loop_y - last_y);
147  if (sqdist > min_sq_resolution) {
148  int steps = ceil((sqrt(sqdist)) / resolution);
149  // add a points in-between
150  double deltax = (loop_x - last_x) / steps;
151  double deltay = (loop_y - last_y) / steps;
152  // TODO: Interpolate orientation
153  for (int j = 1; j < steps; ++j) {
154  geometry_msgs::PoseStamped pose;
155  pose.pose.position.x = last_x + j * deltax;
156  pose.pose.position.y = last_y + j * deltay;
157  pose.pose.position.z = global_plan_in[i].pose.position.z;
158  pose.pose.orientation = global_plan_in[i].pose.orientation;
159  pose.header = global_plan_in[i].header;
160  global_plan_out.push_back(pose);
161  }
162  }
163  global_plan_out.push_back(global_plan_in[i]);
164  last_x = loop_x;
165  last_y = loop_y;
166  }
167  }
168 
169  //update what map cells are considered path based on the global_plan
171  const std::vector<geometry_msgs::PoseStamped>& global_plan) {
172  sizeCheck(costmap.getSizeInCellsX(), costmap.getSizeInCellsY());
173 
174  bool started_path = false;
175 
176  queue<MapCell*> path_dist_queue;
177 
178  std::vector<geometry_msgs::PoseStamped> adjusted_global_plan;
179  adjustPlanResolution(global_plan, adjusted_global_plan, costmap.getResolution());
180  if (adjusted_global_plan.size() != global_plan.size()) {
181  ROS_DEBUG("Adjusted global plan resolution, added %zu points", adjusted_global_plan.size() - global_plan.size());
182  }
183  unsigned int i;
184  // put global path points into local map until we reach the border of the local map
185  for (i = 0; i < adjusted_global_plan.size(); ++i) {
186  double g_x = adjusted_global_plan[i].pose.position.x;
187  double g_y = adjusted_global_plan[i].pose.position.y;
188  unsigned int map_x, map_y;
189  if (costmap.worldToMap(g_x, g_y, map_x, map_y) && costmap.getCost(map_x, map_y) != costmap_2d::NO_INFORMATION) {
190  MapCell& current = getCell(map_x, map_y);
191  current.target_dist = 0.0;
192  current.target_mark = true;
193  path_dist_queue.push(&current);
194  started_path = true;
195  } else if (started_path) {
196  break;
197  }
198  }
199  if (!started_path) {
200  ROS_ERROR("None of the %d first of %zu (%zu) points of the global plan were in the local costmap and free",
201  i, adjusted_global_plan.size(), global_plan.size());
202  return;
203  }
204 
205  computeTargetDistance(path_dist_queue, costmap);
206  }
207 
208  //mark the point of the costmap as local goal where global_plan first leaves the area (or its last point)
210  const std::vector<geometry_msgs::PoseStamped>& global_plan) {
211  sizeCheck(costmap.getSizeInCellsX(), costmap.getSizeInCellsY());
212 
213  int local_goal_x = -1;
214  int local_goal_y = -1;
215  bool started_path = false;
216 
217  std::vector<geometry_msgs::PoseStamped> adjusted_global_plan;
218  adjustPlanResolution(global_plan, adjusted_global_plan, costmap.getResolution());
219 
220  // skip global path points until we reach the border of the local map
221  for (unsigned int i = 0; i < adjusted_global_plan.size(); ++i) {
222  double g_x = adjusted_global_plan[i].pose.position.x;
223  double g_y = adjusted_global_plan[i].pose.position.y;
224  unsigned int map_x, map_y;
225  if (costmap.worldToMap(g_x, g_y, map_x, map_y) && costmap.getCost(map_x, map_y) != costmap_2d::NO_INFORMATION) {
226  local_goal_x = map_x;
227  local_goal_y = map_y;
228  started_path = true;
229  } else {
230  if (started_path) {
231  break;
232  }// else we might have a non pruned path, so we just continue
233  }
234  }
235  if (!started_path) {
236  ROS_ERROR("None of the points of the global plan were in the local costmap, global plan points too far from robot");
237  return;
238  }
239 
240  queue<MapCell*> path_dist_queue;
241  if (local_goal_x >= 0 && local_goal_y >= 0) {
242  MapCell& current = getCell(local_goal_x, local_goal_y);
243  costmap.mapToWorld(local_goal_x, local_goal_y, goal_x_, goal_y_);
244  current.target_dist = 0.0;
245  current.target_mark = true;
246  path_dist_queue.push(&current);
247  }
248 
249  computeTargetDistance(path_dist_queue, costmap);
250  }
251 
252 
253 
255  MapCell* current_cell;
256  MapCell* check_cell;
257  unsigned int last_col = size_x_ - 1;
258  unsigned int last_row = size_y_ - 1;
259  while(!dist_queue.empty()){
260  current_cell = dist_queue.front();
261 
262 
263  dist_queue.pop();
264 
265  if(current_cell->cx > 0){
266  check_cell = current_cell - 1;
267  if(!check_cell->target_mark){
268  //mark the cell as visisted
269  check_cell->target_mark = true;
270  if(updatePathCell(current_cell, check_cell, costmap)) {
271  dist_queue.push(check_cell);
272  }
273  }
274  }
275 
276  if(current_cell->cx < last_col){
277  check_cell = current_cell + 1;
278  if(!check_cell->target_mark){
279  check_cell->target_mark = true;
280  if(updatePathCell(current_cell, check_cell, costmap)) {
281  dist_queue.push(check_cell);
282  }
283  }
284  }
285 
286  if(current_cell->cy > 0){
287  check_cell = current_cell - size_x_;
288  if(!check_cell->target_mark){
289  check_cell->target_mark = true;
290  if(updatePathCell(current_cell, check_cell, costmap)) {
291  dist_queue.push(check_cell);
292  }
293  }
294  }
295 
296  if(current_cell->cy < last_row){
297  check_cell = current_cell + size_x_;
298  if(!check_cell->target_mark){
299  check_cell->target_mark = true;
300  if(updatePathCell(current_cell, check_cell, costmap)) {
301  dist_queue.push(check_cell);
302  }
303  }
304  }
305  }
306  }
307 
308 };
base_local_planner::MapGrid::commonInit
void commonInit()
Utility to share initialization code across constructors.
Definition: map_grid.cpp:57
base_local_planner::MapGrid::unreachableCellCosts
double unreachableCellCosts()
Definition: map_grid.h:176
base_local_planner::MapGrid::size_y_
unsigned int size_y_
The dimensions of the grid.
Definition: map_grid.h:223
base_local_planner::MapGrid::MapGrid
MapGrid()
Creates a 0x0 map by default.
Definition: map_grid.cpp:40
costmap_2d::Costmap2D::worldToMap
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
base_local_planner::MapGrid::goal_x_
double goal_x_
Definition: map_grid.h:221
std::vector< geometry_msgs::PoseStamped >
std::vector::size
T size(T... args)
costmap_2d::INSCRIBED_INFLATED_OBSTACLE
static const unsigned char INSCRIBED_INFLATED_OBSTACLE
base_local_planner::MapGrid::adjustPlanResolution
static void adjustPlanResolution(const std::vector< geometry_msgs::PoseStamped > &global_plan_in, std::vector< geometry_msgs::PoseStamped > &global_plan_out, double resolution)
Definition: map_grid.cpp:132
costmap_2d::NO_INFORMATION
static const unsigned char NO_INFORMATION
base_local_planner::MapGrid::map_
std::vector< MapCell > map_
Storage for the MapCells.
Definition: map_grid.h:227
costmap_2d::Costmap2D
base_local_planner::MapGrid::size_x_
unsigned int size_x_
Definition: map_grid.h:223
costmap_2d::Costmap2D::mapToWorld
void mapToWorld(unsigned int mx, unsigned int my, double &wx, double &wy) const
cost_values.h
std::queue
std::queue::front
T front(T... args)
std::sqrt
T sqrt(T... args)
std::vector::push_back
T push_back(T... args)
map_grid.h
base_local_planner::MapGrid::obstacleCosts
double obstacleCosts()
Definition: map_grid.h:168
base_local_planner::MapCell::cy
unsigned int cy
Cell index in the grid map.
Definition: map_cell.h:89
base_local_planner::MapGrid::setLocalGoal
void setLocalGoal(const costmap_2d::Costmap2D &costmap, const std::vector< geometry_msgs::PoseStamped > &global_plan)
Update what cell is considered the next local goal.
Definition: map_grid.cpp:209
base_local_planner::MapGrid::updatePathCell
bool updatePathCell(MapCell *current_cell, MapCell *check_cell, const costmap_2d::Costmap2D &costmap)
Used to update the distance of a cell in path distance computation.
Definition: map_grid.cpp:103
std::queue::pop
T pop(T... args)
base_local_planner::MapGrid::resetPathDist
void resetPathDist()
reset path distance fields for all cells
Definition: map_grid.cpp:124
costmap_2d::Costmap2D::getSizeInCellsY
unsigned int getSizeInCellsY() const
base_local_planner::MapGrid::computeTargetDistance
void computeTargetDistance(std::queue< MapCell * > &dist_queue, const costmap_2d::Costmap2D &costmap)
Compute the distance from each cell in the local map grid to the planned path.
Definition: map_grid.cpp:254
costmap_2d::LETHAL_OBSTACLE
static const unsigned char LETHAL_OBSTACLE
std::ceil
T ceil(T... args)
base_local_planner::MapCell::target_dist
double target_dist
Distance to planner's path.
Definition: map_cell.h:91
base_local_planner::MapGrid
A grid of MapCell cells that is used to propagate path and goal distances for the trajectory controll...
Definition: map_grid.h:84
base_local_planner::MapGrid::getCell
MapCell & getCell(unsigned int x, unsigned int y)
Definition: map_grid.h:119
base_local_planner::MapGrid::operator=
MapGrid & operator=(const MapGrid &mg)
Assignment operator for a MapGrid.
Definition: map_grid.cpp:77
base_local_planner::MapCell::cx
unsigned int cx
Definition: map_cell.h:89
base_local_planner::MapCell::target_mark
bool target_mark
Marks for computing path/goal distances.
Definition: map_cell.h:93
std
base_local_planner::MapGrid::sizeCheck
void sizeCheck(unsigned int size_x, unsigned int size_y)
check if we need to resize
Definition: map_grid.cpp:84
std::queue::empty
T empty(T... args)
std::queue::push
T push(T... args)
base_local_planner::MapGrid::goal_y_
double goal_y_
The goal distance was last computed from.
Definition: map_grid.h:221
costmap_2d::Costmap2D::getResolution
double getResolution() const
base_local_planner::MapGrid::setTargetCells
void setTargetCells(const costmap_2d::Costmap2D &costmap, const std::vector< geometry_msgs::PoseStamped > &global_plan)
Update what cells are considered path based on the global plan.
Definition: map_grid.cpp:170
costmap_2d::Costmap2D::getSizeInCellsX
unsigned int getSizeInCellsX() const
base_local_planner::MapCell::within_robot
bool within_robot
Mark for cells within the robot footprint.
Definition: map_cell.h:95
base_local_planner
Definition: alignment_cost_function.h:7
base_local_planner::MapGrid::getIndex
size_t getIndex(int x, int y)
Returns a 1D index into the MapCell array for a 2D index.
Definition: map_grid.cpp:73
costmap_2d::Costmap2D::getCost
unsigned char getCost(unsigned int mx, unsigned int my) const
base_local_planner::MapCell
Stores path distance and goal distance information used for scoring trajectories.
Definition: map_cell.h:76