SPARS.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2013, Rutgers the State University of New Jersey, New Brunswick
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 Rutgers 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: Andrew Dobson */
36 
37 #include "ompl/geometric/planners/prm/SPARS.h"
38 #include "ompl/geometric/planners/prm/ConnectionStrategy.h"
39 #include "ompl/base/goals/GoalSampleableRegion.h"
40 #include "ompl/base/objectives/PathLengthOptimizationObjective.h"
41 #include "ompl/tools/config/SelfConfig.h"
42 #include "ompl/tools/config/MagicConstants.h"
43 #include <functional>
44 #include <thread>
45 #include <boost/graph/astar_search.hpp>
46 #include <boost/graph/incremental_components.hpp>
47 #include <boost/property_map/vector_property_map.hpp>
48 #include <boost/foreach.hpp>
49 
50 #include "GoalVisitor.hpp"
51 
52 #define foreach BOOST_FOREACH
53 #define foreach_reverse BOOST_REVERSE_FOREACH
54 
56  base::Planner(si, "SPARS"),
57  geomPath_(si),
58  stateProperty_(boost::get(vertex_state_t(), g_)),
59  sparseStateProperty_(boost::get(vertex_state_t(), s_)),
60  sparseColorProperty_(boost::get(vertex_color_t(), s_)),
61  representativesProperty_(boost::get(vertex_representative_t(), g_)),
62  nonInterfaceListsProperty_(boost::get(vertex_list_t(), s_)),
63  interfaceListsProperty_(boost::get(vertex_interface_list_t(), s_)),
64  weightProperty_(boost::get(boost::edge_weight, g_)),
65  sparseDJSets_(boost::get(boost::vertex_rank, s_),
66  boost::get(boost::vertex_predecessor, s_)),
67  consecutiveFailures_(0),
68  stretchFactor_(3.),
69  maxFailures_(1000),
70  addedSolution_(false),
71  denseDeltaFraction_(.001),
72  sparseDeltaFraction_(.25),
73  denseDelta_(0.),
74  sparseDelta_(0.),
75  iterations_(0),
76  bestCost_(std::numeric_limits<double>::quiet_NaN())
77 {
80  specs_.optimizingPaths = true;
81  specs_.multithreaded = true;
82 
83  psimp_.reset(new PathSimplifier(si_));
84  psimp_->freeStates(false);
85 
86  Planner::declareParam<double>("stretch_factor", this, &SPARS::setStretchFactor, &SPARS::getStretchFactor, "1.1:0.1:3.0");
87  Planner::declareParam<double>("sparse_delta_fraction", this, &SPARS::setSparseDeltaFraction, &SPARS::getSparseDeltaFraction, "0.0:0.01:1.0");
88  Planner::declareParam<double>("dense_delta_fraction", this, &SPARS::setDenseDeltaFraction, &SPARS::getDenseDeltaFraction, "0.0:0.0001:0.1");
89  Planner::declareParam<unsigned int>("max_failures", this, &SPARS::setMaxFailures, &SPARS::getMaxFailures, "100:10:3000");
90 
91  addPlannerProgressProperty("iterations INTEGER",
92  std::bind(&SPARS::getIterationCount, this));
93  addPlannerProgressProperty("best cost REAL",
94  std::bind(&SPARS::getBestCost, this));
95 }
96 
98 {
99  freeMemory();
100 }
101 
103 {
104  Planner::setup();
105  if (!nn_)
106  nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<DenseVertex>(this));
107  nn_->setDistanceFunction(std::bind(&SPARS::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
108  if (!snn_)
109  snn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<SparseVertex>(this));
110  snn_->setDistanceFunction(std::bind(&SPARS::sparseDistanceFunction, this, std::placeholders::_1, std::placeholders::_2));
111  if (!connectionStrategy_)
112  connectionStrategy_ = KStarStrategy<DenseVertex>(std::bind(&SPARS::milestoneCount, this), nn_, si_->getStateDimension());
113  double maxExt = si_->getMaximumExtent();
115  denseDelta_ = denseDeltaFraction_ * maxExt;
116 
117  // Setup optimization objective
118  //
119  // If no optimization objective was specified, then default to
120  // optimizing path length as computed by the distance() function
121  // in the state space.
122  if (pdef_)
123  {
124  if (pdef_->hasOptimizationObjective())
125  {
126  opt_ = pdef_->getOptimizationObjective();
127  if (!dynamic_cast<base::PathLengthOptimizationObjective*>(opt_.get()))
128  OMPL_WARN("%s: Asymptotic optimality has only been proven with path length optimizaton; convergence for other optimizaton objectives is not guaranteed.", getName().c_str());
129  }
130  else
132  }
133  else
134  {
135  OMPL_INFORM("%s: problem definition is not set, deferring setup completion...", getName().c_str());
136  setup_ = false;
137  }
138 }
139 
141 {
142  Planner::setProblemDefinition(pdef);
143  clearQuery();
144 }
145 
147 {
149 }
150 
152 {
153  startM_.clear();
154  goalM_.clear();
155  pis_.restart();
156 
157  // Clear past solutions if there are any
158  if (pdef_)
159  pdef_->clearSolutionPaths();
160 }
161 
163 {
164  Planner::clear();
165  sampler_.reset();
166  simpleSampler_.reset();
167  freeMemory();
168  if (nn_)
169  nn_->clear();
170  if (snn_)
171  snn_->clear();
172  clearQuery();
173  resetFailures();
174  iterations_ = 0;
175  bestCost_ = base::Cost(std::numeric_limits<double>::quiet_NaN());
176 }
177 
179 {
180  foreach (DenseVertex v, boost::vertices(g_))
181  if( stateProperty_[v] != nullptr )
182  {
183  si_->freeState(stateProperty_[v]);
184  stateProperty_[v] = nullptr;
185  }
186  foreach (SparseVertex n, boost::vertices(s_))
187  if( sparseStateProperty_[n] != nullptr )
188  {
189  si_->freeState(sparseStateProperty_[n]);
190  sparseStateProperty_[n] = nullptr;
191  }
192  s_.clear();
193  g_.clear();
194 }
195 
197 {
198  DenseVertex result = boost::graph_traits<DenseGraph>::null_vertex();
199 
200  // search for a valid state
201  bool found = false;
202  while (!found && ptc == false)
203  {
204  unsigned int attempts = 0;
205  do
206  {
207  found = sampler_->sample(workState);
208  attempts++;
209  } while (attempts < magic::FIND_VALID_STATE_ATTEMPTS_WITHOUT_TERMINATION_CHECK && !found);
210  }
211 
212  if (found)
213  result = addMilestone(si_->cloneState(workState));
214  return result;
215 }
216 
218 {
219  base::GoalSampleableRegion *goal = static_cast<base::GoalSampleableRegion*>(pdef_->getGoal().get());
220  while (!ptc && !addedSolution_)
221  {
222  // Check for any new goal states
223  if (goal->maxSampleCount() > goalM_.size())
224  {
225  const base::State *st = pis_.nextGoal();
226  if (st)
227  {
228  addMilestone(si_->cloneState(st));
229  goalM_.push_back(addGuard(si_->cloneState(st), GOAL));
230  }
231  }
232 
233  // Check for a solution
235  // Sleep for 1ms
236  if (!addedSolution_)
237  std::this_thread::sleep_for(std::chrono::milliseconds(1));
238  }
239 }
240 
241 bool ompl::geometric::SPARS::haveSolution(const std::vector<DenseVertex> &starts, const std::vector<DenseVertex> &goals, base::PathPtr &solution)
242 {
243  base::Goal *g = pdef_->getGoal().get();
244  base::Cost sol_cost(opt_->infiniteCost());
245  foreach (DenseVertex start, starts)
246  {
247  foreach (DenseVertex goal, goals)
248  {
249  // we lock because the connected components algorithm is incremental and may change disjointSets_
250  graphMutex_.lock();
251  bool same_component = sameComponent(start, goal);
252  graphMutex_.unlock();
253 
254  if (same_component && g->isStartGoalPairValid(sparseStateProperty_[goal], sparseStateProperty_[start]))
255  {
256  base::PathPtr p = constructSolution(start, goal);
257  if (p)
258  {
259  base::Cost pathCost = p->cost(opt_);
260  if (opt_->isCostBetterThan(pathCost, bestCost_))
261  bestCost_ = pathCost;
262  // Check if optimization objective is satisfied
263  if (opt_->isSatisfied(pathCost))
264  {
265  solution = p;
266  return true;
267  }
268  else if (opt_->isCostBetterThan(pathCost, sol_cost))
269  {
270  solution = p;
271  sol_cost = pathCost;
272  }
273  }
274  }
275  }
276  }
277 
278  return false;
279 }
280 
282 {
284 }
285 
287 {
289 }
290 
292 {
293  std::lock_guard<std::mutex> _(graphMutex_);
294  if (boost::num_vertices(g_) < 1)
295  {
296  sparseQueryVertex_ = boost::add_vertex(s_);
297  queryVertex_ = boost::add_vertex(g_);
299  stateProperty_[queryVertex_] = nullptr;
300  }
301 }
302 
304 {
305  return boost::same_component(m1, m2, sparseDJSets_);
306 }
307 
309 {
310  checkValidity();
312 
313  base::GoalSampleableRegion *goal = dynamic_cast<base::GoalSampleableRegion*>(pdef_->getGoal().get());
314 
315  if (!goal)
316  {
317  OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
319  }
320 
321  // Add the valid start states as milestones
322  while (const base::State *st = pis_.nextStart())
323  {
324  addMilestone(si_->cloneState(st));
325  startM_.push_back(addGuard(si_->cloneState(st), START ));
326  }
327  if (startM_.empty())
328  {
329  OMPL_ERROR("%s: There are no valid initial states!", getName().c_str());
331  }
332 
333  if (goalM_.empty() && !goal->couldSample())
334  {
335  OMPL_ERROR("%s: Insufficient states in sampleable goal region", getName().c_str());
337  }
338 
339  // Add the valid goal states as milestones
340  while (const base::State *st = (goalM_.empty() ? pis_.nextGoal(ptc) : pis_.nextGoal()))
341  {
342  addMilestone(si_->cloneState(st));
343  goalM_.push_back(addGuard(si_->cloneState(st), GOAL ));
344  }
345  if (goalM_.empty())
346  {
347  OMPL_ERROR("%s: Unable to find any valid goal states", getName().c_str());
349  }
350 
351  unsigned int nrStartStatesDense = boost::num_vertices(g_) - 1; // don't count query vertex
352  unsigned int nrStartStatesSparse = boost::num_vertices(s_) - 1; // don't count query vertex
353  OMPL_INFORM("%s: Starting planning with %u dense states, %u sparse states", getName().c_str(), nrStartStatesDense, nrStartStatesSparse);
354 
355  // Reset addedSolution_ member
356  addedSolution_ = false;
357  resetFailures();
358  base::PathPtr sol;
361  std::thread slnThread(std::bind(&SPARS::checkForSolution, this, ptcOrFail, boost::ref(sol)));
362 
363  // Construct planner termination condition which also takes maxFailures_ and addedSolution_ into account
366  constructRoadmap(ptcOrStop);
367 
368  // Ensure slnThread is ceased before exiting solve
369  slnThread.join();
370 
371  if (sol)
372  pdef_->addSolutionPath(sol, false, -1.0, getName());
373 
374  OMPL_INFORM("%s: Created %u dense states, %u sparse states", getName().c_str(),
375  (unsigned int)(boost::num_vertices(g_) - nrStartStatesDense),
376  (unsigned int)(boost::num_vertices(s_) - nrStartStatesSparse));
377 
378  // Return true if any solution was found.
380 }
381 
383 {
384  if (stopOnMaxFail)
385  {
386  resetFailures();
389  constructRoadmap(ptcOrFail);
390  }
391  else
392  constructRoadmap(ptc);
393 }
394 
396 {
398 
399  if (!isSetup())
400  setup();
401  if (!sampler_)
402  sampler_ = si_->allocValidStateSampler();
403  if (!simpleSampler_)
404  simpleSampler_ = si_->allocStateSampler();
405 
406  base::State *workState = si_->allocState();
407 
408  /* The whole neighborhood set which has been most recently computed */
409  std::vector<SparseVertex> graphNeighborhood;
410 
411  /* The visible neighborhood set which has been most recently computed */
412  std::vector<SparseVertex> visibleNeighborhood;
413 
414  /* Storage for the interface neighborhood, populated by getInterfaceNeighborhood() */
415  std::vector<DenseVertex> interfaceNeighborhood;
416 
417  bestCost_ = opt_->infiniteCost();
418  while (ptc == false)
419  {
420  iterations_++;
421 
422  // Generate a single sample, and attempt to connect it to nearest neighbors.
423  DenseVertex q = addSample(workState, ptc);
424  if (q == boost::graph_traits<DenseGraph>::null_vertex())
425  continue;
426 
427  //Now that we've added to D, try adding to S
428  //Start by figuring out who our neighbors are
429  getSparseNeighbors(workState, graphNeighborhood);
430  filterVisibleNeighbors(workState, graphNeighborhood, visibleNeighborhood);
431  //Check for addition for Coverage
432  if( !checkAddCoverage(workState, graphNeighborhood))
433  //If not for Coverage, then Connectivity
434  if( !checkAddConnectivity(workState, graphNeighborhood))
435  //Check for the existence of an interface
436  if( !checkAddInterface(graphNeighborhood, visibleNeighborhood, q))
437  {
438  // Then check to see if it's on an interface
439  getInterfaceNeighborhood(q, interfaceNeighborhood);
440  if (interfaceNeighborhood.size() > 0)
441  {
442  //Check for addition for spanner prop
443  if (!checkAddPath(q, interfaceNeighborhood))
444  //All of the tests have failed. Report failure for the sample
446  }
447  else
448  //There's no interface here, so drop it
450  }
451  }
452 
453  si_->freeState(workState);
454 }
455 
457 {
458  std::lock_guard<std::mutex> _(graphMutex_);
459 
460  DenseVertex m = boost::add_vertex(g_);
461  stateProperty_[m] = state;
462 
463  // Which milestones will we attempt to connect to?
464  const std::vector<DenseVertex>& neighbors = connectionStrategy_(m);
465 
466  foreach (DenseVertex n, neighbors)
467  if (si_->checkMotion(stateProperty_[m], stateProperty_[n]))
468  {
469  const double weight = distanceFunction(m, n);
470  const DenseGraph::edge_property_type properties(weight);
471 
472  boost::add_edge(m, n, properties, g_);
473  }
474 
475  nn_->add(m);
476 
477  //Need to update representative information here...
479 
480  std::vector<DenseVertex> interfaceNeighborhood;
481  std::set<SparseVertex> interfaceRepresentatives;
482 
483  getInterfaceNeighborRepresentatives(m, interfaceRepresentatives);
484  getInterfaceNeighborhood(m, interfaceNeighborhood);
485  addToRepresentatives(m, representativesProperty_[m], interfaceRepresentatives);
486  foreach (DenseVertex qp, interfaceNeighborhood)
487  {
489  getInterfaceNeighborRepresentatives( qp, interfaceRepresentatives );
490  addToRepresentatives( qp, representativesProperty_[qp], interfaceRepresentatives );
491  }
492 
493  return m;
494 }
495 
497 {
498  std::lock_guard<std::mutex> _(graphMutex_);
499 
500  SparseVertex v = boost::add_vertex(s_);
501  sparseStateProperty_[v] = state;
502  sparseColorProperty_[v] = type;
503 
504  sparseDJSets_.make_set(v);
505 
506  snn_->add(v);
508 
509  resetFailures();
510  return v;
511 }
512 
514 {
515  const base::Cost weight(costHeuristic(v, vp));
516  const SpannerGraph::edge_property_type properties(weight);
517  std::lock_guard<std::mutex> _(graphMutex_);
518  boost::add_edge(v, vp, properties, s_);
519  sparseDJSets_.union_set(v, vp);
520 }
521 
523 {
524  const double weight = distanceFunction(v, vp);
525  const DenseGraph::edge_property_type properties(weight);
526  std::lock_guard<std::mutex> _(graphMutex_);
527  boost::add_edge(v, vp, properties, g_);
528 }
529 
530 bool ompl::geometric::SPARS::checkAddCoverage(const base::State *lastState, const std::vector<SparseVertex>& neigh )
531 {
532  //For each of these neighbors,
533  foreach (SparseVertex n, neigh)
534  //If path between is free
535  if (si_->checkMotion( lastState, sparseStateProperty_[n]))
536  //Abort out and return false
537  return false;
538  //No free paths means we add for coverage
539  addGuard(si_->cloneState(lastState), COVERAGE);
540  return true;
541 }
542 
543 bool ompl::geometric::SPARS::checkAddConnectivity( const base::State *lastState, const std::vector<SparseVertex>& neigh )
544 {
545  std::vector< SparseVertex > links;
546  //For each neighbor
547  for (std::size_t i = 0; i < neigh.size(); ++i )
548  //For each other neighbor
549  for (std::size_t j = i + 1; j < neigh.size(); ++j )
550  //If they are in different components
551  if (!sameComponent(neigh[i], neigh[j]))
552  //If the paths between are collision free
553  if( si_->checkMotion( lastState, sparseStateProperty_[neigh[i]] ) && si_->checkMotion( lastState, sparseStateProperty_[neigh[j]] ) )
554  {
555  links.push_back( neigh[i] );
556  links.push_back( neigh[j] );
557  }
558 
559  if( links.size() != 0 )
560  {
561  //Add the node
562  SparseVertex g = addGuard( si_->cloneState(lastState), CONNECTIVITY );
563 
564  for (std::size_t i = 0; i < links.size(); ++i )
565  //If there's no edge
566  if (!boost::edge(g, links[i], s_).second)
567  //And the components haven't been united by previous links
568  if (!sameComponent(links[i], g))
569  connectSparsePoints( g, links[i] );
570  return true;
571  }
572  return false;
573 }
574 
575 bool ompl::geometric::SPARS::checkAddInterface(const std::vector<SparseVertex>& graphNeighborhood, const std::vector<SparseVertex>& visibleNeighborhood, DenseVertex q )
576 {
577  //If we have more than 1 neighbor
578  if( visibleNeighborhood.size() > 1 )
579  //If our closest neighbors are also visible
580  if( graphNeighborhood[0] == visibleNeighborhood[0] && graphNeighborhood[1] == visibleNeighborhood[1] )
581  //If our two closest neighbors don't share an edge
582  if (!boost::edge(visibleNeighborhood[0], visibleNeighborhood[1], s_).second)
583  {
584  //If they can be directly connected
585  if( si_->checkMotion( sparseStateProperty_[visibleNeighborhood[0]], sparseStateProperty_[visibleNeighborhood[1]] ) )
586  {
587  //Connect them
588  connectSparsePoints( visibleNeighborhood[0], visibleNeighborhood[1] );
589  //And report that we added to the roadmap
590  resetFailures();
591  //Report success
592  return true;
593  }
594  else
595  {
596  //Add the new node to the graph, to bridge the interface
597  SparseVertex v = addGuard( si_->cloneState( stateProperty_[q] ), INTERFACE );
598  connectSparsePoints( v, visibleNeighborhood[0] );
599  connectSparsePoints( v, visibleNeighborhood[1] );
600  //Report success
601  return true;
602  }
603  }
604  return false;
605 }
606 
607 bool ompl::geometric::SPARS::checkAddPath(DenseVertex q, const std::vector<DenseVertex>& neigh)
608 {
609  bool result = false;
610 
611  //Get q's representative => v
613 
614  //Extract the representatives of neigh => n_rep
615  std::set<SparseVertex> n_rep;
616  foreach( DenseVertex qp, neigh )
617  n_rep.insert(representativesProperty_[qp]);
618 
619  std::vector<SparseVertex> Xs;
620  //for each v' in n_rep
621  for (std::set<SparseVertex>::iterator it = n_rep.begin() ; it != n_rep.end() && !result ; ++it)
622  {
623  SparseVertex vp = *it;
624  //Identify appropriate v" candidates => vpps
625  std::vector<SparseVertex> VPPs;
626  computeVPP(v, vp, VPPs);
627 
628  foreach( SparseVertex vpp, VPPs )
629  {
630  double s_max = 0;
631  //Find the X nodes to test
632  computeX(v, vp, vpp, Xs);
633 
634  //For each x in xs
635  foreach( SparseVertex x, Xs )
636  {
637  //Compute/Retain MAXimum distance path thorugh S
638  double dist = (si_->distance(sparseStateProperty_[x], sparseStateProperty_[v])
639  + si_->distance(sparseStateProperty_[v], sparseStateProperty_[vp])) / 2.0;
640  if( dist > s_max )
641  s_max = dist;
642  }
643 
644  DensePath bestDPath;
645  DenseVertex best_qpp = boost::graph_traits<DenseGraph>::null_vertex();
646  double d_min = std::numeric_limits<double>::infinity(); //Insanely big number
647  //For each vpp in vpps
648  for (std::size_t j = 0; j < VPPs.size() && !result; ++j)
649  {
650  SparseVertex vpp = VPPs[j];
651  //For each q", which are stored interface nodes on v for i(vpp,v)
652  foreach( DenseVertex qpp, interfaceListsProperty_[v][vpp] )
653  {
654  // check that representatives are consistent
655  assert(representativesProperty_[qpp] == v);
656 
657  //If they happen to be the one and same node
658  if (q == qpp)
659  {
660  bestDPath.push_front( stateProperty_[q] );
661  best_qpp = qpp;
662  d_min = 0;
663  }
664  else
665  {
666  //Compute/Retain MINimum distance path on D through q, q"
667  DensePath dPath;
668  computeDensePath(q, qpp, dPath);
669  if (dPath.size() > 0)
670  {
671  // compute path length
672  double length = 0.0;
673  DensePath::const_iterator jt = dPath.begin();
674  for (DensePath::const_iterator it = jt + 1 ; it != dPath.end() ; ++it)
675  {
676  length += si_->distance(*jt, *it);
677  jt = it;
678  }
679 
680  if (length < d_min)
681  {
682  d_min = length;
683  bestDPath.swap(dPath);
684  best_qpp = qpp;
685  }
686  }
687  }
688  }
689 
690  //If the spanner property is violated for these paths
691  if (s_max > stretchFactor_* d_min)
692  {
693  //Need to augment this path with the appropriate neighbor information
694  DenseVertex na = getInterfaceNeighbor(q, vp);
695  DenseVertex nb = getInterfaceNeighbor(best_qpp, vpp);
696 
697  bestDPath.push_front( stateProperty_[na] );
698  bestDPath.push_back( stateProperty_[nb] );
699 
700  // check consistency of representatives
701  assert(representativesProperty_[na] == vp && representativesProperty_[nb] == vpp);
702 
703  //Add the dense path to the spanner
704  addPathToSpanner( bestDPath, vpp, vp );
705 
706  //Report success
707  result = true;
708  }
709  }
710  }
711  }
712  return result;
713 }
714 
716 {
717  double degree = 0.0;
718  foreach (DenseVertex v, boost::vertices(s_))
719  degree += (double)boost::out_degree(v, s_);
720  degree /= (double)boost::num_vertices(s_);
721  return degree;
722 }
723 
724 void ompl::geometric::SPARS::printDebug(std::ostream &out) const
725 {
726  out << "SPARS Debug Output: " << std::endl;
727  out << " Settings: " << std::endl;
728  out << " Max Failures: " << getMaxFailures() << std::endl;
729  out << " Dense Delta Fraction: " << getDenseDeltaFraction() << std::endl;
730  out << " Sparse Delta Fraction: " << getSparseDeltaFraction() << std::endl;
731  out << " Stretch Factor: " << getStretchFactor() << std::endl;
732  out << " Status: " << std::endl;
733  out << " Milestone Count: " << milestoneCount() << std::endl;
734  out << " Guard Count: " << guardCount() << std::endl;
735  out << " Iterations: " << getIterationCount() << std::endl;
736  out << " Average Valence: " << averageValence() << std::endl;
737  out << " Consecutive Failures: " << consecutiveFailures_ << std::endl;
738 }
739 
740 void ompl::geometric::SPARS::getSparseNeighbors(base::State *inState, std::vector<SparseVertex> &graphNeighborhood)
741 {
743 
744  graphNeighborhood.clear();
745  snn_->nearestR(sparseQueryVertex_, sparseDelta_, graphNeighborhood);
746 
748 }
749 
750 void ompl::geometric::SPARS::filterVisibleNeighbors(base::State *inState, const std::vector<SparseVertex> &graphNeighborhood,
751  std::vector<SparseVertex> &visibleNeighborhood) const
752 {
753  visibleNeighborhood.clear();
754  //Now that we got the neighbors from the NN, we must remove any we can't see
755  for (std::size_t i = 0; i < graphNeighborhood.size(); ++i)
756  if (si_->checkMotion(inState, sparseStateProperty_[graphNeighborhood[i]]))
757  visibleNeighborhood.push_back(graphNeighborhood[i]);
758 }
759 
761 {
762  foreach (DenseVertex vp, boost::adjacent_vertices( q, g_ ))
763  if (representativesProperty_[vp] == rep )
764  if (distanceFunction( q, vp ) <= denseDelta_)
765  return vp;
766  throw Exception(name_, "Vertex has no interface neighbor with given representative");
767 }
768 
770 {
771  // First, check to see that the path has length
772  if (dense_path.size() <= 1)
773  {
774  // The path is 0 length, so simply link the representatives
775  connectSparsePoints( vp, vpp );
776  resetFailures();
777  }
778  else
779  {
780  //We will need to construct a PathGeometric to do this.
781  geomPath_.getStates().resize( dense_path.size() );
782  std::copy( dense_path.begin(), dense_path.end(), geomPath_.getStates().begin() );
783 
784  //Attempt to simplify the path
785  psimp_->reduceVertices( geomPath_, geomPath_.getStateCount() * 2);
786 
787  // we are sure there are at least 2 points left on geomPath_
788 
789  std::vector< SparseVertex > added_nodes;
790  added_nodes.reserve(geomPath_.getStateCount());
791  for (std::size_t i = 0; i < geomPath_.getStateCount(); ++i )
792  {
793  //Add each guard
794  SparseVertex ng = addGuard( si_->cloneState(geomPath_.getState(i)), QUALITY );
795  added_nodes.push_back( ng );
796  }
797  //Link them up
798  for (std::size_t i = 1; i < added_nodes.size() ; ++i )
799  {
800  connectSparsePoints(added_nodes[i - 1], added_nodes[i]);
801  }
802  //Don't forget to link them to their representatives
803  connectSparsePoints( added_nodes[0], vp );
804  connectSparsePoints( added_nodes[added_nodes.size()-1], vpp );
805  }
806  geomPath_.getStates().clear();
807  return true;
808 }
809 
811 {
812  //Get all of the dense samples which may be affected by adding this node
813  std::vector< DenseVertex > dense_points;
814 
816 
817  nn_->nearestR( queryVertex_, sparseDelta_ + denseDelta_, dense_points );
818 
819  stateProperty_[ queryVertex_ ] = nullptr;
820 
821  //For each of those points
822  for (std::size_t i = 0 ; i < dense_points.size() ; ++i)
823  {
824  //Remove that point from the old representative's list(s)
825  removeFromRepresentatives( dense_points[i], representativesProperty_[dense_points[i]] );
826  //Update that point's representative
827  calculateRepresentative( dense_points[i] );
828  }
829 
830  std::set<SparseVertex> interfaceRepresentatives;
831  //For each of the points
832  for (std::size_t i = 0 ; i < dense_points.size(); ++i)
833  {
834  //Get it's representative
835  SparseVertex rep = representativesProperty_[dense_points[i]];
836  //Extract the representatives of any interface-sharing neighbors
837  getInterfaceNeighborRepresentatives( dense_points[i], interfaceRepresentatives );
838  //For sanity's sake, make sure we clear ourselves out of what this new rep might think of us
839  removeFromRepresentatives( dense_points[i], rep );
840  //Add this vertex to it's representative's list for the other representatives
841  addToRepresentatives( dense_points[i], rep, interfaceRepresentatives );
842  }
843 }
844 
846 {
847  //Get the nearest neighbors within sparseDelta_
848  std::vector<SparseVertex> graphNeighborhood;
849  getSparseNeighbors(stateProperty_[q], graphNeighborhood);
850 
851  //For each neighbor
852  for (std::size_t i = 0; i < graphNeighborhood.size(); ++i)
853  if (si_->checkMotion(stateProperty_[q], sparseStateProperty_[graphNeighborhood[i]]))
854  {
855  //update the representative
856  representativesProperty_[q] = graphNeighborhood[i];
857  //abort
858  break;
859  }
860 }
861 
862 void ompl::geometric::SPARS::addToRepresentatives(DenseVertex q, SparseVertex rep, const std::set<SparseVertex> &oreps)
863 {
864  //If this node supports no interfaces
865  if (oreps.size() == 0)
866  {
867  //Add it to the pool of non-interface nodes
868  bool new_insert = nonInterfaceListsProperty_[rep].insert(q).second;
869 
870  // we expect this was not previously tracked
871  if (!new_insert)
872  assert(false);
873  }
874  else
875  {
876  //otherwise, for every neighbor representative
877  foreach( SparseVertex v, oreps )
878  {
879  assert(rep == representativesProperty_[q]);
880  bool new_insert = interfaceListsProperty_[rep][v].insert(q).second;
881  if (!new_insert)
882  assert(false);
883  }
884  }
885 }
886 
888 {
889  // Remove the node from the non-interface points (if there)
890  nonInterfaceListsProperty_[rep].erase(q);
891 
892  // From each of the interfaces
893  foreach (SparseVertex vpp, interfaceListsProperty_[rep] | boost::adaptors::map_keys)
894  {
895  // Remove this node from that list
896  interfaceListsProperty_[rep][vpp].erase( q );
897  }
898 }
899 
900 void ompl::geometric::SPARS::computeVPP(SparseVertex v, SparseVertex vp, std::vector<SparseVertex> &VPPs)
901 {
902  foreach( SparseVertex cvpp, boost::adjacent_vertices( v, s_ ) )
903  if( cvpp != vp )
904  if( !boost::edge( cvpp, vp, s_ ).second )
905  VPPs.push_back( cvpp );
906 }
907 
908 void ompl::geometric::SPARS::computeX(SparseVertex v, SparseVertex vp, SparseVertex vpp, std::vector<SparseVertex> &Xs)
909 {
910  Xs.clear();
911  foreach( SparseVertex cx, boost::adjacent_vertices( vpp, s_ ) )
912  if( boost::edge( cx, v, s_ ).second && !boost::edge( cx, vp, s_ ).second )
913  if (interfaceListsProperty_[vpp][cx].size() > 0)
914  Xs.push_back( cx );
915  Xs.push_back( vpp );
916 }
917 
918 void ompl::geometric::SPARS::getInterfaceNeighborRepresentatives(DenseVertex q, std::set<SparseVertex> &interfaceRepresentatives)
919 {
920  interfaceRepresentatives.clear();
921 
922  // Get our representative
924  // For each neighbor we are connected to
925  foreach( DenseVertex n, boost::adjacent_vertices( q, g_ ) )
926  {
927  // Get his representative
929  // If that representative is not our own
930  if (orep != rep)
931  // If he is within denseDelta_
932  if (distanceFunction( q, n ) < denseDelta_)
933  // Include his rep in the set
934  interfaceRepresentatives.insert(orep);
935  }
936 }
937 
938 void ompl::geometric::SPARS::getInterfaceNeighborhood(DenseVertex q, std::vector<DenseVertex> &interfaceNeighborhood)
939 {
940  interfaceNeighborhood.clear();
941 
942  // Get our representative
944 
945  // For each neighbor we are connected to
946  foreach( DenseVertex n, boost::adjacent_vertices( q, g_ ) )
947  // If neighbor representative is not our own
948  if( representativesProperty_[n] != rep )
949  // If he is within denseDelta_
950  if( distanceFunction( q, n ) < denseDelta_ )
951  // Append him to the list
952  interfaceNeighborhood.push_back( n );
953 }
954 
956 {
957  std::lock_guard<std::mutex> _(graphMutex_);
958 
959  boost::vector_property_map<SparseVertex> prev(boost::num_vertices(s_));
960 
961  try
962  {
963  // Consider using a persistent distance_map if it's slow
964  boost::astar_search(s_, start,
965  std::bind(&SPARS::costHeuristic, this, std::placeholders::_1, goal),
966  boost::predecessor_map(prev).
967  distance_compare(std::bind(&base::OptimizationObjective::
968  isCostBetterThan, opt_.get(), std::placeholders::_1, std::placeholders::_2)).
969  distance_combine(std::bind(&base::OptimizationObjective::
970  combineCosts, opt_.get(), std::placeholders::_1, std::placeholders::_2)).
971  distance_inf(opt_->infiniteCost()).
972  distance_zero(opt_->identityCost()).
973  visitor(AStarGoalVisitor<SparseVertex>(goal)));
974  }
975  catch (AStarFoundGoal&)
976  {
977  }
978 
979  if (prev[goal] == goal)
980  throw Exception(name_, "Could not find solution path");
981  else
982  {
983  PathGeometric *p = new PathGeometric(si_);
984 
985  for (SparseVertex pos = goal; prev[pos] != pos; pos = prev[pos])
986  p->append(sparseStateProperty_[pos]);
987  p->append(sparseStateProperty_[start]);
988  p->reverse();
989 
990  return base::PathPtr(p);
991  }
992 }
993 
995 {
996  path.clear();
997 
998  boost::vector_property_map<DenseVertex> prev(boost::num_vertices(g_));
999 
1000  try
1001  {
1002  boost::astar_search(g_, start,
1003  std::bind(&SPARS::distanceFunction, this, std::placeholders::_1, goal),
1004  boost::predecessor_map(prev).
1005  visitor(AStarGoalVisitor<DenseVertex>(goal)));
1006  }
1007  catch (AStarFoundGoal&)
1008  {
1009  }
1010 
1011  if (prev[goal] == goal)
1012  OMPL_WARN("%s: No dense path was found?", getName().c_str());
1013  else
1014  {
1015  for (DenseVertex pos = goal; prev[pos] != pos; pos = prev[pos])
1016  path.push_front( stateProperty_[pos] );
1017  path.push_front( stateProperty_[start] );
1018  }
1019 }
1020 
1022 {
1023  Planner::getPlannerData(data);
1024 
1025  // Explicitly add start and goal states:
1026  for (std::size_t i = 0; i < startM_.size(); ++i)
1028 
1029  for (std::size_t i = 0; i < goalM_.size(); ++i)
1031 
1032  // Adding edges and all other vertices simultaneously
1033  foreach (const SparseEdge e, boost::edges(s_))
1034  {
1035  const SparseVertex v1 = boost::source(e, s_);
1036  const SparseVertex v2 = boost::target(e, s_);
1039 
1040  // Add the reverse edge, since we're constructing an undirected roadmap
1043  }
1044 
1045  // Make sure to add edge-less nodes as well
1046  foreach (const SparseVertex n, boost::vertices(s_))
1047  if (boost::out_degree( n, s_ ) == 0)
1049 }
1050 
1052 {
1053  return opt_->motionCostHeuristic(stateProperty_[u], stateProperty_[v]);
1054 }
double stretchFactor_
The stretch factor in terms of graph spanners for SPARS to check against.
Definition: SPARS.h:535
bool approximateSolutions
Flag indicating whether the planner is able to compute approximate solutions.
Definition: Planner.h:212
void freeMemory()
Free all the memory allocated by the planner.
Definition: SPARS.cpp:178
virtual void clear()
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
Definition: SPARS.cpp:162
void addPlannerProgressProperty(const std::string &progressPropertyName, const PlannerProgressProperty &prop)
Add a planner progress property called progressPropertyName with a property querying function prop to...
Definition: Planner.h:392
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Definition: PlannerData.h:163
base::StateSamplerPtr simpleSampler_
Sampler user for generating random in the state space.
Definition: SPARS.h:469
void clearQuery()
Clear the query previously loaded from the ProblemDefinition. Subsequent calls to solve() will reuse ...
Definition: SPARS.cpp:151
PlannerTerminationCondition plannerOrTerminationCondition(const PlannerTerminationCondition &c1, const PlannerTerminationCondition &c2)
Combine two termination conditions into one. If either termination condition returns true...
SPARS(const base::SpaceInformationPtr &si)
Constructor.
Definition: SPARS.cpp:55
base::ValidStateSamplerPtr sampler_
Sampler user for generating valid samples in the state space.
Definition: SPARS.h:466
A shared pointer wrapper for ompl::base::ProblemDefinition.
PathSimplifierPtr psimp_
A path simplifier used to simplify dense paths added to S.
Definition: SPARS.h:517
The planner failed to find a solution.
Definition: PlannerStatus.h:62
virtual void setup()
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
Definition: SPARS.cpp:102
long unsigned int iterations_
A counter for the number of iterations of the algorithm.
Definition: SPARS.h:570
GoalType recognizedGoal
The type of goal specification the planner can use.
Definition: Planner.h:206
boost::property_map< SpannerGraph, vertex_interface_list_t >::type interfaceListsProperty_
Access to the interface-supporting vertice hashes of the sparse nodes.
Definition: SPARS.h:514
DenseVertex getInterfaceNeighbor(DenseVertex q, SparseVertex rep)
Get the first neighbor of q who has representative rep and is within denseDelta_. ...
Definition: SPARS.cpp:760
const State * nextGoal(const PlannerTerminationCondition &ptc)
Return the next valid goal state or nullptr if no more valid goal states are available. Because sampling of goal states may also produce invalid goals, this function takes an argument that specifies whether a termination condition has been reached. If the termination condition evaluates to true the function terminates even if no valid goal has been found.
Definition: Planner.cpp:271
double denseDeltaFraction_
SPARS parameter for dense graph connection distance as a fraction of max. extent. ...
Definition: SPARS.h:544
virtual ~SPARS()
Destructor.
Definition: SPARS.cpp:97
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...
virtual base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
Function that can solve the motion planning problem. This function can be called multiple times on th...
Definition: SPARS.cpp:308
Abstract definition of goals.
Definition: Goal.h:62
void setDenseDeltaFraction(double d)
Set the delta fraction for interface detection. If two nodes in the dense graph are more than a delta...
Definition: SPARS.h:264
double sparseDelta_
SPARS parameter for Sparse Roadmap connection distance.
Definition: SPARS.h:553
std::function< const std::vector< DenseVertex > &(const DenseVertex)> connectionStrategy_
Function that returns the milestones to attempt connections with.
Definition: SPARS.h:529
virtual void getPlannerData(base::PlannerData &data) const
Get information about the current run of the motion planner. Repeated calls to this function will upd...
Definition: SPARS.cpp:1021
double distanceFunction(const DenseVertex a, const DenseVertex b) const
Compute distance between two milestones (this is simply distance between the states of the milestones...
Definition: SPARS.h:454
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
bool checkAddPath(DenseVertex q, const std::vector< DenseVertex > &neigh)
Checks for adding an entire dense path to the Sparse Roadmap.
Definition: SPARS.cpp:607
boost::graph_traits< SpannerGraph >::edge_descriptor SparseEdge
An edge in the sparse roadmap that is constructed.
Definition: SPARS.h:150
STL namespace.
unsigned int addVertex(const PlannerDataVertex &st)
Adds the given vertex to the graph data. The vertex index is returned. Duplicates are not added...
void removeFromRepresentatives(DenseVertex q, SparseVertex rep)
Removes the node from its representative&#39;s lists.
Definition: SPARS.cpp:887
void getInterfaceNeighborRepresentatives(DenseVertex q, std::set< SparseVertex > &interfaceRepresentatives)
Gets the representatives of all interfaces that q supports.
Definition: SPARS.cpp:918
bool reachedTerminationCriterion() const
Returns true if we have reached the iteration failures limit, maxFailures_ or if a solution was added...
Definition: SPARS.cpp:281
SparseNeighbors snn_
Nearest Neighbors structure for the sparse roadmap.
Definition: SPARS.h:475
void append(const base::State *state)
Append state to the end of this path. The memory for state is copied.
void constructRoadmap(const base::PlannerTerminationCondition &ptc)
While the termination condition permits, construct the spanner graph.
Definition: SPARS.cpp:395
void printDebug(std::ostream &out=std::cout) const
Print debug information about planner.
Definition: SPARS.cpp:724
ProblemDefinitionPtr pdef_
The user set problem definition.
Definition: Planner.h:401
bool multithreaded
Flag indicating whether multiple threads are used in the computation of the planner.
Definition: Planner.h:209
base::State * getState(unsigned int index)
Get the state located at index along the path.
void computeVPP(DenseVertex v, DenseVertex vp, std::vector< SparseVertex > &VPPs)
Computes all nodes which qualify as a candidate v" for v and vp.
Definition: SPARS.cpp:900
unsigned int maxFailures_
The maximum number of failures before terminating the algorithm.
Definition: SPARS.h:538
unsigned int milestoneCount() const
Returns the number of milestones added to D.
Definition: SPARS.h:330
std::size_t getStateCount() const
Get the number of states (way-points) that make up this path.
base::Cost costHeuristic(SparseVertex u, SparseVertex v) const
Given two vertices, returns a heuristic on the cost of the path connecting them. This method wraps Op...
Definition: SPARS.cpp:1051
boost::property_map< SpannerGraph, vertex_list_t >::type nonInterfaceListsProperty_
Access to all non-interface supporting vertices of the sparse nodes.
Definition: SPARS.h:511
bool checkAddCoverage(const base::State *lastState, const std::vector< SparseVertex > &neigh)
Checks the latest dense sample for the coverage property, and adds appropriately. ...
Definition: SPARS.cpp:530
void setMaxFailures(unsigned int m)
Set the maximum consecutive failures to augment the spanner before termination. In general...
Definition: SPARS.h:256
double getSparseDeltaFraction() const
Retrieve the sparse graph visibility range delta fraction.
Definition: SPARS.h:303
void calculateRepresentative(DenseVertex q)
Calculates the representative for a dense sample.
Definition: SPARS.cpp:845
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition: PlannerData.h:59
void updateRepresentatives(SparseVertex v)
Automatically updates the representatives of all dense samplse within sparseDelta_ of v...
Definition: SPARS.cpp:810
void setStretchFactor(double t)
Set the roadmap spanner stretch factor. This value represents a multiplicative upper bound on path qu...
Definition: SPARS.h:285
Invalid start state or no start state specified.
Definition: PlannerStatus.h:56
void addToRepresentatives(DenseVertex q, SparseVertex rep, const std::set< SparseVertex > &oreps)
Adds a dense sample to the appropriate lists of its representative.
Definition: SPARS.cpp:862
bool setup_
Flag indicating whether setup() has been called.
Definition: Planner.h:419
double getStretchFactor() const
Retrieve the spanner&#39;s set stretch factor.
Definition: SPARS.h:309
Abstract definition of a goal region that can be sampled.
double getDenseDeltaFraction() const
Retrieve the dense graph interface support delta fraction.
Definition: SPARS.h:297
DenseVertex addMilestone(base::State *state)
Construct a milestone for a given state (state) and store it in the nearest neighbors data structure...
Definition: SPARS.cpp:456
virtual unsigned int maxSampleCount() const =0
Return the maximum number of samples that can be asked for before repeating.
std::vector< SparseVertex > goalM_
Array of goal guards.
Definition: SPARS.h:487
void getInterfaceNeighborhood(DenseVertex q, std::vector< DenseVertex > &interfaceNeighborhood)
Gets the neighbors of q who help it support an interface.
Definition: SPARS.cpp:938
boost::graph_traits< SpannerGraph >::vertex_descriptor SparseVertex
A vertex in the sparse roadmap that is constructed.
Definition: SPARS.h:147
boost::disjoint_sets< boost::property_map< SpannerGraph, boost::vertex_rank_t >::type, boost::property_map< SpannerGraph, boost::vertex_predecessor_t >::type > sparseDJSets_
Data structure that maintains the connected components of S.
Definition: SPARS.h:526
The goal is of a type that a planner does not recognize.
Definition: PlannerStatus.h:60
boost::property_map< DenseGraph, vertex_state_t >::type stateProperty_
Access to the internal base::state at each DenseVertex.
Definition: SPARS.h:499
boost::property_map< SpannerGraph, vertex_state_t >::type sparseStateProperty_
Access to the internal base::State for each SparseVertex of S.
Definition: SPARS.h:502
std::vector< base::State * > & getStates()
Get the states that make up the path (as a reference, so it can be modified, hence the function is no...
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
void connectDensePoints(DenseVertex v, DenseVertex vp)
Connects points in the dense graph.
Definition: SPARS.cpp:522
boost::graph_traits< DenseGraph >::vertex_descriptor DenseVertex
A vertex in DenseGraph.
Definition: SPARS.h:180
double sparseDeltaFraction_
SPARS parameter for Sparse Roadmap connection distance as a fraction of max. extent.
Definition: SPARS.h:547
void computeDensePath(const DenseVertex start, const DenseVertex goal, DensePath &path) const
Constructs the dense path between the start and goal vertices (if connected)
Definition: SPARS.cpp:994
The planner found an exact solution.
Definition: PlannerStatus.h:66
base::Cost bestCost_
Best cost found so far by algorithm.
Definition: SPARS.h:572
void filterVisibleNeighbors(base::State *inState, const std::vector< SparseVertex > &graphNeighborhood, std::vector< SparseVertex > &visibleNeighborhood) const
Get the visible neighbors.
Definition: SPARS.cpp:750
boost::property_map< SpannerGraph, vertex_color_t >::type sparseColorProperty_
Access to draw colors for the SparseVertexs of S, to indicate addition type.
Definition: SPARS.h:505
void computeX(DenseVertex v, DenseVertex vp, DenseVertex vpp, std::vector< SparseVertex > &Xs)
Computes all nodes which qualify as a candidate x for v, v&#39;, and v".
Definition: SPARS.cpp:908
void reverse()
Reverse the path.
unsigned int guardCount() const
Returns the number of guards added to S.
Definition: SPARS.h:336
std::mutex graphMutex_
Mutex to guard access to the graphs.
Definition: SPARS.h:559
bool haveSolution(const std::vector< DenseVertex > &start, const std::vector< DenseVertex > &goal, base::PathPtr &solution)
Check if there exists a solution, i.e., there exists a pair of milestones such that the first is in s...
Definition: SPARS.cpp:241
A class to store the exit status of Planner::solve()
Definition: PlannerStatus.h:48
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...
virtual bool isStartGoalPairValid(const State *, const State *) const
Since there can be multiple starting states (and multiple goal states) it is possible certain pairs a...
Definition: Goal.h:138
This class contains routines that attempt to simplify geometric paths.
A shared pointer wrapper for ompl::base::SpaceInformation.
base::PathPtr constructSolution(const SparseVertex start, const SparseVertex goal) const
Given two milestones from the same connected component, construct a path connecting them and set it a...
Definition: SPARS.cpp:955
An optimization objective which corresponds to optimizing path length.
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
virtual void checkValidity()
Check to see if the planner is in a working state (setup has been called, a goal was set...
Definition: Planner.cpp:100
static const unsigned int FIND_VALID_STATE_ATTEMPTS_WITHOUT_TERMINATION_CHECK
Maximum number of sampling attempts to find a valid state, without checking whether the allowed time ...
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
Definition: Console.h:66
PlannerInputStates pis_
Utility class to extract valid input states.
Definition: Planner.h:404
DenseVertex sparseQueryVertex_
DenseVertex for performing nearest neighbor queries on the SPARSE roadmap.
Definition: SPARS.h:490
unsigned getMaxFailures() const
Retrieve the maximum consecutive failure limit.
Definition: SPARS.h:291
Abstract definition of optimization objectives.
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition: Planner.h:410
const State * nextStart()
Return the next valid start state or nullptr if no more valid start states are available.
Definition: Planner.cpp:230
The exception type for ompl.
Definition: Exception.h:47
unsigned int consecutiveFailures_
A counter for the number of consecutive failed iterations of the algorithm.
Definition: SPARS.h:532
virtual void setProblemDefinition(const base::ProblemDefinitionPtr &pdef)
Set the problem definition for the planner. The problem needs to be set before calling solve()...
Definition: SPARS.cpp:140
DenseVertex queryVertex_
Vertex for performing nearest neighbor queries on the DENSE graph.
Definition: SPARS.h:493
virtual bool couldSample() const
Return true if samples could be generated by this sampler at some point in the future. By default this is equivalent to canSample(), but for GoalLazySamples, this call also reflects the fact that a sampling thread is active and although no samples are produced yet, some may become available at some point in the future.
bool checkAddInterface(const std::vector< DenseVertex > &graphNeighborhood, const std::vector< DenseVertex > &visibleNeighborhood, DenseVertex q)
Checks the latest dense sample for bridging an edge-less interface.
Definition: SPARS.cpp:575
Make the minimal number of connections required to ensure asymptotic optimality.
SpannerGraph s_
The sparse roadmap, S.
Definition: SPARS.h:481
std::string name_
The name of this planner.
Definition: Planner.h:407
bool reachedFailureLimit() const
Returns true if we have reached the iteration failures limit, maxFailures_.
Definition: SPARS.cpp:286
double denseDelta_
SPARS parameter for dense graph connection distance.
Definition: SPARS.h:550
void checkForSolution(const base::PlannerTerminationCondition &ptc, base::PathPtr &solution)
Definition: SPARS.cpp:217
bool addedSolution_
A flag indicating that a solution has been added during solve()
Definition: SPARS.h:541
bool checkAddConnectivity(const base::State *lastState, const std::vector< SparseVertex > &neigh)
Checks the latest dense sample for connectivity, and adds appropriately.
Definition: SPARS.cpp:543
base::OptimizationObjectivePtr opt_
Objective cost function for PRM graph edges.
Definition: SPARS.h:562
bool optimizingPaths
Flag indicating whether the planner attempts to optimize the path and reduce its length until the max...
Definition: Planner.h:216
void connectSparsePoints(SparseVertex v, SparseVertex vp)
Convenience function for creating an edge in the Spanner Roadmap.
Definition: SPARS.cpp:513
void restart()
Forget how many states were returned by nextStart() and nextGoal() and return all states again...
Definition: Planner.cpp:170
void getSparseNeighbors(base::State *inState, std::vector< SparseVertex > &graphNeighborhood)
Get all nodes in the sparse graph which are within sparseDelta_ of the given state.
Definition: SPARS.cpp:740
void checkQueryStateInitialization()
Check that the query vertex is initialized (used for internal nearest neighbor searches) ...
Definition: SPARS.cpp:291
std::vector< SparseVertex > startM_
Array of start guards.
Definition: SPARS.h:484
Definition of a geometric path.
Definition: PathGeometric.h:60
SparseVertex addGuard(base::State *state, GuardType type)
Construct a node with the given state (state) for the spanner and store it in the nn structure...
Definition: SPARS.cpp:496
SpaceInformationPtr si_
The space information for which planning is done.
Definition: Planner.h:398
void resetFailures()
A reset function for resetting the failures count.
Definition: SPARS.cpp:146
double sparseDistanceFunction(const SparseVertex a, const SparseVertex b) const
Compute distance between two nodes in the sparse roadmap spanner.
Definition: SPARS.h:460
PathGeometric geomPath_
Geometric Path variable used for smoothing out paths.
Definition: SPARS.h:496
bool addPathToSpanner(const DensePath &p, SparseVertex vp, SparseVertex vpp)
Method for actually adding a dense path to the Roadmap Spanner, S.
Definition: SPARS.cpp:769
boost::property_map< DenseGraph, vertex_representative_t >::type representativesProperty_
Access to the representatives of the Dense vertices.
Definition: SPARS.h:508
std::deque< base::State * > DensePath
Internal representation of a dense path.
Definition: SPARS.h:121
GuardType
Enumeration which specifies the reason a guard is added to the spanner.
Definition: SPARS.h:84
DenseGraph g_
The dense graph, D.
Definition: SPARS.h:478
void setSparseDeltaFraction(double d)
Set the delta fraction for connection distance on the sparse spanner. This value represents the visib...
Definition: SPARS.h:275
DenseVertex addSample(base::State *workState, const base::PlannerTerminationCondition &ptc)
Attempt to add a single sample to the roadmap.
Definition: SPARS.cpp:196
bool sameComponent(SparseVertex m1, SparseVertex m2)
Check that two vertices are in the same connected component.
Definition: SPARS.cpp:303
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition: Cost.h:47
const std::string & getName() const
Get the name of the planner.
Definition: Planner.cpp:55
bool isSetup() const
Check if setup() was called for this planner.
Definition: Planner.cpp:107
DenseNeighbors nn_
Nearest neighbors data structure.
Definition: SPARS.h:472
A shared pointer wrapper for ompl::base::Path.
double averageValence() const
Returns the average valence of the spanner graph.
Definition: SPARS.cpp:715
This bit is set if casting to sampleable goal regions (ompl::base::GoalSampleableRegion) is possible...
Definition: GoalTypes.h:55
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition: Console.h:68