grid_astar.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2017, 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 #ifndef PLANNER_CSPACE_GRID_ASTAR_H
31 #define PLANNER_CSPACE_GRID_ASTAR_H
32 
33 #include <memory>
34 #define _USE_MATH_DEFINES
35 #include <cmath>
36 #include <cfloat>
37 #include <list>
38 #include <map>
39 #include <unordered_map>
40 #include <vector>
41 
42 #include <boost/chrono.hpp>
43 
47 
48 #include <omp.h>
49 
50 template <int DIM = 3, int NONCYCLIC = 2>
51 class GridAstar
52 {
53 public:
56 
57  template <class T, int block_width = 0x20>
58  class Gridmap : public BlockMemGridmap<T, DIM, NONCYCLIC, block_width>
59  {
61  };
62 
64  {
65  public:
66  float p_;
67  float p_raw_;
69 
71  {
72  p_ = 0;
73  }
74  PriorityVec(const float& p, const float& p_raw, const Vec& v)
75  {
76  p_ = p;
77  p_raw_ = p_raw;
78  v_ = v;
79  }
80  bool operator<(const PriorityVec& b) const
81  {
82  // smaller first
83  return p_ > b.p_;
84  }
85  };
87  {
88  private:
89  const Vec p0_;
90  const Vec p1_;
91  const float cost_estim_;
92  const float cost_;
93 
94  public:
96  const Vec& p0, const Vec& p1,
97  const float cost_estim, const float cost)
98  : p0_(p0)
99  , p1_(p1)
100  , cost_estim_(cost_estim)
101  , cost_(cost)
102  {
103  }
104  const Vec& getParentPos() const
105  {
106  return p0_;
107  }
108  const Vec& getPos() const
109  {
110  return p1_;
111  }
112  const float getCost() const
113  {
114  return cost_;
115  }
117  {
118  return PriorityVec(cost_estim_, cost_, p1_);
119  }
120  };
121 
122 public:
123  constexpr int getDim() const
124  {
125  return DIM;
126  }
127  constexpr int getNoncyclic() const
128  {
129  return NONCYCLIC;
130  }
131  void setSearchTaskNum(const size_t& search_task_num)
132  {
133  search_task_num_ = search_task_num;
134  }
135 
136  void reset(const Vec size)
137  {
138  g_.reset(size);
139  g_.clear(FLT_MAX);
140  parents_.reserve(g_.ser_size() / 16);
141  open_.reserve(g_.ser_size() / 16);
142  }
144  : queue_size_limit_(0)
145  , search_task_num_(1)
146  {
147  }
148  explicit GridAstar(const Vec size)
149  {
150  reset(size);
151  queue_size_limit_ = 0;
152  }
153  void setQueueSizeLimit(const size_t size)
154  {
156  }
157 
158  bool search(
159  const Vec& s, const Vec& e,
160  std::list<Vec>& path,
161  std::function<float(const Vec&, Vec&, const Vec&, const Vec&)> cb_cost,
162  std::function<float(const Vec&, const Vec&)> cb_cost_estim,
163  std::function<std::vector<Vec>&(const Vec&, const Vec&, const Vec&)> cb_search,
164  std::function<bool(const std::list<Vec>&)> cb_progress,
165  const float cost_leave,
166  const float progress_interval,
167  const bool return_best = false)
168  {
169  return searchImpl(g_, s, e, path,
170  cb_cost, cb_cost_estim, cb_search, cb_progress,
171  cost_leave, progress_interval, return_best);
172  }
173 
174 protected:
176  Gridmap<float>& g,
177  const Vec& st, const Vec& en,
178  std::list<Vec>& path,
179  std::function<float(const Vec&, Vec&, const Vec&, const Vec&)> cb_cost,
180  std::function<float(const Vec&, const Vec&)> cb_cost_estim,
181  std::function<std::vector<Vec>&(const Vec&, const Vec&, const Vec&)> cb_search,
182  std::function<bool(const std::list<Vec>&)> cb_progress,
183  const float cost_leave,
184  const float progress_interval,
185  const bool return_best = false)
186  {
187  if (st == en)
188  {
189  return false;
190  }
191  Vec s = st;
192  Vec e = en;
193  for (int i = NONCYCLIC; i < DIM; i++)
194  {
195  s.cycleUnsigned(g.size());
196  e.cycleUnsigned(g.size());
197  }
198  g.clear(FLT_MAX);
199  open_.clear();
200  parents_.clear();
201 
202  g[s] = 0;
203  open_.push(PriorityVec(cb_cost_estim(s, e), 0, s));
204 
205  auto ts = boost::chrono::high_resolution_clock::now();
206 
207  Vec better = s;
208  int cost_estim_min = cb_cost_estim(s, e);
209 
210  while (true)
211  {
212  // Fetch tasks to be paralellized
213  if (open_.size() < 1)
214  {
215  // No fesible path
216  if (return_best)
217  {
218  findPath(s, better, path);
219  }
220  return false;
221  }
222  bool found(false);
223  std::vector<PriorityVec> centers;
224  for (size_t i = 0; i < search_task_num_; ++i)
225  {
226  if (open_.size() == 0)
227  break;
228  PriorityVec center = open_.top();
229  open_.pop();
230  if (center.v_ == e || center.p_ - center.p_raw_ <= cost_leave)
231  {
232  e = center.v_;
233  found = true;
234  break;
235  }
236  centers.push_back(center);
237  }
238  if (found)
239  break;
240  auto tnow = boost::chrono::high_resolution_clock::now();
241  if (boost::chrono::duration<float>(tnow - ts).count() >= progress_interval)
242  {
243  std::list<Vec> path_tmp;
244  ts = tnow;
245  findPath(s, better, path_tmp);
246  cb_progress(path_tmp);
247  }
248 
249 #pragma omp parallel
250  {
251  std::list<GridmapUpdate> updates;
252  std::list<Vec> dont;
253 
254 #pragma omp for schedule(static)
255  for (auto it = centers.cbegin(); it < centers.cend(); ++it)
256  {
257  const Vec p = it->v_;
258  const float c = it->p_raw_;
259  const float c_estim = it->p_;
260  if (c > g[p])
261  continue;
262 
263  if (c_estim - c < cost_estim_min)
264  {
265  cost_estim_min = c_estim - c;
266  better = p;
267  }
268 
269  const std::vector<Vec> search_list = cb_search(p, s, e);
270 
271  bool updated(false);
272  for (auto it = search_list.cbegin(); it < search_list.cend(); ++it)
273  {
274  while (1)
275  {
276  Vec next = p + *it;
277  next.cycleUnsigned(g.size());
278  if (next.isExceeded(g.size()))
279  break;
280  if (g[next] < 0)
281  break;
282 
283  const float cost_estim = cb_cost_estim(next, e);
284  if (cost_estim < 0 || cost_estim == FLT_MAX)
285  break;
286 
287  const float cost = cb_cost(p, next, s, e);
288  if (cost < 0 || cost == FLT_MAX)
289  break;
290 
291  const float cost_next = c + cost;
292  if (g[next] > cost_next)
293  {
294  updated = true;
295  updates.push_back(
296  GridmapUpdate(p, next, cost_next + cost_estim, cost_next));
297  }
298 
299  break;
300  }
301  }
302  if (!updated)
303  dont.push_back(p);
304  }
305 #pragma omp critical
306  {
307  for (const GridmapUpdate& u : updates)
308  {
309  if (g[u.getPos()] > u.getCost())
310  {
311  g[u.getPos()] = u.getCost();
312  parents_[u.getPos()] = u.getParentPos();
313  open_.push(u.getPriorityVec());
314  if (queue_size_limit_ > 0 && open_.size() > queue_size_limit_)
315  open_.pop_back();
316  }
317  }
318  for (const Vec& p : dont)
319  {
320  g[p] = -1;
321  }
322  } // omp critical
323  } // omp parallel
324  }
325 
326  return findPath(s, e, path);
327  }
328  bool findPath(const Vec& s, const Vec& e, std::list<Vec>& path)
329  {
330  Vec n = e;
331  while (true)
332  {
333  path.push_front(n);
334  if (n == s)
335  break;
336  if (parents_.find(n) == parents_.end())
337  return false;
338 
339  const Vec child = n;
340  n = parents_[child];
341  parents_.erase(child);
342  }
343  return true;
344  }
345 
346  Gridmap<float> g_;
347  std::unordered_map<Vec, Vec, Vec> parents_;
351 };
352 
353 #endif // PLANNER_CSPACE_GRID_ASTAR_H
const Vec & getPos() const
Definition: grid_astar.h:108
bool searchImpl(Gridmap< float > &g, const Vec &st, const Vec &en, std::list< Vec > &path, std::function< float(const Vec &, Vec &, const Vec &, const Vec &)> cb_cost, std::function< float(const Vec &, const Vec &)> cb_cost_estim, std::function< std::vector< Vec > &(const Vec &, const Vec &, const Vec &)> cb_search, std::function< bool(const std::list< Vec > &)> cb_progress, const float cost_leave, const float progress_interval, const bool return_best=false)
Definition: grid_astar.h:175
const PriorityVec getPriorityVec() const
Definition: grid_astar.h:116
void cycleUnsigned(const int res, const ArgList &...rest)
Definition: cyclic_vec.h:279
size_t queue_size_limit_
Definition: grid_astar.h:349
constexpr int getNoncyclic() const
Definition: grid_astar.h:127
const Vec & getParentPos() const
Definition: grid_astar.h:104
void setSearchTaskNum(const size_t &search_task_num)
Definition: grid_astar.h:131
const float getCost() const
Definition: grid_astar.h:112
PriorityVec(const float &p, const float &p_raw, const Vec &v)
Definition: grid_astar.h:74
void reset(const CyclicVecInt< DIM, NONCYCLIC > &size)
constexpr int getDim() const
Definition: grid_astar.h:123
void setQueueSizeLimit(const size_t size)
Definition: grid_astar.h:153
GridAstar(const Vec size)
Definition: grid_astar.h:148
size_t search_task_num_
Definition: grid_astar.h:350
Gridmap< float > g_
Definition: grid_astar.h:346
void clear(const T zero)
size_t ser_size() const
bool search(const Vec &s, const Vec &e, std::list< Vec > &path, std::function< float(const Vec &, Vec &, const Vec &, const Vec &)> cb_cost, std::function< float(const Vec &, const Vec &)> cb_cost_estim, std::function< std::vector< Vec > &(const Vec &, const Vec &, const Vec &)> cb_search, std::function< bool(const std::list< Vec > &)> cb_progress, const float cost_leave, const float progress_interval, const bool return_best=false)
Definition: grid_astar.h:158
std::unordered_map< Vec, Vec, Vec > parents_
Definition: grid_astar.h:347
const float cost_estim_
Definition: grid_astar.h:91
const CyclicVecInt< DIM, NONCYCLIC > & size() const
bool isExceeded(const CyclicVecBase< DIM, NONCYCLIC, int > &v) const
Definition: cyclic_vec.h:313
reservable_priority_queue< PriorityVec > open_
Definition: grid_astar.h:348
bool operator<(const PriorityVec &b) const
Definition: grid_astar.h:80
void reset(const Vec size)
Definition: grid_astar.h:136
GridmapUpdate(const Vec &p0, const Vec &p1, const float cost_estim, const float cost)
Definition: grid_astar.h:95
bool findPath(const Vec &s, const Vec &e, std::list< Vec > &path)
Definition: grid_astar.h:328


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Tue Jul 9 2019 05:00:13