grid_astar.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014-2017, the neonavigation authors
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the copyright holder nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #ifndef PLANNER_CSPACE_GRID_ASTAR_H
00031 #define PLANNER_CSPACE_GRID_ASTAR_H
00032 
00033 #include <memory>
00034 #define _USE_MATH_DEFINES
00035 #include <cmath>
00036 #include <cfloat>
00037 #include <list>
00038 #include <map>
00039 #include <unordered_map>
00040 #include <vector>
00041 
00042 #include <boost/chrono.hpp>
00043 
00044 #include <planner_cspace/reservable_priority_queue.h>
00045 #include <planner_cspace/cyclic_vec.h>
00046 #include <planner_cspace/blockmem_gridmap.h>
00047 
00048 #include <omp.h>
00049 
00050 template <int DIM = 3, int NONCYCLIC = 2>
00051 class GridAstar
00052 {
00053 public:
00054   using Vec = CyclicVecInt<DIM, NONCYCLIC>;
00055   using Vecf = CyclicVecFloat<DIM, NONCYCLIC>;
00056 
00057   template <class T, int block_width = 0x20>
00058   class Gridmap : public BlockMemGridmap<T, DIM, NONCYCLIC, block_width>
00059   {
00060     using BlockMemGridmap<T, DIM, NONCYCLIC, block_width>::BlockMemGridmap;
00061   };
00062 
00063   class PriorityVec
00064   {
00065   public:
00066     float p_;
00067     float p_raw_;
00068     Vec v_;
00069 
00070     PriorityVec()
00071     {
00072       p_ = 0;
00073     }
00074     PriorityVec(const float& p, const float& p_raw, const Vec& v)
00075     {
00076       p_ = p;
00077       p_raw_ = p_raw;
00078       v_ = v;
00079     }
00080     bool operator<(const PriorityVec& b) const
00081     {
00082       // smaller first
00083       return p_ > b.p_;
00084     }
00085   };
00086 
00087 protected:
00088   Gridmap<float> g_;
00089   std::unordered_map<Vec, Vec, Vec> parents_;
00090   reservable_priority_queue<PriorityVec> open_;
00091   size_t queue_size_limit_;
00092   size_t search_task_num_;
00093 
00094 public:
00095   constexpr int getDim() const
00096   {
00097     return DIM;
00098   }
00099   constexpr int getNoncyclic() const
00100   {
00101     return NONCYCLIC;
00102   }
00103   void setSearchTaskNum(const size_t& search_task_num)
00104   {
00105     search_task_num_ = search_task_num;
00106   }
00107 
00108   void reset(const Vec size)
00109   {
00110     g_.reset(size);
00111     g_.clear(FLT_MAX);
00112     parents_.reserve(g_.ser_size() / 16);
00113     open_.reserve(g_.ser_size() / 16);
00114   }
00115   GridAstar()
00116     : queue_size_limit_(0)
00117     , search_task_num_(1)
00118   {
00119   }
00120   explicit GridAstar(const Vec size)
00121   {
00122     reset(size);
00123     queue_size_limit_ = 0;
00124   }
00125   void setQueueSizeLimit(const size_t size)
00126   {
00127     queue_size_limit_ = size;
00128   }
00129 
00130   bool search(
00131       const Vec& s, const Vec& e,
00132       std::list<Vec>& path,
00133       std::function<float(const Vec&, Vec&, const Vec&, const Vec&)> cb_cost,
00134       std::function<float(const Vec&, const Vec&)> cb_cost_estim,
00135       std::function<std::vector<Vec>&(const Vec&, const Vec&, const Vec&)> cb_search,
00136       std::function<bool(const std::list<Vec>&)> cb_progress,
00137       const float cost_leave,
00138       const float progress_interval,
00139       const bool return_best = false)
00140   {
00141     return searchImpl(g_, s, e, path,
00142                       cb_cost, cb_cost_estim, cb_search, cb_progress,
00143                       cost_leave, progress_interval, return_best);
00144   }
00145   bool searchImpl(
00146       Gridmap<float>& g,
00147       const Vec& st, const Vec& en,
00148       std::list<Vec>& path,
00149       std::function<float(const Vec&, Vec&, const Vec&, const Vec&)> cb_cost,
00150       std::function<float(const Vec&, const Vec&)> cb_cost_estim,
00151       std::function<std::vector<Vec>&(const Vec&, const Vec&, const Vec&)> cb_search,
00152       std::function<bool(const std::list<Vec>&)> cb_progress,
00153       const float cost_leave,
00154       const float progress_interval,
00155       const bool return_best = false)
00156   {
00157     if (st == en)
00158     {
00159       return false;
00160     }
00161     Vec s = st;
00162     Vec e = en;
00163     for (int i = NONCYCLIC; i < DIM; i++)
00164     {
00165       s.cycleUnsigned(g.size());
00166       e.cycleUnsigned(g.size());
00167     }
00168     g.clear(FLT_MAX);
00169     open_.clear();
00170     parents_.clear();
00171 
00172     g[s] = 0;
00173     open_.push(PriorityVec(cb_cost_estim(s, e), 0, s));
00174 
00175     auto ts = boost::chrono::high_resolution_clock::now();
00176 
00177     Vec better = s;
00178     int cost_estim_min = cb_cost_estim(s, e);
00179 
00180     while (true)
00181     {
00182       // Fetch tasks to be paralellized
00183       if (open_.size() < 1)
00184       {
00185         // No fesible path
00186         if (return_best)
00187         {
00188           findPath(s, better, path);
00189         }
00190         return false;
00191       }
00192       bool found(false);
00193       std::vector<PriorityVec> centers;
00194       for (size_t i = 0; i < search_task_num_; ++i)
00195       {
00196         if (open_.size() == 0)
00197           break;
00198         PriorityVec center = open_.top();
00199         open_.pop();
00200         if (center.v_ == e || center.p_ - center.p_raw_ <= cost_leave)
00201         {
00202           e = center.v_;
00203           found = true;
00204           break;
00205         }
00206         centers.push_back(center);
00207       }
00208       if (found)
00209         break;
00210       auto tnow = boost::chrono::high_resolution_clock::now();
00211       if (boost::chrono::duration<float>(tnow - ts).count() >= progress_interval)
00212       {
00213         std::list<Vec> path_tmp;
00214         ts = tnow;
00215         findPath(s, better, path_tmp);
00216         cb_progress(path_tmp);
00217       }
00218 
00219 #pragma omp parallel for schedule(static)
00220       for (auto it = centers.begin(); it < centers.end(); ++it)
00221       {
00222         const Vec p = it->v_;
00223         const float c = it->p_raw_;
00224         const float c_estim = it->p_;
00225         float& gp = g[p];
00226         if (c > gp)
00227           continue;
00228 
00229         if (c_estim - c < cost_estim_min)
00230         {
00231           cost_estim_min = c_estim - c;
00232           better = p;
00233         }
00234 
00235         const std::vector<Vec> search_list = cb_search(p, s, e);
00236         int updates = 0;
00237 
00238         for (auto it = search_list.begin(); it < search_list.end(); ++it)
00239         {
00240           while (1)
00241           {
00242             Vec next = p + *it;
00243             for (int i = NONCYCLIC; i < DIM; i++)
00244             {
00245               next.cycleUnsigned(g.size());
00246             }
00247             if ((unsigned int)next[0] >= (unsigned int)g.size()[0] ||
00248                 (unsigned int)next[1] >= (unsigned int)g.size()[1])
00249               break;
00250             if (g[next] < 0)
00251               break;
00252 
00253             const float cost_estim = cb_cost_estim(next, e);
00254             if (cost_estim < 0 || cost_estim == FLT_MAX)
00255               break;
00256 
00257             const float cost = cb_cost(p, next, s, e);
00258             if (cost < 0 || cost == FLT_MAX)
00259               break;
00260 
00261             float& gnext = g[next];
00262             if (gnext > c + cost)
00263             {
00264               gnext = c + cost;
00265 #pragma omp critical
00266               {
00267                 parents_[next] = p;
00268                 open_.push(PriorityVec(c + cost + cost_estim, c + cost, next));
00269                 if (queue_size_limit_ > 0 &&
00270                     open_.size() > queue_size_limit_)
00271                   open_.pop_back();
00272               }
00273               updates++;
00274             }
00275             break;
00276           }
00277         }
00278         if (updates == 0)
00279         {
00280           gp = -1;
00281         }
00282       }
00283       // printf("(parents %d)\n", (int)parents_.size());
00284     }
00285     // printf("AStar search finished (parents %d)\n", (int)parents_.size());
00286 
00287     return findPath(s, e, path);
00288   }
00289   bool findPath(const Vec& s, const Vec& e, std::list<Vec>& path)
00290   {
00291     Vec n = e;
00292     while (true)
00293     {
00294       path.push_front(n);
00295       // printf("p- %d %d %d   %0.4f\n", n[0], n[1], n[2], g_[n]);
00296       if (n == s)
00297         break;
00298       if (parents_.find(n) == parents_.end())
00299       {
00300         n = parents_[n];
00301         // printf("px %d %d %d\n", n[0], n[1], n[2]);
00302         return false;
00303       }
00304       n = parents_[n];
00305     }
00306     return true;
00307   }
00308 };
00309 
00310 #endif  // PLANNER_CSPACE_GRID_ASTAR_H


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Sat Jun 22 2019 20:07:27