PlannerData.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Rice University
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Rice University nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 /* Author: Ryan Luna */
36 
37 #include "ompl/base/PlannerData.h"
38 #include "ompl/base/PlannerDataGraph.h"
39 #include "ompl/base/StateStorage.h"
40 #include "ompl/base/OptimizationObjective.h"
41 #include "ompl/base/objectives/PathLengthOptimizationObjective.h"
42 #include "ompl/base/ScopedState.h"
43 
44 #include <boost/graph/graphviz.hpp>
45 #include <boost/graph/graphml.hpp>
46 #include <boost/graph/dijkstra_shortest_paths.hpp>
47 #include <boost/property_map/function_property_map.hpp>
48 
49 // This is a convenient macro to cast the void* graph pointer as the
50 // Boost.Graph structure from PlannerDataGraph.h
51 #define graph_ reinterpret_cast<ompl::base::PlannerData::Graph*>(graphRaw_)
52 
55 const unsigned int ompl::base::PlannerData::INVALID_INDEX = std::numeric_limits<unsigned int>::max();
56 
57 ompl::base::PlannerData::PlannerData (const SpaceInformationPtr &si) : si_(si)
58 {
59  graphRaw_ = new Graph();
60 }
61 
63 {
64  freeMemory();
65 
66  if (graph_)
67  {
68  delete graph_;
69  graphRaw_ = nullptr;
70  }
71 }
72 
74 {
75  freeMemory();
76  decoupledStates_.clear();
77 }
78 
80 {
81  unsigned int count = 0;
82  for (unsigned int i = 0; i < numVertices(); ++i)
83  {
84  PlannerDataVertex &vtx = getVertex(i);
85  // If this vertex's state is not in the decoupled list, clone it and add it
86  if (decoupledStates_.find(const_cast<State*>(vtx.getState())) == decoupledStates_.end())
87  {
88  const State *oldState = vtx.getState();
89  State *clone = si_->cloneState(oldState);
90  decoupledStates_.insert(clone);
91  // Replacing the shallow state pointer with our shiny new clone
92  vtx.state_ = clone;
93 
94  // Remove oldState from stateIndexMap
95  stateIndexMap_.erase(oldState);
96  // Add the new, cloned state to stateIndexMap
97  stateIndexMap_[clone] = i;
98  count++;
99  }
100  }
101 }
102 
103 unsigned int ompl::base::PlannerData::getEdges (unsigned int v, std::vector<unsigned int>& edgeList) const
104 {
105  std::pair<Graph::AdjIterator, Graph::AdjIterator> iterators = boost::adjacent_vertices(boost::vertex(v, *graph_), *graph_);
106 
107  edgeList.clear();
108  boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
109  for (Graph::AdjIterator iter = iterators.first; iter != iterators.second; ++iter)
110  edgeList.push_back(vertices[*iter]);
111 
112  return edgeList.size();
113 }
114 
115 unsigned int ompl::base::PlannerData::getEdges (unsigned int v, std::map<unsigned int, const PlannerDataEdge*>& edgeMap) const
116 {
117  std::pair<Graph::OEIterator, Graph::OEIterator> iterators = boost::out_edges(boost::vertex(v, *graph_), *graph_);
118 
119  edgeMap.clear();
120  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
121  boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
122  for (Graph::OEIterator iter = iterators.first; iter != iterators.second; ++iter)
123  edgeMap[vertices[boost::target(*iter, *graph_)]] = boost::get(edges, *iter);
124 
125  return edgeMap.size();
126 }
127 
128 unsigned int ompl::base::PlannerData::getIncomingEdges (unsigned int v, std::vector<unsigned int>& edgeList) const
129 {
130  std::pair<Graph::IEIterator, Graph::IEIterator> iterators = boost::in_edges(boost::vertex(v, *graph_), *graph_);
131 
132  edgeList.clear();
133  boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
134  for (Graph::IEIterator iter = iterators.first; iter != iterators.second; ++iter)
135  edgeList.push_back(vertices[boost::source(*iter, *graph_)]);
136 
137  return edgeList.size();
138 }
139 
140 unsigned int ompl::base::PlannerData::getIncomingEdges (unsigned int v, std::map<unsigned int, const PlannerDataEdge*> &edgeMap) const
141 {
142  std::pair<Graph::IEIterator, Graph::IEIterator> iterators = boost::in_edges(boost::vertex(v, *graph_), *graph_);
143 
144  edgeMap.clear();
145  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
146  boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
147  for (Graph::IEIterator iter = iterators.first; iter != iterators.second; ++iter)
148  edgeMap[vertices[boost::source(*iter, *graph_)]] = boost::get(edges, *iter);
149 
150  return edgeMap.size();
151 }
152 
153 bool ompl::base::PlannerData::getEdgeWeight(unsigned int v1, unsigned int v2, Cost* weight) const
154 {
155  Graph::Edge e;
156  bool exists;
157  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
158 
159  if (exists)
160  {
161  boost::property_map<Graph::Type, boost::edge_weight_t>::type edges = get(boost::edge_weight, *graph_);
162  *weight = edges[e];
163  return true;
164  }
165 
166  return false;
167 }
168 
169 bool ompl::base::PlannerData::setEdgeWeight(unsigned int v1, unsigned int v2, Cost weight)
170 {
171  Graph::Edge e;
172  bool exists;
173  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
174 
175  if (exists)
176  {
177  boost::property_map<Graph::Type, boost::edge_weight_t>::type edges = get(boost::edge_weight, *graph_);
178  edges[e] = weight;
179  }
180 
181  return exists;
182 }
183 
184 bool ompl::base::PlannerData::edgeExists (unsigned int v1, unsigned int v2) const
185 {
186  Graph::Edge e;
187  bool exists;
188 
189  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
190  return exists;
191 }
192 
194 {
195  return vertexIndex(v) != INVALID_INDEX;
196 }
197 
199 {
200  return boost::num_vertices(*graph_);
201 }
202 
204 {
205  return boost::num_edges(*graph_);
206 }
207 
209 {
210  if (index >= boost::num_vertices(*graph_))
211  return NO_VERTEX;
212 
213  boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
214  return *(vertices[boost::vertex(index, *graph_)]);
215 }
216 
218 {
219  if (index >= boost::num_vertices(*graph_))
220  return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);
221 
222  boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
223  return *(vertices[boost::vertex(index, *graph_)]);
224 }
225 
226 const ompl::base::PlannerDataEdge& ompl::base::PlannerData::getEdge (unsigned int v1, unsigned int v2) const
227 {
228  Graph::Edge e;
229  bool exists;
230  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
231 
232  if (exists)
233  {
234  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
235  return *(boost::get(edges, e));
236  }
237 
238  return NO_EDGE;
239 }
240 
242 {
243  Graph::Edge e;
244  bool exists;
245  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
246 
247  if (exists)
248  {
249  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
250  return *(boost::get(edges, e));
251  }
252 
253  return const_cast<ompl::base::PlannerDataEdge&>(NO_EDGE);
254 }
255 
256 void ompl::base::PlannerData::printGraphviz (std::ostream& out) const
257 {
258  boost::write_graphviz(out, *graph_);
259 }
260 
261 namespace
262 {
263  // Property map for extracting the edge weight of a graph edge as
264  // a double for printGraphML.
265  double edgeWeightAsDouble(ompl::base::PlannerData::Graph::Type &g,
267  {
268  return get(boost::edge_weight_t(), g)[e].value();
269  }
270 
271  // Property map for extracting states as arrays of doubles
272  std::string vertexCoords (ompl::base::PlannerData::Graph::Type &g,
275  {
276  s = *get(vertex_type_t(), g)[v]->getState();
277  std::vector<double> coords(s.reals());
278  std::ostringstream sstream;
279  if (coords.size()>0)
280  {
281  sstream << coords[0];
282  for (std::size_t i = 1; i < coords.size(); ++i)
283  sstream << ',' << coords[i];
284  }
285  return sstream.str();
286  }
287 }
288 
289 void ompl::base::PlannerData::printGraphML (std::ostream& out) const
290 {
291  // For some reason, make_function_property_map can't infer its
292  // template arguments corresponding to edgeWeightAsDouble's type
293  // signature. So, we have to use this horribly verbose
294  // instantiation of the property map.
295  //
296  // \todo Can we use make_function_property_map() here and have it
297  // infer the property template arguments?
298  boost::function_property_map<
299  std::function<double (ompl::base::PlannerData::Graph::Edge)>,
301  double>
302  weightmap(std::bind(&edgeWeightAsDouble, *graph_, std::placeholders::_1));
304  boost::function_property_map<
305  std::function<std::string (ompl::base::PlannerData::Graph::Vertex)>,
307  std::string >
308  coordsmap(std::bind(&vertexCoords, *graph_, s, std::placeholders::_1));
309 
310 
311  // Not writing vertex or edge structures.
312  boost::dynamic_properties dp;
313  dp.property("weight", weightmap);
314  dp.property("coords", coordsmap);
315 
316  boost::write_graphml(out, *graph_, dp);
317 }
318 
320 {
321  std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(v.getState());
322  if (it != stateIndexMap_.end())
323  return it->second;
324  return INVALID_INDEX;
325 }
326 
328 {
329  return startVertexIndices_.size();
330 }
331 
333 {
334  return goalVertexIndices_.size();
335 }
336 
337 unsigned int ompl::base::PlannerData::getStartIndex (unsigned int i) const
338 {
339  if (i >= startVertexIndices_.size())
340  return INVALID_INDEX;
341 
342  return startVertexIndices_[i];
343 }
344 
345 unsigned int ompl::base::PlannerData::getGoalIndex (unsigned int i) const
346 {
347  if (i >= goalVertexIndices_.size())
348  return INVALID_INDEX;
349 
350  return goalVertexIndices_[i];
351 }
352 
353 bool ompl::base::PlannerData::isStartVertex (unsigned int index) const
354 {
355  return std::binary_search(startVertexIndices_.begin(), startVertexIndices_.end(), index);
356 }
357 
358 bool ompl::base::PlannerData::isGoalVertex (unsigned int index) const
359 {
360  return std::binary_search(goalVertexIndices_.begin(), goalVertexIndices_.end(), index);
361 }
362 
364 {
365  if (i >= startVertexIndices_.size())
366  return NO_VERTEX;
367 
368  return getVertex(startVertexIndices_[i]);
369 }
370 
372 {
373  if (i >= startVertexIndices_.size())
374  return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);
375 
376  return getVertex(startVertexIndices_[i]);
377 }
378 
380 {
381  if (i >= goalVertexIndices_.size())
382  return NO_VERTEX;
383 
384  return getVertex(goalVertexIndices_[i]);
385 }
386 
388 {
389  if (i >= goalVertexIndices_.size())
390  return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);
391 
392  return getVertex(goalVertexIndices_[i]);
393 }
394 
396 {
397  // Do not add vertices with null states
398  if (st.getState() == nullptr)
399  return INVALID_INDEX;
400 
401  unsigned int index = vertexIndex(st);
402  if (index == INVALID_INDEX) // Vertex does not already exist
403  {
404  // Clone the state to prevent object slicing when retrieving this object
405  ompl::base::PlannerDataVertex *clone = st.clone();
406  Graph::Vertex v = boost::add_vertex(clone, *graph_);
407  boost::property_map<Graph::Type, boost::vertex_index_t>::type vertexIndexMap = get(boost::vertex_index, *graph_);
408 
409  // Insert this entry into the stateIndexMap_ for fast lookup
410  stateIndexMap_[clone->getState()] = numVertices()-1;
411  return vertexIndexMap[v];
412  }
413  return index;
414 }
415 
417 {
418  unsigned int index = addVertex(v);
419  if (index != INVALID_INDEX)
421 
422  return index;
423 }
424 
426 {
427  unsigned int index = addVertex(v);
428 
429  if (index != INVALID_INDEX)
430  markGoalState(v.getState());
431 
432  return index;
433 }
434 
435 bool ompl::base::PlannerData::addEdge(unsigned int v1, unsigned int v2, const PlannerDataEdge &edge, Cost weight)
436 {
437  // If either of the vertices do not exist, don't add an edge
438  if (v1 >= numVertices() || v2 >= numVertices())
439  return false;
440 
441  // If an edge already exists, do not add one
442  if (edgeExists (v1, v2))
443  return false;
444 
445  // Clone the edge to prevent object slicing
446  ompl::base::PlannerDataEdge *clone = edge.clone();
447  const Graph::edge_property_type properties(clone, weight);
448 
449  Graph::Edge e;
450  bool added = false;
451  tie(e, added) = boost::add_edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), properties, *graph_);
452 
453  if (!added)
454  delete clone;
455 
456  return added;
457 }
458 
460 {
461  unsigned int index1 = addVertex(v1);
462  unsigned int index2 = addVertex(v2);
463 
464  // If neither vertex was added or already exists, return false
465  if (index1 == INVALID_INDEX && index2 == INVALID_INDEX)
466  return false;
467 
468  // Only add the edge if both vertices exist
469  if (index1 != INVALID_INDEX && index2 != INVALID_INDEX)
470  return addEdge (index1, index2, edge, weight);
471 
472  return true;
473 }
474 
476 {
477  unsigned int index = vertexIndex (st);
478  if (index != INVALID_INDEX)
479  return removeVertex (index);
480  return false;
481 }
482 
483 bool ompl::base::PlannerData::removeVertex (unsigned int vIndex)
484 {
485  if (vIndex >= boost::num_vertices(*graph_))
486  return false;
487 
488  // Retrieve a list of all edge structures
489  boost::property_map<Graph::Type, edge_type_t>::type edgePropertyMap = get(edge_type_t(), *graph_);
490 
491  // Freeing memory associated with outgoing edges of this vertex
492  std::pair<Graph::OEIterator, Graph::OEIterator> oiterators = boost::out_edges(boost::vertex(vIndex, *graph_), *graph_);
493  for (Graph::OEIterator iter = oiterators.first; iter != oiterators.second; ++iter)
494  delete edgePropertyMap[*iter];
495 
496  // Freeing memory associated with incoming edges of this vertex
497  std::pair<Graph::IEIterator, Graph::IEIterator> initerators = boost::in_edges(boost::vertex(vIndex, *graph_), *graph_);
498  for (Graph::IEIterator iter = initerators.first; iter != initerators.second; ++iter)
499  delete edgePropertyMap[*iter];
500 
501  // Remove this vertex from stateIndexMap_, and update the map
502  stateIndexMap_.erase(getVertex(vIndex).getState());
503  boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
504  for (unsigned int i = vIndex+1; i < boost::num_vertices(*graph_); ++i)
505  stateIndexMap_[vertices[boost::vertex(i, *graph_)]->getState()]--;
506 
507  // Remove this vertex from the start and/or goal index list, if it exists. Update the lists.
508  std::vector<unsigned int>::iterator it = std::find(startVertexIndices_.begin(), startVertexIndices_.end(), vIndex);
509  if (it != startVertexIndices_.end())
510  startVertexIndices_.erase(it);
511  for (size_t i = 0; i < startVertexIndices_.size(); ++i)
512  if (startVertexIndices_[i] > vIndex)
513  startVertexIndices_[i]--;
514 
515  it = std::find(goalVertexIndices_.begin(), goalVertexIndices_.end(), vIndex);
516  if (it != goalVertexIndices_.end())
517  goalVertexIndices_.erase(it);
518  for (size_t i = 0; i < goalVertexIndices_.size(); ++i)
519  if (goalVertexIndices_[i] > vIndex)
520  goalVertexIndices_[i]--;
521 
522  // If the state attached to this vertex was decoupled, free it here
523  State *vtxState = const_cast<State*>(getVertex(vIndex).getState());
524  if (decoupledStates_.find(vtxState) != decoupledStates_.end())
525  {
526  decoupledStates_.erase(vtxState);
527  si_->freeState(vtxState);
528  vtxState = nullptr;
529  }
530 
531  // Slay the vertex
532  boost::clear_vertex(boost::vertex(vIndex, *graph_), *graph_);
533  boost::property_map<Graph::Type, vertex_type_t>::type vertexTypeMap = get(vertex_type_t(), *graph_);
534  delete vertexTypeMap[boost::vertex(vIndex, *graph_)];
535  boost::remove_vertex(boost::vertex(vIndex, *graph_), *graph_);
536 
537  return true;
538 }
539 
540 bool ompl::base::PlannerData::removeEdge (unsigned int v1, unsigned int v2)
541 {
542  Graph::Edge e;
543  bool exists;
544  boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
545 
546  if (!exists)
547  return false;
548 
549  // Freeing memory associated with this edge
550  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
551  delete edges[e];
552 
553  boost::remove_edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
554  return true;
555 }
556 
558 {
559  unsigned int index1, index2;
560  index1 = vertexIndex(v1);
561  index2 = vertexIndex(v2);
562 
563  if (index1 == INVALID_INDEX || index2 == INVALID_INDEX)
564  return false;
565 
566  return removeEdge (index1, index2);
567 }
568 
570 {
571  std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
572  if (it != stateIndexMap_.end())
573  {
574  getVertex(it->second).setTag(tag);
575  return true;
576  }
577  return false;
578 }
579 
581 {
582  // Find the index in the stateIndexMap_
583  std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
584  if (it != stateIndexMap_.end())
585  {
586  if (!isStartVertex(it->second))
587  {
588  startVertexIndices_.push_back(it->second);
589  // Sort the indices for quick lookup
590  std::sort(startVertexIndices_.begin(), startVertexIndices_.end());
591  }
592  return true;
593  }
594  return false;
595 }
596 
598 {
599  // Find the index in the stateIndexMap_
600  std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
601  if (it != stateIndexMap_.end())
602  {
603  if (!isGoalVertex(it->second))
604  {
605  goalVertexIndices_.push_back(it->second);
606  // Sort the indices for quick lookup
607  std::sort(startVertexIndices_.begin(), startVertexIndices_.end());
608  }
609  return true;
610  }
611  return false;
612 }
613 
615 {
616  unsigned int nv = numVertices();
617  for (unsigned int i = 0; i < nv; ++i)
618  {
619  std::map<unsigned int, const PlannerDataEdge*> nbrs;
620  getEdges(i, nbrs);
621 
622  std::map<unsigned int, const PlannerDataEdge*>::const_iterator it;
623  for (it = nbrs.begin(); it != nbrs.end(); ++it)
624  {
625  setEdgeWeight(i, it->first, opt.motionCost(getVertex(i).getState(),
626  getVertex(it->first).getState()));
627  }
628  }
629 }
630 
632 {
633  // Create a PathLengthOptimizationObjective to compute the edge
634  // weights according to state space distance
636  computeEdgeWeights(opt);
637 }
638 
639 namespace
640 {
641  // Used in minimum spanning tree
642  ompl::base::Cost project2nd (ompl::base::Cost /*unused*/, ompl::base::Cost second)
643  {
644  return second;
645  }
646 }
647 
649  const base::OptimizationObjective &opt,
650  base::PlannerData &mst) const
651 {
652  std::vector<ompl::base::PlannerData::Graph::Vertex> pred(numVertices());
653 
654  // This is how boost's minimum spanning tree is actually
655  // implemented, except it lacks the generality for specifying our
656  // own comparison function or zero/inf values.
657  //
658  // \todo Once (https://svn.boost.org/trac/boost/ticket/9368) gets
659  // into boost we can use the far more direct
660  // boost::prim_minimum_spanning_tree().
661  boost::dijkstra_shortest_paths
662  (*graph_, v,
663  boost::predecessor_map(&pred[0]).
664  distance_compare(std::bind(&base::OptimizationObjective::
665  isCostBetterThan, &opt,
666  std::placeholders::_1, std::placeholders::_2)).
667  distance_combine(&project2nd).
668  distance_inf(opt.infiniteCost()).
669  distance_zero(opt.identityCost()));
670 
671  // Adding vertices to MST
672  for (std::size_t i = 0; i < pred.size(); ++i)
673  {
674  if (isStartVertex(i))
675  mst.addStartVertex(getVertex(i));
676  else if (isGoalVertex(i))
677  mst.addGoalVertex(getVertex(i));
678  else
679  mst.addVertex(getVertex(i));
680  }
681 
682  // Adding edges to MST
683  for (std::size_t i = 0; i < pred.size(); ++i)
684  {
685  if (pred[i] != i)
686  {
687  Cost c;
688  getEdgeWeight(pred[i], i, &c);
689  mst.addEdge(pred[i], i, getEdge(pred[i], i), c);
690  }
691  }
692 }
693 
695 {
696  // If this vertex already exists in data, return
697  if (data.vertexExists(getVertex(v)))
698  return;
699 
700  // Adding the vertex corresponding to v into data
701  unsigned int idx;
702  if (isStartVertex(v))
703  idx = data.addStartVertex(getVertex(v));
704  else if (isGoalVertex(v))
705  idx = data.addGoalVertex(getVertex(v));
706  else
707  idx = data.addVertex(getVertex(v));
708 
709  assert (idx != INVALID_INDEX);
710 
711  std::map<unsigned int, const PlannerDataEdge*> neighbors;
712  getEdges(v, neighbors);
713 
714  // Depth-first traversal of reachable graph
715  std::map<unsigned int, const PlannerDataEdge*>::iterator it;
716  for (it = neighbors.begin(); it != neighbors.end(); ++it)
717  {
718  extractReachable(it->first, data);
719  Cost weight;
720  getEdgeWeight(v, it->first, &weight);
721  data.addEdge(idx, data.vertexIndex(getVertex(it->first)), *(it->second), weight);
722  }
723 }
724 
725 ompl::base::StateStoragePtr ompl::base::PlannerData::extractStateStorage() const
726 {
727  GraphStateStorage *store = new GraphStateStorage(si_->getStateSpace());
728  if (graph_)
729  {
730  // copy the states
731  std::map<unsigned int, unsigned int> indexMap;
732  for (std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.begin() ; it != stateIndexMap_.end() ; ++it)
733  {
734  indexMap[it->second] = store->size();
735  store->addState(it->first);
736  }
737 
738  // add the edges
739  for (std::map<unsigned int, unsigned int>::const_iterator it = indexMap.begin() ; it != indexMap.end() ; ++it)
740  {
741  std::vector<unsigned int> edgeList;
742  getEdges(it->first, edgeList);
743  GraphStateStorage::MetadataType &md = store->getMetadata(it->second);
744  md.resize(edgeList.size());
745  // map node indices to index values in StateStorage
746  for (std::size_t k = 0 ; k < edgeList.size() ; ++k)
747  md[k] = indexMap[edgeList[k]];
748  }
749  }
750  return StateStoragePtr(store);
751 }
752 
754 {
755  ompl::base::PlannerData::Graph *boostgraph = reinterpret_cast<ompl::base::PlannerData::Graph*>(graphRaw_);
756  return *boostgraph;
757 }
758 
760 {
761  const ompl::base::PlannerData::Graph *boostgraph = reinterpret_cast<const ompl::base::PlannerData::Graph*>(graphRaw_);
762  return *boostgraph;
763 }
764 
766 {
767  return si_;
768 }
769 
770 void ompl::base::PlannerData::freeMemory()
771 {
772  // Freeing decoupled states, if any
773  for (std::set<State*>::iterator it = decoupledStates_.begin(); it != decoupledStates_.end(); ++it)
774  si_->freeState(*it);
775 
776  if (graph_)
777  {
778  std::pair<Graph::EIterator, Graph::EIterator> eiterators = boost::edges(*graph_);
779  boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
780  for (Graph::EIterator iter = eiterators.first; iter != eiterators.second; ++iter)
781  delete boost::get(edges, *iter);
782 
783  std::pair<Graph::VIterator, Graph::VIterator> viterators = boost::vertices(*graph_);
784  boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
785  for (Graph::VIterator iter = viterators.first; iter != viterators.second; ++iter)
786  delete vertices[*iter];
787 
788  graph_->clear();
789  }
790 }
791 
793 {
794  return false;
795 }
const State * state_
The state represented by this vertex.
Definition: PlannerData.h:107
SpaceInformationPtr si_
The space information instance for this data.
Definition: PlannerData.h:408
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Definition: PlannerData.h:163
void computeEdgeWeights()
Computes all edge weights using state space distance (i.e. getSpaceInformation()->distance()) ...
Wrapper class for the Boost.Graph representation of the PlannerData. This class inherits from a boost...
StateStoragePtr extractStateStorage() const
Extract a ompl::base::GraphStateStorage object from this PlannerData. Memory for states is copied (th...
std::vector< unsigned int > startVertexIndices_
A mutable listing of the vertices marked as start states. Stored in sorted order. ...
Definition: PlannerData.h:403
boost::graph_traits< Type >::edge_descriptor Edge
Boost.Graph edge descriptor.
bool vertexExists(const PlannerDataVertex &v) const
Check whether a vertex exists with the given vertex data.
virtual void decoupleFromPlanner()
Creates a deep copy of the states contained in the vertices of this PlannerData structure so that whe...
Definition: PlannerData.cpp:79
boost::graph_traits< Type >::adjacency_iterator AdjIterator
Boost.Graph adjacency iterator.
PlannerDataGraph Type
Data type for the Boost.Graph representation.
Definition of a scoped state.
Definition: ScopedState.h:56
virtual bool hasControls() const
Indicate whether any information about controls (ompl::control::Control) is stored in this instance...
unsigned int addGoalVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
boost::graph_traits< Type >::in_edge_iterator IEIterator
Boost.Graph input edge iterator.
void extractReachable(unsigned int v, PlannerData &data) const
Extracts the subset of PlannerData reachable from the vertex with index v. For tree structures...
bool markStartState(const State *st)
Mark the given state as a start vertex. If the given state does not exist in a vertex, false is returned.
Graph & toBoostGraph()
Extract a Boost.Graph object from this PlannerData.
unsigned int addVertex(const PlannerDataVertex &st)
Adds the given vertex to the graph data. The vertex index is returned. Duplicates are not added...
unsigned int numGoalVertices() const
Returns the number of goal vertices.
const PlannerDataVertex & getStartVertex(unsigned int i) const
Retrieve a reference to the ith start vertex object. If i is greater than the number of start vertice...
std::vector< unsigned int > goalVertexIndices_
A mutable listing of the vertices marked as goal states. Stored in sorted order.
Definition: PlannerData.h:405
unsigned int getStartIndex(unsigned int i) const
Returns the index of the ith start state. INVALID_INDEX is returned if i is out of range...
boost::graph_traits< Type >::edge_iterator EIterator
Boost.Graph edge iterator.
M MetadataType
the datatype of the metadata
Definition: StateStorage.h:215
bool getEdgeWeight(unsigned int v1, unsigned int v2, Cost *weight) const
Returns the weight of the edge between the given vertex indices. If there exists an edge between v1 a...
unsigned int getIncomingEdges(unsigned int v, std::vector< unsigned int > &edgeList) const
Returns a list of vertices with outgoing edges to the vertex with index v. The number of edges connec...
virtual Cost infiniteCost() const
Get a cost which is greater than all other costs in this OptimizationObjective; required for use in D...
virtual void addState(const State *state)
Add a state to the set of states maintained by this storage structure. The state is copied to interna...
Definition: StateStorage.h:226
boost::graph_traits< Type >::vertex_iterator VIterator
Boost.Graph vertex iterator.
bool setEdgeWeight(unsigned int v1, unsigned int v2, Cost weight)
Sets the weight of the edge between the given vertex indices. If an edge between v1 and v2 does not e...
virtual Cost motionCost(const State *s1, const State *s2) const =0
Get the cost that corresponds to the motion segment between s1 and s2.
unsigned int getEdges(unsigned int v, std::vector< unsigned int > &edgeList) const
Returns a list of the vertex indexes directly connected to vertex with index v (outgoing edges)...
std::set< State * > decoupledStates_
A list of states that are allocated during the decoupleFromPlanner method. These states are freed by ...
Definition: PlannerData.h:411
boost::graph_traits< Type >::out_edge_iterator OEIterator
Boost.Graph output edge iterator.
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition: PlannerData.h:59
virtual bool removeVertex(const PlannerDataVertex &st)
Removes the vertex associated with the given data. If the vertex does not exist, false is returned...
bool isGoalVertex(unsigned int index) const
Returns true if the given vertex index is marked as a goal vertex.
const PlannerDataVertex & getGoalVertex(unsigned int i) const
Retrieve a reference to the ith goal vertex object. If i is greater than the number of goal vertices...
bool tagState(const State *st, int tag)
Set the integer tag associated with the given state. If the given state does not exist in a vertex...
unsigned int numEdges() const
Retrieve the number of edges in this structure.
void printGraphML(std::ostream &out=std::cout) const
Writes a GraphML file of this structure to the given stream.
unsigned int numVertices() const
Retrieve the number of vertices in this structure.
boost::graph_traits< Type >::vertex_descriptor Vertex
Boost.Graph vertex descriptor.
StateStorageWithMetadata< std::vector< std::size_t > > GraphStateStorage
Storage of states where the metadata is a vector of indices. This is is typically used to store a gra...
Definition: StateStorage.h:279
unsigned int vertexIndex(const PlannerDataVertex &v) const
Return the index for the vertex associated with the given data. INVALID_INDEX is returned if this ver...
const M & getMetadata(unsigned int index) const
Get const access to the metadata of a state at a particular index.
Definition: StateStorage.h:246
virtual bool addEdge(unsigned int v1, unsigned int v2, const PlannerDataEdge &edge=PlannerDataEdge(), Cost weight=Cost(1.0))
Adds a directed edge between the given vertex indexes. An optional edge structure and weight can be s...
A shared pointer wrapper for ompl::base::SpaceInformation.
const PlannerDataVertex & getVertex(unsigned int index) const
Retrieve a reference to the vertex object with the given index. If this vertex does not exist...
void printGraphviz(std::ostream &out=std::cout) const
Writes a Graphviz dot file of this structure to the given stream.
An optimization objective which corresponds to optimizing path length.
virtual void clear()
Clears the entire data structure.
Definition: PlannerData.cpp:73
unsigned int addStartVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
Definition of an abstract state.
Definition: State.h:50
std::vector< double > reals() const
Return the real values corresponding to this state. If a conversion is not possible, an exception is thrown.
Definition: ScopedState.h:356
virtual ~PlannerData()
Destructor.
Definition: PlannerData.cpp:62
virtual PlannerDataEdge * clone() const
Return a clone of this object, allocated from the heap.
Definition: PlannerData.h:122
static const PlannerDataVertex NO_VERTEX
Representation for a non-existant vertex.
Definition: PlannerData.h:171
State storage that allows storing state metadata as well.
Definition: StateStorage.h:210
Abstract definition of optimization objectives.
bool edgeExists(unsigned int v1, unsigned int v2) const
Check whether an edge between vertex index v1 and index v2 exists.
static const unsigned int INVALID_INDEX
Representation of an invalid vertex index.
Definition: PlannerData.h:173
const PlannerDataEdge & getEdge(unsigned int v1, unsigned int v2) const
Retrieve a reference to the edge object connecting vertices with indexes v1 and v2. If this edge does not exist, NO_EDGE is returned.
bool markGoalState(const State *st)
Mark the given state as a goal vertex. If the given state does not exist in a vertex, false is returned.
bool isStartVertex(unsigned int index) const
Returns true if the given vertex index is marked as a start vertex.
virtual void setTag(int tag)
Set the integer tag associated with this vertex.
Definition: PlannerData.h:71
unsigned int numStartVertices() const
Returns the number of start vertices.
void extractMinimumSpanningTree(unsigned int v, const OptimizationObjective &opt, PlannerData &mst) const
Extracts the minimum spanning tree of the data rooted at the vertex with index v. The minimum spannin...
Base class for a PlannerData edge.
Definition: PlannerData.h:116
const SpaceInformationPtr & getSpaceInformation() const
Return the instance of SpaceInformation used in this PlannerData.
std::map< const State *, unsigned int > stateIndexMap_
A mapping of states to vertex indexes. For fast lookup of vertex index.
Definition: PlannerData.h:401
virtual PlannerDataVertex * clone() const
Return a clone of this object, allocated from the heap.
Definition: PlannerData.h:76
virtual const State * getState() const
Retrieve the state associated with this vertex.
Definition: PlannerData.h:73
unsigned int getGoalIndex(unsigned int i) const
Returns the index of the ith goal state. INVALID_INDEX is returned if i is out of range Indexes are v...
virtual bool removeEdge(unsigned int v1, unsigned int v2)
Removes the edge between vertex indexes v1 and v2. Success is returned.
virtual Cost identityCost() const
Get the identity cost value. The identity cost value is the cost c_i such that, for all costs c...
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition: Cost.h:47
std::size_t size() const
Return the number of stored states.
Definition: StateStorage.h:98
static const PlannerDataEdge NO_EDGE
Representation for a non-existant edge.
Definition: PlannerData.h:166
std::map< std::string, std::string > properties
Any extra properties (key-value pairs) the planner can set.
Definition: PlannerData.h:397