LEMUR Packages: ompl_lemur or_lemur pr_bgl prpy_lemur
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Groups Pages
lpastar.h
Go to the documentation of this file.
1 
9 namespace pr_bgl
10 {
11 
28 template <typename Graph, typename AStarHeuristic,
29  typename LPAStarVisitor, typename PredecessorMap,
30  typename DistanceMap, typename DistanceLookaheadMap,
31  typename WeightMap, typename VertexIndexMap,
32  typename CompareFunction, typename CombineFunction,
33  typename CostInf, typename CostZero>
34 class lpastar
35 {
36 public:
37  typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
38  typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIter;
39  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
40  typedef typename boost::graph_traits<Graph>::out_edge_iterator OutEdgeIter;
41  typedef typename boost::graph_traits<Graph>::in_edge_iterator InEdgeIter;
42  typedef typename boost::property_traits<WeightMap>::value_type weight_type;
43 
44  const Graph & g;
45  Vertex v_start;
46  Vertex v_goal;
47  AStarHeuristic h;
48  LPAStarVisitor vis;
49  PredecessorMap predecessor;
50  DistanceMap distance;
51  DistanceLookaheadMap distance_lookahead;
52  WeightMap weight;
53  VertexIndexMap index_map;
54  CompareFunction compare;
55  CombineFunction combine;
56  CostInf inf;
57  CostZero zero;
58  weight_type goal_margin;
59 
61 
62  lpastar(
63  const Graph & g,
64  Vertex v_start, Vertex v_goal,
65  AStarHeuristic h,
66  LPAStarVisitor vis,
67  PredecessorMap predecessor,
68  DistanceMap distance, DistanceLookaheadMap distance_lookahead,
69  WeightMap weight,
70  VertexIndexMap index_map,
71  CompareFunction compare, CombineFunction combine,
72  CostInf inf, CostZero zero,
73  weight_type goal_margin):
74  g(g), v_start(v_start), v_goal(v_goal),
75  h(h), vis(vis), predecessor(predecessor),
76  distance(distance), distance_lookahead(distance_lookahead),
77  weight(weight), index_map(index_map),
78  compare(compare), combine(combine),
79  inf(inf), zero(zero),
80  goal_margin(goal_margin)
81  {
82  reset();
83  }
84 
85  void reset()
86  {
87  VertexIter vi, vi_end;
88  for (boost::tie(vi,vi_end)=vertices(g); vi!=vi_end; ++vi)
89  {
90  put(distance_lookahead, *vi, inf);
91  put(distance, *vi, inf);
92  }
93  put(predecessor, v_start, v_start);
94  put(distance_lookahead, v_start, zero);
95  queue.reset();
96  queue.insert(get(index_map,v_start), std::make_pair(h(v_start),0));
97  }
98 
99  inline std::pair<weight_type,weight_type> calculate_key(Vertex u, bool do_goal_margin=false)
100  {
101  weight_type minval
102  = std::min(get(distance,u), get(distance_lookahead,u));
103  if (do_goal_margin)
104  minval += goal_margin;
105  return std::make_pair(minval+h(u), minval);
106  }
107 
108  // this is called to update vertex v due to either:
109  // - u_dist being updated OR
110  // - uv_weight being updated
111  // it will recalculate v's lookahead distance
112  // and return whether v's lookahead distance changed
113  // (if predecessor changed, but lookahead value didnt, return false)
114  inline bool update_predecessor(Vertex u, Vertex v, weight_type uv_weight)
115  {
116  // start vertex dist lookahead is always zero
117  if (v == v_start)
118  return false;
119 
120  // current predecessor and lookahead value
121  Vertex v_pred = get(predecessor, v);
122  weight_type v_look_old = get(distance_lookahead, v);
123  weight_type v_look_u = combine(get(distance,u), uv_weight);
124 
125  if (v_pred == u) // u was previously relied upon
126  {
127  // if dist through u decreased, then u is still best; just update value
128  if (v_look_u == v_look_old)
129  {
130  return false;
131  }
132  else if (v_look_u < v_look_old)
133  {
134  put(distance_lookahead, v, v_look_u);
135  return true;
136  }
137  else // dist through u increased
138  {
139  // so we need to search for a potentially new best predecessessor
140  weight_type v_look_best = inf;
141  Vertex v_pred_best;
142  InEdgeIter ei, ei_end;
143  for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
144  {
145  weight_type v_look_uu = combine(get(distance,source(*ei,g)), get(weight,*ei));
146  if (v_look_uu < v_look_best)
147  {
148  v_look_best = v_look_uu;
149  v_pred_best = source(*ei,g);
150  }
151  }
152  if (v_look_best != inf)
153  put(predecessor, v, v_pred_best);
154  if (v_look_best == v_look_old)
155  {
156  return false;
157  }
158  else
159  {
160  put(distance_lookahead, v, v_look_best);
161  return true;
162  }
163  }
164  }
165  else // some other (existing) predecessor was used by v
166  {
167  if (v_look_u < v_look_old) // dist through u is better
168  {
169  put(predecessor, v, u);
170  put(distance_lookahead, v, v_look_u);
171  return true;
172  }
173  else // u is not better
174  {
175  return false;
176  }
177  }
178  }
179 
180  // this must be called called when u's dist and/or lookahead dist
181  // (and therefore consistency) may have been changed
182  // this ensures u is in the queue correctly
183  inline void update_vertex(Vertex u)
184  {
185  weight_type u_dist = get(distance,u);
186  bool is_consistent = (u_dist == get(distance_lookahead,u));
187  size_t u_idx = get(index_map,u);
188  if (is_consistent)
189  {
190  if (queue.contains(u_idx))
191  queue.remove(u_idx);
192  }
193  else // not consistent
194  {
195  if (queue.contains(u_idx))
196  queue.update(u_idx, calculate_key(u));
197  else
198  queue.insert(u_idx, calculate_key(u));
199  }
200  }
201 
202  void compute_shortest_path()
203  {
204  while (queue.size()
205  && (queue.top_key() < calculate_key(v_goal,true) // do_goal_margin
206  || get(distance_lookahead,v_goal) != get(distance,v_goal)))
207  {
208  Vertex u = vertex(queue.top_idx(), g);
209 
210  vis.examine_vertex(u, g);
211  queue.remove_min();
212  if (get(distance,u) > get(distance_lookahead,u))
213  {
214  put(distance, u, get(distance_lookahead,u));
215  OutEdgeIter ei, ei_end;
216  for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
217  {
218  Vertex v = target(*ei,g);
219  bool lookahead_changed = update_predecessor(u, v, get(weight,*ei));
220  if (lookahead_changed)
221  update_vertex(v);
222  }
223  }
224  else
225  {
226  put(distance, u, inf);
227  update_vertex(u);
228  OutEdgeIter ei, ei_end;
229  for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
230  {
231  Vertex v = target(*ei,g);
232  bool lookahead_changed = update_predecessor(u, v, get(weight,*ei));
233  if (lookahead_changed)
234  update_vertex(v);
235  }
236  }
237  }
238  }
239 };
240 
241 } // namespace pr_bgl
Binary min-heap with index lookups.
Definition: heap_indexed.h:34
Implements the Lifelong Planning A* incremental search algorithm.
Definition: lpastar.h:34