distance_map.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2021, the neonavigation authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <cmath>
31 #include <limits>
32 #include <unordered_map>
33 #include <utility>
34 #include <vector>
35 
36 #include <omp.h>
37 
41 
42 namespace planner_cspace
43 {
44 namespace planner_3d
45 {
48  const Astar::Vec& s_rough)
49 {
50  debug_data_.search_queue_size = open.size();
52 
53  std::vector<Astar::PriorityVec> centers;
54  centers.reserve(num_cost_estim_task_);
55  edges_.clear();
56 
58 
59 #pragma omp parallel
60  {
61  std::vector<Astar::GridmapUpdate> updates;
62  updates.reserve(num_cost_estim_task_ * search_diffs_.size() / omp_get_num_threads());
63  std::unordered_map<Astar::Vec, bool, Astar::Vec> edges_local;
64  edges_local.reserve(open.capacity() / omp_get_num_threads());
65 
66  const float range_overshoot = p_.euclid_cost[0] * (p_.range + p_.local_range + p_.longcut_range);
67  const float weight_linear = p_.resolution / 100.0;
68 
69  while (true)
70  {
71 #pragma omp barrier
72 #pragma omp single
73  {
74  centers.clear();
75  const float start_cost = g_[s_rough];
76  for (size_t i = 0; i < static_cast<size_t>(num_cost_estim_task_);)
77  {
78  if (open.size() < 1)
79  break;
80  Astar::PriorityVec center(open.top());
81  open.pop();
82  if (center.p_raw_ > g_[center.v_])
83  continue;
84  if (center.p_raw_ - range_overshoot > start_cost)
85  {
86  edges_[center.v_] = true;
87  continue;
88  }
89  centers.emplace_back(std::move(center));
90  ++i;
91  }
92  } // omp single
93 
94  if (centers.size() == 0)
95  break;
96  updates.clear();
97 
98 #pragma omp for schedule(static)
99  for (auto it = centers.cbegin(); it < centers.cend(); ++it)
100  {
101  const Astar::Vec p = it->v_;
102 
103  for (const SearchDiffs& ds : search_diffs_)
104  {
105  const Astar::Vec d = ds.d;
106  const Astar::Vec next = p + d;
107 
108  if (static_cast<size_t>(next[0]) >= static_cast<size_t>(p_.size[0]) ||
109  static_cast<size_t>(next[1]) >= static_cast<size_t>(p_.size[1]))
110  {
111  continue;
112  }
113 
114  float cost = ds.euclid_cost;
115 
116  const float gnext = g_[next];
117 
118  if (gnext < g_[p] + cost)
119  {
120  // Skip as this search task has no chance to find better way.
121  continue;
122  }
123 
124  {
125  float sum = 0, sum_hist = 0;
126  bool collision = false;
127  for (const auto& d : ds.pos)
128  {
129  const Astar::Vec pos = p + d;
130  const char c = cm_rough_[pos];
131  if (c > 99)
132  {
133  collision = true;
134  break;
135  }
136  sum += c;
137  sum_hist += bbf_costmap_.getCost(pos);
138  }
139  if (collision)
140  {
141  edges_local[p] = true;
142  continue;
143  }
144  cost +=
145  (weight_linear * ds.grid_to_len) *
146  (sum * cc_.weight_costmap_ + sum_hist * cc_.weight_remembered_);
147 
148  if (cost < 0)
149  {
150  cost = 0;
152  }
153  }
154 
155  const float cost_next = it->p_raw_ + cost;
156  if (gnext > cost_next)
157  {
158  updates.emplace_back(p, next, cost_next, cost_next);
159  }
160  }
161  }
162 #pragma omp barrier
163 #pragma omp critical
164  {
165  for (const Astar::GridmapUpdate& u : updates)
166  {
167  if (g_[u.getPos()] > u.getCost())
168  {
169  g_[u.getPos()] = u.getCost();
170  open.push(std::move(u.getPriorityVec()));
171  }
172  }
173  for (const auto& e : edges_local)
174  {
175  edges_[e.first] = true;
176  }
177  } // omp critical
178  }
179  } // omp parallel
180 }
181 
183  const BlockMemGridmapBase<char, 3, 2>& cm_rough,
184  const CostmapBBF& bbf_costmap)
185  : cm_rough_(cm_rough)
186  , bbf_costmap_(bbf_costmap)
187 {
188 }
189 
190 void DistanceMap::setParams(const CostCoeff& cc, const int num_cost_estim_task)
191 {
192  cc_ = cc;
193  num_cost_estim_task_ = num_cost_estim_task;
194 }
195 
196 void DistanceMap::init(const GridAstarModel3D::Ptr model, const Params& p)
197 {
198  if (p.size[0] != p_.size[0] || p.size[1] != p_.size[1])
199  {
200  // Typical open/erase queue size is be approximated by perimeter of the map
201  pq_open_.reserve((p.size[0] + p.size[1]) * 2);
202  pq_erase_.reserve((p.size[0] + p.size[1]) * 2);
203 
204  g_.reset(Astar::Vec(p.size[0], p.size[1], 1));
205  g_.clear(0);
206  }
207  p_ = p;
208  search_diffs_.clear();
209 
210  const int range_rough = 4;
211  for (Astar::Vec d(-range_rough, 0, 0); d[0] <= range_rough; d[0]++)
212  {
213  for (d[1] = -range_rough; d[1] <= range_rough; d[1]++)
214  {
215  if (d[0] == 0 && d[1] == 0)
216  continue;
217  if (d.sqlen() > range_rough * range_rough)
218  continue;
219 
220  SearchDiffs diffs;
221 
222  const float grid_to_len = d.gridToLenFactor();
223  const int dist = d.len();
224  const float dpx = static_cast<float>(d[0]) / dist;
225  const float dpy = static_cast<float>(d[1]) / dist;
226  Astar::Vecf pos(0, 0, 0);
227  for (int i = 0; i < dist; i++)
228  {
229  Astar::Vec ipos(pos);
230  if (diffs.pos.size() == 0 || diffs.pos.back() != ipos)
231  {
232  diffs.pos.push_back(std::move(ipos));
233  }
234  pos[0] += dpx;
235  pos[1] += dpy;
236  }
237  diffs.grid_to_len = grid_to_len;
238  diffs.d = d;
239  diffs.euclid_cost = model->euclidCostRough(d);
240  search_diffs_.push_back(std::move(diffs));
241  }
242  }
243 }
244 
246  const Astar::Vec& s, const Astar::Vec& e,
247  const Rect& rect)
248 {
249  Astar::Vec p_cost_min;
250  float cost_min = std::numeric_limits<float>::max();
251  for (Astar::Vec p(0, rect.min[1], 0); p[1] <= rect.max[1]; p[1]++)
252  {
253  for (p[0] = rect.min[0]; p[0] <= rect.max[0]; p[0]++)
254  {
255  if (cost_min > g_[p])
256  {
257  p_cost_min = p;
258  cost_min = g_[p];
259  }
260  }
261  }
262  if (cost_min == 0.0)
263  {
264  // Goal is in the updated area
265  create(s, e);
266  return;
267  }
268  pq_open_.clear();
269  pq_erase_.clear();
270 
271  const Astar::Vec e_rough(e[0], e[1], 0);
272  const Astar::Vec s_rough(s[0], s[1], 0);
273 
274  if (cost_min != std::numeric_limits<float>::max())
275  {
276  pq_erase_.emplace(0.0, 0.0, p_cost_min);
277  }
278 
279  if (g_[s_rough] > cost_min)
280  {
281  pq_erase_.emplace(0.0, 0.0, s_rough);
282  }
283 
284  while (true)
285  {
286  if (pq_erase_.size() < 1)
287  break;
288  const Astar::PriorityVec center(pq_erase_.top());
289  const Astar::Vec p = center.v_;
290  pq_erase_.pop();
291 
292  if (g_[p] == std::numeric_limits<float>::max())
293  continue;
294  g_[p] = std::numeric_limits<float>::max();
295 
296  for (Astar::Vec d(-1, 0, 0); d[0] <= 1; d[0]++)
297  {
298  for (d[1] = -1; d[1] <= 1; d[1]++)
299  {
300  if (!((d[0] == 0) ^ (d[1] == 0)))
301  continue;
302  Astar::Vec next = p + d;
303  next[2] = 0;
304  if ((unsigned int)next[0] >= (unsigned int)p_.size[0] ||
305  (unsigned int)next[1] >= (unsigned int)p_.size[1])
306  continue;
307  const float gn = g_[next];
308  if (gn == std::numeric_limits<float>::max())
309  continue;
310  if (gn < cost_min)
311  {
312  pq_open_.emplace(gn, gn, next);
313  continue;
314  }
315  pq_erase_.emplace(0.0, 0.0, next);
316  if (edges_.find(next) != edges_.end())
317  {
318  edges_.erase(next);
319  }
320  }
321  }
322  }
323 
324  if (pq_open_.size() == 0)
325  {
326  pq_open_.emplace(-p_.euclid_cost[0] * 0.5, -p_.euclid_cost[0] * 0.5, e_rough);
327  }
328 
329  for (const auto& e : edges_)
330  {
331  const float p = g_[e.first];
332  pq_open_.emplace(p, p, e.first);
333  }
334 
335  fillCostmap(pq_open_, s_rough);
336 }
337 
338 void DistanceMap::create(const Astar::Vec& s, const Astar::Vec& e)
339 {
340  pq_open_.clear();
341  pq_erase_.clear();
342  g_.clear(std::numeric_limits<float>::max());
343 
344  const Astar::Vec e_rough(e[0], e[1], 0);
345  const Astar::Vec s_rough(s[0], s[1], 0);
346 
347  g_[e_rough] = -p_.euclid_cost[0] * 0.5; // Decrement to reduce calculation error
348  pq_open_.push(Astar::PriorityVec(g_[e_rough], g_[e_rough], e_rough));
349  fillCostmap(pq_open_, s_rough);
350  g_[e_rough] = 0;
351 }
352 
353 } // namespace planner_3d
354 } // namespace planner_cspace
d
void init(const GridAstarModel3D::Ptr model, const Params &p)
CyclicVecInt< DIM, NONCYCLIC > Vec
Definition: grid_astar.h:67
DistanceMap(const BlockMemGridmapBase< char, 3, 2 > &cm_rough, const CostmapBBF &bbf_costmap)
char getCost(const Vec &p) const
Definition: costmap_bbf.h:69
const BlockMemGridmapBase< char, 3, 2 > & cm_rough_
Definition: distance_map.h:128
reservable_priority_queue< Astar::PriorityVec > pq_erase_
Definition: distance_map.h:136
void setParams(const CostCoeff &cc, const int num_cost_estim_task)
reservable_priority_queue< Astar::PriorityVec > pq_open_
Definition: distance_map.h:134
std::vector< SearchDiffs > search_diffs_
Definition: distance_map.h:131
void fillCostmap(reservable_priority_queue< Astar::PriorityVec > &open, const Astar::Vec &s_rough)
void create(const Astar::Vec &s, const Astar::Vec &e)
std::unordered_map< Astar::Vec, bool, Astar::Vec > edges_
Definition: distance_map.h:135
void update(const Astar::Vec &s, const Astar::Vec &e, const Rect &rect)


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Mon Jul 3 2023 02:39:06