Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
map_cspace.cpp
1 /*
2  * Player - One Hell of a Robot Server
3  * Copyright (C) 2000 Brian Gerkey & Kasper Stoy
4  * gerkey@usc.edu kaspers@robotics.usc.edu
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <cmath>
23 #include <cstring>
24 #include <queue>
25 #include "nav2_amcl/map/map.hpp"
26 
27 /*
28  * @struct CellData
29  * @brief Data about map cells
30  */
31 struct CellData
32 {
33  map_t * map_;
34  unsigned int i_, j_;
35  unsigned int src_i_, src_j_;
36  float occ_dist;
37 };
38 
39 /*
40  * @class CachedDistanceMap
41  * @brief Cached map with distances
42  */
44 {
45 public:
46  /*
47  * @brief CachedDistanceMap constructor
48  */
49  CachedDistanceMap(double scale, double max_dist)
50  : distances_(NULL), scale_(scale), max_dist_(max_dist)
51  {
52  cell_radius_ = max_dist / scale;
53  distances_ = new double *[cell_radius_ + 2];
54  for (int i = 0; i <= cell_radius_ + 1; i++) {
55  distances_[i] = new double[cell_radius_ + 2];
56  for (int j = 0; j <= cell_radius_ + 1; j++) {
57  distances_[i][j] = sqrt(i * i + j * j);
58  }
59  }
60  }
61 
62  /*
63  * @brief CachedDistanceMap destructor
64  */
66  {
67  if (distances_) {
68  for (int i = 0; i <= cell_radius_ + 1; i++) {
69  delete[] distances_[i];
70  }
71  delete[] distances_;
72  }
73  }
74  double ** distances_;
75  double scale_;
76  double max_dist_;
77  int cell_radius_;
78 };
79 
80 /*
81  * @brief operator<
82  */
83 bool operator<(const CellData & a, const CellData & b)
84 {
85  return a.occ_dist > b.occ_dist;
86 }
87 
88 /*
89  * @brief get_distance_map
90  * @param scale of cost information wrt distance
91  * @param max_dist Maximum distance to cache from occupied information
92  * @return Pointer to cached distance map
93  */
95 get_distance_map(double scale, double max_dist)
96 {
97  static CachedDistanceMap * cdm = NULL;
98 
99  if (!cdm || (cdm->scale_ != scale) || (cdm->max_dist_ != max_dist)) {
100  if (cdm) {
101  delete cdm;
102  }
103  cdm = new CachedDistanceMap(scale, max_dist);
104  }
105 
106  return cdm;
107 }
108 
109 /*
110  * @brief enqueue cell data for caching
111  */
112 void enqueue(
113  map_t * map, int i, int j,
114  int src_i, int src_j,
115  std::priority_queue<CellData> & Q,
116  CachedDistanceMap * cdm,
117  unsigned char * marked)
118 {
119  const int map_index = MAP_INDEX(map, i, j);
120 
121  if (marked[map_index]) {
122  return;
123  }
124 
125  int di = abs(i - src_i);
126  int dj = abs(j - src_j);
127  double distance = cdm->distances_[di][dj];
128 
129  if (distance > cdm->cell_radius_) {
130  return;
131  }
132 
133  map->cells[map_index].occ_dist = distance * map->scale;
134 
135  Q.emplace(CellData{map, static_cast<unsigned int>(i), static_cast<unsigned int>(j),
136  static_cast<unsigned int>(src_i), static_cast<unsigned int>(src_j),
137  map->cells[map_index].occ_dist});
138 
139  marked[map_index] = 1;
140 }
141 
142 /*
143  * @brief Update the cspace distance values
144  * @param map Map to update
145  * @param max_occ_distance Maximum distance for occpuancy interest
146  */
147 void map_update_cspace(map_t * map, double max_occ_dist)
148 {
149  unsigned char * marked;
150  std::priority_queue<CellData> Q;
151 
152  marked = new unsigned char[map->size_x * map->size_y];
153  memset(marked, 0, sizeof(unsigned char) * map->size_x * map->size_y);
154 
155  map->max_occ_dist = max_occ_dist;
156 
157  CachedDistanceMap * cdm = get_distance_map(map->scale, map->max_occ_dist);
158 
159  // Enqueue all the obstacle cells
160  CellData cell;
161  cell.map_ = map;
162  int loop_map_index;
163  for (int i = 0; i < map->size_x; i++) {
164  cell.src_i_ = cell.i_ = i;
165  for (int j = 0; j < map->size_y; j++) {
166  loop_map_index = MAP_INDEX(map, i, j);
167  if (map->cells[loop_map_index].occ_state == +1) {
168  map->cells[loop_map_index].occ_dist = 0.0;
169  cell.src_j_ = cell.j_ = j;
170  marked[loop_map_index] = 1;
171  Q.push(cell);
172  } else {
173  map->cells[loop_map_index].occ_dist = max_occ_dist;
174  }
175  }
176  }
177 
178  while (!Q.empty()) {
179  CellData current_cell = Q.top();
180  if (current_cell.i_ > 0) {
181  enqueue(
182  map, current_cell.i_ - 1, current_cell.j_,
183  current_cell.src_i_, current_cell.src_j_,
184  Q, cdm, marked);
185  }
186  if (current_cell.j_ > 0) {
187  enqueue(
188  map, current_cell.i_, current_cell.j_ - 1,
189  current_cell.src_i_, current_cell.src_j_,
190  Q, cdm, marked);
191  }
192  if (static_cast<int>(current_cell.i_) < map->size_x - 1) {
193  enqueue(
194  map, current_cell.i_ + 1, current_cell.j_,
195  current_cell.src_i_, current_cell.src_j_,
196  Q, cdm, marked);
197  }
198  if (static_cast<int>(current_cell.j_) < map->size_y - 1) {
199  enqueue(
200  map, current_cell.i_, current_cell.j_ + 1,
201  current_cell.src_i_, current_cell.src_j_,
202  Q, cdm, marked);
203  }
204 
205  Q.pop();
206  }
207 
208  delete[] marked;
209 }
Definition: map.hpp:62