BITstar.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2014, University of Toronto
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 University of Toronto 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 /* Authors: Jonathan Gammell */
36 
37 //My definition:
38 #include "ompl/geometric/planners/bitstar/BITstar.h"
39 
40 //For, you know, math
41 #include <cmath>
42 //For stringstreams
43 #include <sstream>
44 //For stream manipulations
45 #include <iomanip>
46 //For std::bind
47 #include <functional>
48 //For boost math constants
49 #include <boost/math/constants/constants.hpp>
50 
51 //For OMPL_INFORM et al.
52 #include "ompl/util/Console.h"
53 //For exceptions:
54 #include "ompl/util/Exception.h"
55 // For geometric equations like unitNBallMeasure
56 #include "ompl/util/GeometricEquations.h"
57 //For ompl::base::GoalSampleableRegion, which both GoalState and GoalStates derive from:
58 #include "ompl/base/goals/GoalSampleableRegion.h"
59 //For getDefaultNearestNeighbors
60 #include "ompl/tools/config/SelfConfig.h"
61 //For ompl::geometric::path
62 #include "ompl/geometric/PathGeometric.h"
63 //For the default optimization objective:
64 #include "ompl/base/objectives/PathLengthOptimizationObjective.h"
65 
66 
67 
68 namespace ompl
69 {
70  namespace geometric
71  {
73  //Public functions:
74  BITstar::BITstar(const ompl::base::SpaceInformationPtr& si, const std::string& name /*= "BITstar"*/)
75  : ompl::base::Planner(si, name),
76  sampler_(),
77  opt_(),
78  startVertices_(),
79  goalVertices_(),
80  prunedStartVertices_(),
81  prunedGoalVertices_(),
82  curGoalVertex_(),
83  freeStateNN_(),
84  vertexNN_(),
85  intQueue_(),
86  newSamples_(),
87  recycledSamples_(),
88  numUniformStates_(0u),
89  r_(0.0), //Purposeful Gibberish
90  k_rgg_(0.0), //Purposeful Gibberish
91  k_(0u), //Purposeful Gibberish
92  bestCost_( std::numeric_limits<double>::infinity() ), //Gets set in setup to the proper calls from OptimizationObjective
93  bestLength_(0u),
94  prunedCost_( std::numeric_limits<double>::infinity() ), //Gets set in setup to the proper calls from OptimizationObjective
95  prunedMeasure_(0.0), //Gets set in setup with the proper call to Planner::si_->getSpaceMeasure()
96  minCost_( std::numeric_limits<double>::infinity() ), //Gets set in setup to the proper calls from OptimizationObjective
97  costSampled_( std::numeric_limits<double>::infinity() ), //Gets set in setup to the proper calls from OptimizationObjective
98  hasSolution_(false),
99  stopLoop_(false),
100  approximateSoln_(false),
101  approximateDiff_(-1.0),
102  numIterations_(0u),
103  numBatches_(0u),
104  numPrunings_(0u),
105  numSamples_(0u),
106  numVertices_(0u),
107  numFreeStatesPruned_(0u),
108  numVerticesDisconnected_(0u),
109  numRewirings_(0u),
110  numStateCollisionChecks_(0u),
111  numEdgeCollisionChecks_(0u),
112  numNearestNeighbours_(0u),
113  numEdgesProcessed_(0u),
114  useStrictQueueOrdering_(false),
115  rewireFactor_(2.0),
116  samplesPerBatch_(100u),
117  useKNearest_(true),
118  usePruning_(true),
119  pruneFraction_(0.01),
120  delayRewiring_(true),
121  useJustInTimeSampling_(false),
122  dropSamplesOnPrune_(false),
123  stopOnSolnChange_(false)
124  {
125  //Make sure the default name reflects the default k-nearest setting, if not overridden to something else
126  if (useKNearest_ == true && Planner::getName() == "BITstar")
127  {
128  //It's the current default r-disc BIT* name, but we're using k-nearest, so change
129  Planner::setName("kBITstar");
130  }
131  else if (useKNearest_ == false && Planner::getName() == "kBITstar")
132  {
133  //It's the current default k-nearest BIT* name, but we're using r-disc, so change
134  Planner::setName("BITstar");
135  }
136  //It's not default named, don't change it
137 
138  //Specify my planner specs:
139  Planner::specs_.recognizedGoal = ompl::base::GOAL_SAMPLEABLE_REGION;
140  Planner::specs_.multithreaded = false;
141  Planner::specs_.approximateSolutions = false; //For now!
142  Planner::specs_.optimizingPaths = true;
143  Planner::specs_.directed = true;
144  Planner::specs_.provingSolutionNonExistence = false;
145 
146  //Register my setting callbacks
147  Planner::declareParam<double>("rewire_factor", this, &BITstar::setRewireFactor, &BITstar::getRewireFactor, "1.0:0.01:3.0");
148  Planner::declareParam<unsigned int>("samples_per_batch", this, &BITstar::setSamplesPerBatch, &BITstar::getSamplesPerBatch, "1:1:1000000");
149  Planner::declareParam<bool>("use_k_nearest", this, &BITstar::setKNearest, &BITstar::getKNearest, "0,1");
150  Planner::declareParam<bool>("use_graph_pruning", this, &BITstar::setPruning, &BITstar::getPruning, "0,1");
151  Planner::declareParam<double>("prune_threshold_as_fractional_cost_change", this, &BITstar::setPruneThresholdFraction, &BITstar::getPruneThresholdFraction, "0.0:0.01:1.0");
152  Planner::declareParam<bool>("delay_rewiring_to_first_solution", this, &BITstar::setDelayRewiringUntilInitialSolution, &BITstar::getDelayRewiringUntilInitialSolution, "0,1");
153  Planner::declareParam<bool>("use_just_in_time_sampling", this, &BITstar::setJustInTimeSampling, &BITstar::getJustInTimeSampling, "0,1");
154  Planner::declareParam<bool>("drop_unconnected_samples_on_prune", this, &BITstar::setDropSamplesOnPrune, &BITstar::getDropSamplesOnPrune, "0,1");
155  Planner::declareParam<bool>("stop_on_each_solution_improvement", this, &BITstar::setStopOnSolnImprovement, &BITstar::getStopOnSolnImprovement, "0,1");
156 
157  //More advanced setting callbacks that aren't necessary to be exposed to Python. Uncomment if desired.
158  //Planner::declareParam<bool>("use_strict_queue_ordering", this, &BITstar::setStrictQueueOrdering, &BITstar::getStrictQueueOrdering, "0,1");
159  //Planner::declareParam<bool>("use_edge_failure_tracking", this, &BITstar::setUseFailureTracking, &BITstar::getUseFailureTracking, "0,1");
160 
161  //Register my progress info:
162  addPlannerProgressProperty("best cost DOUBLE", std::bind(&BITstar::bestCostProgressProperty, this));
163  addPlannerProgressProperty("number of segments in solution path INTEGER", std::bind(&BITstar::bestLengthProgressProperty, this));
164  addPlannerProgressProperty("current free states INTEGER", std::bind(&BITstar::currentFreeProgressProperty, this));
165  addPlannerProgressProperty("current graph vertices INTEGER", std::bind(&BITstar::currentVertexProgressProperty, this));
166  addPlannerProgressProperty("state collision checks INTEGER", std::bind(&BITstar::stateCollisionCheckProgressProperty, this));
167  addPlannerProgressProperty("edge collision checks INTEGER", std::bind(&BITstar::edgeCollisionCheckProgressProperty, this));
168  addPlannerProgressProperty("nearest neighbour calls INTEGER", std::bind(&BITstar::nearestNeighbourProgressProperty, this));
169 
170  //Extra progress info that aren't necessary for every day use. Uncomment if desired.
171  //addPlannerProgressProperty("vertex queue size INTEGER", std::bind(&BITstar::vertexQueueSizeProgressProperty, this));
172  //addPlannerProgressProperty("edge queue size INTEGER", std::bind(&BITstar::edgeQueueSizeProgressProperty, this));
173  //addPlannerProgressProperty("iterations INTEGER", std::bind(&BITstar::iterationProgressProperty, this));
174  //addPlannerProgressProperty("batches INTEGER", std::bind(&BITstar::batchesProgressProperty, this));
175  //addPlannerProgressProperty("graph prunings INTEGER", std::bind(&BITstar::pruningProgressProperty, this));
176  //addPlannerProgressProperty("total states generated INTEGER", std::bind(&BITstar::totalStatesCreatedProgressProperty, this));
177  //addPlannerProgressProperty("vertices constructed INTEGER", std::bind(&BITstar::verticesConstructedProgressProperty, this));
178  //addPlannerProgressProperty("states pruned INTEGER", std::bind(&BITstar::statesPrunedProgressProperty, this));
179  //addPlannerProgressProperty("graph vertices disconnected INTEGER", std::bind(&BITstar::verticesDisconnectedProgressProperty, this));
180  //addPlannerProgressProperty("rewiring edges INTEGER", std::bind(&BITstar::rewiringProgressProperty, this));
181  }
182 
183 
184 
186  {
187  }
188 
189 
190 
192  {
193  //Call the base class setup:
194  Planner::setup();
195 
196  //Do some sanity checks
197  //Make sure we have a problem definition
198  if(static_cast<bool>(Planner::pdef_) == false)
199  {
200  OMPL_ERROR("%s::setup() was called without a problem definition.", Planner::getName().c_str());
201  Planner::setup_ = false;
202  return;
203  }
204 
205  //Make sure we have an optimization objective
206  if (Planner::pdef_->hasOptimizationObjective() == false)
207  {
208  OMPL_INFORM("%s: No optimization objective specified. Defaulting to optimizing path length.", Planner::getName().c_str());
209  Planner::pdef_->setOptimizationObjective( std::make_shared<base::PathLengthOptimizationObjective> (Planner::si_) );
210  }
211 
212  //If the problem definition *has* a goal, make sure it is of appropriate type
213  if (static_cast<bool>(Planner::pdef_->getGoal()) == true)
214  {
215  if (Planner::pdef_->getGoal()->hasType(ompl::base::GOAL_SAMPLEABLE_REGION) == false)
216  {
217  OMPL_ERROR("%s::setup() BIT* currently only supports goals that can be cast to a sampleable goal region (i.e., are countable sets).", Planner::getName().c_str());
218  Planner::setup_ = false;
219  return;
220  }
221  //No else, of correct type.
222  }
223  //No else, called without a goal. Is this MoveIt?
224 
225  //Store the optimization objective for future ease of use
226  opt_ = Planner::pdef_->getOptimizationObjective();
227 
228  //Configure the nearest-neighbour constructs.
229  //Only allocate if they are empty (as they can be set to a specific version by a call to setNearestNeighbors)
230  if (static_cast<bool>(freeStateNN_) == false)
231  {
232  freeStateNN_.reset( ompl::tools::SelfConfig::getDefaultNearestNeighbors<VertexPtr>(this) );
233  }
234  //No else, already allocated (by a call to setNearestNeighbors())
235 
236  if (static_cast<bool>(vertexNN_) == false)
237  {
238  vertexNN_.reset( ompl::tools::SelfConfig::getDefaultNearestNeighbors<VertexPtr>(this) );
239  }
240  //No else, already allocated (by a call to setNearestNeighbors())
241 
242  //Configure:
243  freeStateNN_->setDistanceFunction(std::bind(&BITstar::nnDistance, this,
244  std::placeholders::_1, std::placeholders::_2));
245  vertexNN_->setDistanceFunction(std::bind(&BITstar::nnDistance, this,
246  std::placeholders::_1, std::placeholders::_2));
247 
248  //Configure the queue
249  //std::make_shared can only take 9 arguments, so be careful:
250  intQueue_ = std::make_shared<IntegratedQueue> (opt_,
251  std::bind(&BITstar::nnDistance, this, std::placeholders::_1, std::placeholders::_2),
252  std::bind(&BITstar::nearestSamples, this, std::placeholders::_1, std::placeholders::_2),
253  std::bind(&BITstar::nearestVertices, this, std::placeholders::_1, std::placeholders::_2),
254  std::bind(&BITstar::lowerBoundHeuristicVertex, this, std::placeholders::_1),
255  std::bind(&BITstar::currentHeuristicVertex, this, std::placeholders::_1),
256  std::bind(&BITstar::lowerBoundHeuristicEdge, this, std::placeholders::_1),
257  std::bind(&BITstar::currentHeuristicEdge, this, std::placeholders::_1),
258  std::bind(&BITstar::currentHeuristicEdgeTarget, this, std::placeholders::_1));
259  intQueue_->setDelayedRewiring(delayRewiring_);
260 
261  //Set the best-cost, pruned-cost, sampled-cost and min-cost to the proper opt_-based values:
262  bestCost_ = opt_->infiniteCost();
263  prunedCost_ = opt_->infiniteCost();
264  minCost_ = opt_->infiniteCost();
265  costSampled_ = opt_->infiniteCost();
266 
267  //Add any start and goals vertices that exist to the queue, but do NOT wait for any more goals:
269 
270  //Get the measure of the problem
271  prunedMeasure_ = Planner::si_->getSpaceMeasure();
272 
273  //Does the problem have finite boundaries?
274  if (std::isfinite(prunedMeasure_) == false)
275  {
276  //It does not, so let's estimate a measure of the planning problem.
277  //A not horrible place to start would be hypercube proportional to the distance between the start and goal. It's not *great*, but at least it sort of captures the order-of-magnitude of the problem.
278 
279  //First, some asserts.
280  //Check that JIT sampling is on, which is required for infinite problems
281  if (useJustInTimeSampling_ == false)
282  {
283  throw ompl::Exception("For unbounded planning problems, just-in-time sampling must be enabled before calling setup.");
284  }
285  //No else
286 
287  //Check that we have a start and goal
288  if (startVertices_.empty() == true || goalVertices_.empty() == true)
289  {
290  throw ompl::Exception("For unbounded planning problems, at least one start and one goal must exist before calling setup.");
291  }
292  //No else
293 
294  //Variables
295  //The maximum distance between start and goal:
296  double maxDist = 0.0;
297  //The scale on the maximum distance, i.e. the width of the hypercube is equal to this value times the distance between start and goal.
298  //This number is completely made up.
299  double distScale = 2.0;
300 
301  //Find the max distance
302  for (std::list<VertexPtr>::const_iterator sIter = startVertices_.begin(); sIter != startVertices_.end(); ++sIter)
303  {
304  for (std::list<VertexPtr>::const_iterator gIter = goalVertices_.begin(); gIter != goalVertices_.end(); ++gIter)
305  {
306  maxDist = std::max(maxDist, Planner::si_->distance((*sIter)->stateConst(), (*gIter)->stateConst()));
307  }
308  }
309 
310  //Calculate an estimate of the problem measure by (hyper)cubing the max distance
311  prunedMeasure_ = std::pow(distScale*maxDist, Planner::si_->getStateDimension());
312  }
313  //No else, finite problem dimension
314 
315  //Finally initialize the nearestNeighbour terms:
316  this->initializeNearestTerms();
317 
318  //Debug: Output an estimate of the state measure:
319  //this->estimateMeasures();
320  }
321 
322 
323 
325  {
326  //Clear all the variables.
327  //Keep this in the order of the constructors list:
328 
329  //The various convenience pointers:
330  sampler_.reset();
331  opt_.reset();
332  startVertices_.clear();
333  goalVertices_.clear();
334  prunedStartVertices_.clear();
335  prunedGoalVertices_.clear();
336  curGoalVertex_.reset();
337 
338  //The list of samples
339  if (static_cast<bool>(freeStateNN_) == true)
340  {
341  freeStateNN_->clear();
342  freeStateNN_.reset();
343  }
344  //No else, not allocated
345 
346  //The list of vertices
347  if (static_cast<bool>(vertexNN_) == true)
348  {
349  vertexNN_->clear();
350  vertexNN_.reset();
351  }
352 
353  //The list of new and recycled samples
354  newSamples_.clear();
355  recycledSamples_.clear();
356 
357  //The queue:
358  if (static_cast<bool>(intQueue_) == true)
359  {
360  intQueue_->clear();
361  intQueue_.reset();
362  }
363 
364  //DO NOT reset the parameters:
365  //useStrictQueueOrdering_
366  //rewireFactor_
367  //samplesPerBatch_
368  //useKNearest_
369  //usePruning_
370  //pruneFraction_
371  //delayRewiring_
372  //useJustInTimeSampling_
373  //dropSamplesOnPrune_
374  //stopOnSolnChange_
375 
376  //Reset the various calculations? TODO: Should I recalculate them?
377  numUniformStates_ = 0u;
378  r_ = 0.0;
379  k_rgg_ = 0.0; //This is a double for better rounding later
380  k_ = 0u;
381  bestCost_ = ompl::base::Cost(std::numeric_limits<double>::infinity());
382  bestLength_ = 0u;
383  prunedCost_ = ompl::base::Cost(std::numeric_limits<double>::infinity());
384  prunedMeasure_ = Planner::si_->getSpaceMeasure();
385  minCost_ = ompl::base::Cost(0.0);
387  hasSolution_ = false;
388  stopLoop_ = false;
389  approximateSoln_ = false;
390  approximateDiff_ = -1.0;
391  numIterations_ = 0u;
392  numSamples_ = 0u;
393  numVertices_ = 0u;
399  numEdgesProcessed_ = 0u;
400  numRewirings_ = 0u;
401  numBatches_ = 0u;
402  numPrunings_ = 0u;
403 
404  //Mark as not setup:
405  Planner::setup_ = false;
406 
407  //Call my base clear:
408  Planner::clear();
409  }
410 
411 
412 
414  {
415  Planner::checkValidity();
416  OMPL_INFORM("%s: Searching for a solution to the given planning problem.", Planner::getName().c_str());
417 
418  //Reset the manual stop to the iteration loop:
419  stopLoop_ = false;
420 
421  //If we don't have a goal yet, recall updateStartAndGoalStates, but wait for the first goal (or until the PTC comes true and we give up):
422  if (goalVertices_.empty() == true)
423  {
424  this->updateStartAndGoalStates(ptc);
425  }
426 
427  //Run the outerloop until we're stopped, a suitable cost is found, or until we find the minimum possible cost within tolerance:
428  while (opt_->isSatisfied(bestCost_) == false && ptc == false && (opt_->isCostBetterThan(minCost_, bestCost_) == true || Planner::pis_.haveMoreStartStates() == true || Planner::pis_.haveMoreGoalStates() == true) && stopLoop_ == false)
429  {
430  this->iterate();
431  }
432 
433  if (hasSolution_ == true)
434  {
435  this->endSuccessMessage();
436 
437  this->publishSolution();
438  }
439  else
440  {
441  this->endFailureMessage();
442  }
443 
444  //PlannerStatus(addedSolution, approximate)
446  }
447 
448 
449 
451  {
452  //Get the base planner class data:
453  Planner::getPlannerData(data);
454 
455  //Add samples
456  if (freeStateNN_)
457  {
458  //Variables:
459  //The list of unused samples:
460  std::vector<VertexPtr> samples;
461 
462  //Get the list of samples
463  freeStateNN_->list(samples);
464 
465  //Iterate through it turning each into a disconnected vertex
466  for (std::vector<VertexPtr>::const_iterator sIter = samples.begin(); sIter != samples.end(); ++sIter)
467  {
468  //No, add as a regular vertex:
469  data.addVertex(ompl::base::PlannerDataVertex((*sIter)->stateConst()));
470  }
471  }
472  //No else.
473 
474  //Add vertices
475  if (vertexNN_)
476  {
477  //Variables:
478  //The list of vertices in the graph:
479  std::vector<VertexPtr> vertices;
480 
481  //Get the list of vertices
482  vertexNN_->list(vertices);
483 
484  //Iterate through it turning each into a vertex with an edge:
485  for (std::vector<VertexPtr>::const_iterator vIter = vertices.begin(); vIter != vertices.end(); ++vIter)
486  {
487  //Is the vertex the start?
488  if ((*vIter)->isRoot() == true)
489  {
490  //Yes, add as a start vertex:
491  data.addStartVertex(ompl::base::PlannerDataVertex((*vIter)->stateConst()));
492  }
493  else
494  {
495  //No, add as a regular vertex:
496  data.addVertex(ompl::base::PlannerDataVertex((*vIter)->stateConst()));
497 
498  //And as an incoming edge
499  data.addEdge(ompl::base::PlannerDataVertex((*vIter)->getParentConst()->stateConst()), ompl::base::PlannerDataVertex((*vIter)->stateConst()));
500  }
501  }
502  }
503  //No else.
504 
505  //Did we find a solution?
506  if (hasSolution_ == true)
507  {
508  data.markGoalState(curGoalVertex_->stateConst());
509  }
510  }
511 
512 
513 
514  std::pair<ompl::base::State const*, ompl::base::State const*> BITstar::getNextEdgeInQueue()
515  {
516  //Variable:
517  //The next edge as a basic pair of states
518  std::pair<ompl::base::State const*, ompl::base::State const*> nextEdge;
519 
520  //If we're using strict queue ordering, make sure the queue is up to date
521  if(useStrictQueueOrdering_ == true)
522  {
523  //Resort the queues as necessary (if the graph has been rewired).
524  this->resort();
525  }
526 
527  if (intQueue_->isEmpty() == false)
528  {
529  //The next edge in the queue:
530  nextEdge = std::make_pair(intQueue_->frontEdge().first->state(), intQueue_->frontEdge().second->state());
531  }
532  else
533  {
534  //An empty edge:
535  nextEdge = std::make_pair<ompl::base::State*, ompl::base::State*>(nullptr, nullptr);
536  }
537 
538  return nextEdge;
539  }
540 
541 
542 
544  {
545  //Variable
546  //The cost of the next edge
547  ompl::base::Cost nextCost;
548 
549  //If we're using strict queue ordering, make sure the queue is up to date
550  if(useStrictQueueOrdering_ == true)
551  {
552  //Resort the queues as necessary (if the graph has been rewired).
553  this->resort();
554  }
555 
556  if (intQueue_->isEmpty() == false)
557  {
558  //The next cost in the queue:
559  nextCost = intQueue_->frontEdgeValue().first;
560  }
561  else
562  {
563  //An infinite cost:
564  nextCost = opt_->infiniteCost();
565  }
566 
567  return nextCost;
568  }
569 
570 
571 
572  void BITstar::getEdgeQueue(std::vector<std::pair<VertexConstPtr, VertexConstPtr> >* edgesInQueue)
573  {
574  intQueue_->listEdges(edgesInQueue);
575  }
576 
577 
578 
579  void BITstar::getVertexQueue(std::vector<VertexConstPtr>* verticesInQueue)
580  {
581  intQueue_->listVertices(verticesInQueue);
582  }
583 
584 
585 
586  template<template<typename T> class NN>
588  {
589  //Check if the problem is already setup, if so, the NN structs have data in them and you can't really change them:
590  if (Planner::setup_ == true)
591  {
592  throw ompl::Exception("The type of nearest neighbour datastructure cannot be changed once a planner is setup. ");
593  }
594  else
595  {
596  //The problem isn't setup yet, create NN structs of the specified type:
597  freeStateNN_ = std::make_shared< NN<VertexPtr> >();
598  vertexNN_ = std::make_shared< NN<VertexPtr> >();
599  }
600  }
602 
603 
604 
606  //Protected functions:
608  {
609  OMPL_INFORM("%s: Estimating the measure of the planning domain. This is a debugging function that does not have any effect on the planner.", Planner::getName().c_str());
610  //Variables:
611  //The total number of samples:
612  unsigned int numTotalSamples;
613  //The resulting samples in free:
614  unsigned int numFreeSamples;
615  //The resulting samples in obs:
616  unsigned int numObsSamples;
617  //The sample fraction of free:
618  double fractionFree;
619  //The sample fraction of obs:
620  double fractionObs;
621  //The total measure of the space:
622  double totalMeasure;
623  //The resulting estimate of the free measure
624  double freeMeasure;
625  //The resulting estimate of the obs measure
626  double obsMeasure;
627 
628  //Set the total number of samples
629  numTotalSamples = 100000u;
630  numFreeSamples = 0u;
631  numObsSamples = 0u;
632 
633  //Draw samples, classifying each one
634  for (unsigned int i = 0u; i < numTotalSamples; ++i)
635  {
636  //Allocate a state
637  ompl::base::State* aState = Planner::si_->allocState();
638 
639  //Sample:
640  sampler_->sampleUniform(aState, bestCost_);
641 
642  //Check if collision free
643  if (Planner::si_->isValid(aState) == true)
644  {
645  ++numFreeSamples;
646  }
647  else
648  {
649  ++numObsSamples;
650  }
651  }
652 
653  //Calculate the fractions:
654  fractionFree = static_cast<double>(numFreeSamples)/static_cast<double>(numTotalSamples);
655 
656  fractionObs = static_cast<double>(numObsSamples)/static_cast<double>(numTotalSamples);
657 
658  //Get the total measure of the space
659  totalMeasure = Planner::si_->getSpaceMeasure();
660 
661  //Calculate the measure of the free space
662  freeMeasure = fractionFree*totalMeasure;
663 
664  //Calculate the measure of the obs space
665  obsMeasure = fractionObs*totalMeasure;
666 
667  //Announce
668  OMPL_INFORM("%s: %u samples (%u free, %u in collision) from a space with measure %.4f estimates %.2f%% free and %.2f%% in collision (measures of %.4f and %.4f, respectively).", Planner::getName().c_str(), numTotalSamples, numFreeSamples, numObsSamples, totalMeasure, 100.0*fractionFree, 100.0*fractionObs, freeMeasure, obsMeasure);
669  }
670 
671 
673  {
674  //Info:
675  ++numIterations_;
676 
677  //If we're using strict queue ordering, make sure the queues are up to date
678  if(useStrictQueueOrdering_ == true)
679  {
680  //The queues will be resorted if the graph has been rewired.
681  this->resort();
682  }
683 
684  //Is the edge queue empty
685  if (intQueue_->isEmpty() == true)
686  {
687  //Is it also unsorted?
688  if (intQueue_->isSorted() == false)
689  {
690  //If it is, then we've hit a rare condition where we emptied it without having to sort it, so address that
691  this->resort();
692  }
693  else
694  {
695  //If not, then we're either just starting the problem, or just finished a batch. Either way, make a batch of samples and fill the queue for the first time:
696  this->newBatch();
697  }
698  }
699  else
700  {
701  //If the edge queue is not empty, then there is work to do!
702 
703  //Variables:
704  //The current edge:
705  VertexPtrPair bestEdge;
706 
707  //Pop the minimum edge
709  intQueue_->popFrontEdge(&bestEdge);
710 
711  //In the best case, can this edge improve our solution given the current graph?
712  //g_t(v) + c_hat(v,x) + h_hat(x) < g_t(x_g)
713  if (opt_->isCostBetterThan( this->combineCosts(bestEdge.first->getCost(), this->edgeCostHeuristic(bestEdge), this->costToGoHeuristic(bestEdge.second)), bestCost_ ) == true)
714  {
715  //Variables:
716  //The true cost of the edge:
718 
719  //Get the true cost of the edge
720  trueEdgeCost = this->trueEdgeCost(bestEdge);
721 
722  //Can this actual edge ever improve our solution?
723  //g_hat(v) + c(v,x) + h_hat(x) < g_t(x_g)
724  if (opt_->isCostBetterThan( this->combineCosts(this->costToComeHeuristic(bestEdge.first), trueEdgeCost, this->costToGoHeuristic(bestEdge.second)), bestCost_ ) == true)
725  {
726  //Does this edge have a collision?
727  if (this->checkEdge(bestEdge) == true)
728  {
729  //Does the current edge improve our graph?
730  //g_t(v) + c(v,x) < g_t(x)
731  if (opt_->isCostBetterThan( opt_->combineCosts(bestEdge.first->getCost(), trueEdgeCost), bestEdge.second->getCost() ) == true)
732  {
733  //YAAAAH. Add the edge! Allowing for the sample to be removed from free if it is not currently connected and otherwise propagate cost updates to descendants.
734  //addEdge will update the queue and handle the extra work that occurs if this edge improves the solution.
735  this->addEdge(bestEdge, trueEdgeCost, true, true);
736 
737  //Prune the edge queue of any unnecessary incoming edges
738  intQueue_->pruneEdgesTo(bestEdge.second);
739 
740  //We will only prune the whole graph/samples on a new batch.
741  }
742  //No else, this edge may be useful at some later date.
743  }
744  //No else, we failed
745  }
746  //No else, we failed
747  }
748  else if (intQueue_->isSorted() == false)
749  {
750  //The edge cannot improve our solution, but the queue is imperfectly sorted, so we must resort before we give up.
751  this->resort();
752  }
753  else
754  {
755  //Else, I cannot improve the current solution, and as the queue is perfectly sorted and I am the best edge, no one can improve the current solution . Give up on the batch:
756  intQueue_->finish();
757  }
758  } //Integrated queue not empty.
759  }
760 
761 
762 
764  {
765  //Info:
766  ++numBatches_;
767 
768  //Reset the queue:
769  intQueue_->reset();
770 
771  //Do we need to update our starts or goals?
772  if (Planner::pis_.haveMoreStartStates() == true || Planner::pis_.haveMoreGoalStates() == true)
773  {
774  //There are new starts/goals to get.
776  }
777  //No else, we have enough of a problem to do some work, and everything's up to date.
778 
779  //Prune the graph (if enabled)
780  this->prune();
781 
782  //Set the cost sampled to the minimum
784 
785  //Update the nearest-neighbour terms for the number of samples we *will* have.
786  this->updateNearestTerms();
787 
788  //Relabel all the previous samples as old
789  for (unsigned int i = 0u; i < newSamples_.size(); ++i)
790  {
791  //If the sample still exists, mark as old. It can get pruned during a resort.
792  if (newSamples_.at(i)->isPruned() == false)
793  {
794  newSamples_.at(i)->markOld();
795  }
796  //No else, this sample has been pruned and will shortly disappear
797  }
798 
799  //Clear the list of new samples
800  newSamples_.clear();
801 
802  //Make the recycled vertices to new:
804 
805  //Clear the list of recycled
806  recycledSamples_.clear();
807  }
808 
809 
810 
812  {
813  //Variable
814  //The required cost to contain the neighbourhood of this vertex:
815  ompl::base::Cost costReqd = neighbourhoodCost(vertex);
816 
817  //Check if we need to generate new samples inorder to completely cover the neighbourhood of the vertex
818  if (opt_->isCostBetterThan(costSampled_, costReqd))
819  {
820  //Variable
821  //The total number of samples we wish to have.
822  unsigned int totalReqdSamples;
823 
824  //Get the measure of what we're sampling
825  if (useJustInTimeSampling_ == true)
826  {
827  //Variables
828  //The sample density for this slice of the problem.
829  double sampleDensity;
830  //The resulting number of samples needed for this slice as a *double*
831  double dblNum;
832 
833  //Calculate the sample density given the number of samples per batch and the measure of this batch by assuming that this batch will fill the same measure as the previous
834  sampleDensity = static_cast<double>(samplesPerBatch_)/prunedMeasure_;
835 
836  //Convert that into the number of samples needed for this slice.
837  dblNum = sampleDensity * sampler_->getInformedMeasure(costSampled_, costReqd);
838 
839  //The integer of the double are definitely sampled
840  totalReqdSamples = numSamples_ + static_cast<unsigned int>(dblNum);
841 
842  //And the fractional part represents the probability of one more sample. I like being pedantic.
843  if (rng_.uniform01() <= (dblNum - static_cast<double>(totalReqdSamples)))
844  {
845  //One more please
846  ++totalReqdSamples;
847  }
848  //No else.
849  }
850  else
851  {
852  //We're generating all our samples in one batch. Do it to it.
853  totalReqdSamples = numSamples_ + samplesPerBatch_;
854  }
855 
856  //Actually generate the new samples
857  while (numSamples_ < totalReqdSamples)
858  {
859  //Variable
860  //The new state:
861  VertexPtr newState = std::make_shared<Vertex>(Planner::si_, opt_);
862 
863  //Sample in the interval [costSampled_, costReqd):
864  sampler_->sampleUniform(newState->state(), costSampled_, costReqd);
865 
866  //If the state is collision free, add it to the list of free states
868  if (Planner::si_->isValid(newState->stateConst()) == true)
869  {
870  //Add the new state as a sample
871  this->addSample(newState);
872 
873  //Update the number of uniformly distributed states
875 
876  //Update the number of sample
877  ++numSamples_;
878  }
879  //No else
880  }
881 
882  //Mark that we've sampled all cost spaces (This is in preparation for JIT sampling)
883  costSampled_ = costReqd;
884  }
885  //No else, the samples are up to date
886  }
887 
888 
889 
891  {
892  //Variable:
893  //Whether or not we pruned, start as unpruned
894  bool vertexPruned = false;
895 
896  //Test if we should we do a little tidying up:
897  //Is pruning enabled? Do we have a solution? Has the solution changed enough?
898  if ( (usePruning_ == true) && (hasSolution_ == true) && (std::abs(this->fractionalChange(bestCost_, prunedCost_)) > pruneFraction_) )
899  {
900  //Variables:
901  //The current measure of the problem space:
902  double informedMeasure = sampler_->getInformedMeasure(bestCost_);
903 
904  //Is there good reason to prune? I.e., is the informed subset measurably less than the total problem domain? If an informed measure is not available, we'll assume yes:
905  if ( (sampler_->hasInformedMeasure() == true && informedMeasure < si_->getSpaceMeasure()) || (sampler_->hasInformedMeasure() == false) )
906  {
907  //Variable:
908  //The number of vertices and samples pruned
909  std::pair<unsigned int, unsigned int> numPruned;
910 
911  OMPL_INFORM("%s: Pruning the planning problem from a solution of %.4f to %.4f, resulting in a change of problem size from %.4f to %.4f.", Planner::getName().c_str(), prunedCost_.value(), bestCost_.value(), prunedMeasure_, informedMeasure);
912 
913  //Increment the pruning counter:
914  ++numPrunings_;
915 
916  //First, prune the starts/goals:
917  this->pruneStartsGoals();
918 
919  //Prune the samples
920  this->pruneSamples();
921 
922  //Prune the graph. This can be done extra efficiently by using some info in the integrated queue.
923  //This requires access to the nearest neighbour structures so vertices can be moved to free states.s
925 
926  //The number of vertices and samples pruned are incrementally updated.
928  numFreeStatesPruned_ = numFreeStatesPruned_ + numPruned.second;
929 
930  //Store the cost at which we pruned:
932 
933  //And the measure:
934  prunedMeasure_ = informedMeasure;
935 
936  //Check if any states have actually been pruned
937  vertexPruned = (numPruned.second > 0u);
938  }
939  //No else, it's not worth the work to prune...
940  }
941  //No else, why was I called?
942 
943  return vertexPruned;
944  }
945 
946 
947 
949  {
950  //Variable:
951  //The number of vertices and samples pruned
952  std::pair<unsigned int, unsigned int> numPruned;
953 
954  //During resorting we can be lazy and skip resorting vertices that will just be pruned later. So, are we using pruning?
955  if (usePruning_ == true)
956  {
957  //We are, give the queue access to the nearest neighbour structures so vertices can be pruned instead of resorted.
958  //The number of vertices pruned is also incrementally updated.
959  numPruned = intQueue_->resort(vertexNN_, freeStateNN_, &recycledSamples_);
960  }
961  else
962  {
963  //We are not, give it empty NN structs
964  numPruned = intQueue_->resort(VertexPtrNNPtr(), VertexPtrNNPtr(), nullptr);
965  }
966 
967  //The number of vertices and samples pruned are incrementally updated.
969  numFreeStatesPruned_ = numFreeStatesPruned_ + numPruned.second;
970 
971  return (numPruned.second > 0u);
972  }
973 
974 
975 
977  {
978  //Variable
979  //The path geometric
980  std::shared_ptr<ompl::geometric::PathGeometric> pathGeoPtr;
981  //The reverse path of state pointers
982  std::vector<const ompl::base::State*> reversePath;
983 
984  //Allocate the pathGeoPtr
985  pathGeoPtr = std::make_shared<ompl::geometric::PathGeometric>(Planner::si_);
986 
987  //Get the reversed path
988  reversePath = this->bestPathFromGoalToStart();
989 
990  //Now iterate that vector in reverse, putting the states into the path geometric
991  for (std::vector<const ompl::base::State*>::const_reverse_iterator sIter = reversePath.rbegin(); sIter != reversePath.rend(); ++sIter)
992  {
993  pathGeoPtr->append(*sIter);
994  }
995 
996  //Now create the solution
997  ompl::base::PlannerSolution soln(pathGeoPtr);
998 
999  //Mark the name:
1000  soln.setPlannerName(Planner::getName());
1001 
1002  //Mark as exact or approximate:
1003  if (approximateSoln_ == true)
1004  {
1006  }
1007 
1008  //Mark whether the solution met the optimization objective:
1009  soln.optimized_ = opt_->isSatisfied(bestCost_);
1010 
1011  //Add the solution to the Problem Definition:
1012  Planner::pdef_->addSolutionPath(soln);
1013  }
1014 
1015 
1016 
1017  std::vector<const ompl::base::State*> BITstar::bestPathFromGoalToStart() const
1018  {
1019  //A vector of states from goal->start:
1020  std::vector<const ompl::base::State*> reversePath;
1021 
1022  //Iterate up the chain from the goal, creating a backwards vector:
1023  reversePath.push_back(curGoalVertex_->stateConst());
1024 
1025  //Then, use a vertex pointer like an iterator. Starting at the goal, we iterate up the chain pushing the *parent* of the iterator into the vector until the vertex has no parent.
1026  //This will allows us to add the start (as the parent of the first child) and then stop when we get to the start itself, avoiding trying to find its nonexistent child
1027  for (VertexConstPtr curVertex = curGoalVertex_; curVertex->isRoot() == false; curVertex = curVertex->getParentConst())
1028  {
1029  //Check the case where the chain ends incorrectly. This is unnecessary but sure helpful in debugging:
1030  if (curVertex->hasParent() == false)
1031  {
1032  throw ompl::Exception("The path to the goal does not originate at a start state. Something went wrong.");
1033  }
1034 
1035  //Push back the parent into the vector as a state pointer:
1036  reversePath.push_back(curVertex->getParentConst()->stateConst());
1037  }
1038  return reversePath;
1039  }
1040 
1041 
1042 
1044  {
1045  //Variable
1046  //Whether we've added a start or goal:
1047  bool addedGoal = false;
1048  bool addedStart = false;
1049  //Whether we have to rebuid the queue, i.e.. whether we've called updateStartAndGoalStates before
1050  bool rebuildQueue = false;
1051 
1052  //Add the new starts and goals to the lists of said vertices.
1053  //Do goals first, as they are only added as samples.
1054  //We do this as nested conditions so we always call nextGoal(ptc) at least once (regardless of whether there are moreGoalStates or not)
1055  //in case we have been given a non trivial PTC that wants us to wait, but do *not* call it again if there are no more goals
1056  //(as in the nontrivial PTC case, doing so would cause us to wait out the ptc and never try to solve anything)
1057  do
1058  {
1059  //Variable
1060  //A new goal pointer, if there are none, it will be nullptr.
1061  //We will wait for the duration of PTC for a new goal to appear.
1062  const ompl::base::State* newGoal = Planner::pis_.nextGoal(ptc);
1063 
1064  //Check if it's valid
1065  if (static_cast<bool>(newGoal) == true)
1066  {
1067  //It is valid and we are adding a goal, we will need to rebuild the queue if any starts have previously been added as their (and any descendents') heuristic cost-to-go may change:
1068  rebuildQueue = (startVertices_.size() > 0u);
1069 
1070  //Allocate the vertex pointer
1071  goalVertices_.push_back(std::make_shared<Vertex>(Planner::si_, opt_));
1072 
1073  //Copy the value into the state
1074  Planner::si_->copyState(goalVertices_.back()->state(), newGoal);
1075 
1076  //And add this goal to the set of samples:
1077  this->addSample(goalVertices_.back());
1078 
1079  //Mark that we've added:
1080  addedGoal = true;
1081  }
1082  //No else, there was no goal.
1083  }
1084  while (Planner::pis_.haveMoreGoalStates() == true);
1085 
1086  //And then do the for starts. We do this last as the starts are added to the queue, which uses a cost-to-go heuristic in it's ordering, and for that we want all the goals updated.
1087  //As there is no way to wait for new *start* states, this loop can be cleaner
1088  //There is no need to rebuild the queue when we add start vertices, as the queue is ordered on current cost-to-come, and adding a start doesn't change that.
1089  while (Planner::pis_.haveMoreStartStates() == true)
1090  {
1091  //Variable
1092  //A new start pointer
1093  const ompl::base::State* newStart = Planner::pis_.nextStart();
1094 
1095  //Allocate the vertex pointer:
1096  startVertices_.push_back(std::make_shared<Vertex>(Planner::si_, opt_, true));
1097 
1098  //Copy the value into the state:
1099  Planner::si_->copyState(startVertices_.back()->state(), newStart);
1100 
1101  //Add this start to the queue. It is not a sample, so skip that step:
1102  this->addVertex(startVertices_.back(), false);
1103 
1104  //Mark that we've added:
1105  addedStart = true;
1106  }
1107 
1108  //Now, if we added a new start and have previously pruned goals, we may want to readd them.
1109  if (addedStart == true && prunedGoalVertices_.empty() == false)
1110  {
1111  //Variable
1112  //An iterator to the list of pruned goals
1113  std::list<VertexPtr>::iterator pgIter = prunedGoalVertices_.begin();
1114 
1115  //Consider each one
1116  while (pgIter != prunedGoalVertices_.end())
1117  {
1118  //Mark as unpruned
1119  (*pgIter)->markUnpruned();
1120 
1121  //Check if it should be readded (i.e., would it be pruned *now*?)
1122  if (intQueue_->vertexPruneCondition(*pgIter) == true)
1123  {
1124  //It would be pruned, so remark as pruned
1125  (*pgIter)->markPruned();
1126 
1127  //and move onto the next:
1128  ++pgIter;
1129  }
1130  else
1131  {
1132  //It would not be pruned now, so readd it!
1133  //Add back to the list:
1134  goalVertices_.push_back(*pgIter);
1135 
1136  //Add as a sample
1137  this->addSample(*pgIter);
1138 
1139  //Mark what we've added:
1140  addedGoal = true;
1141 
1142  //Remove the start from the list, this returns the next iterator
1143  pgIter = prunedGoalVertices_.erase(pgIter);
1144 
1145  //Just like the other new goals, we will need to rebuild the queue if any starts have previously been added. Which was a condition to be here in the first place
1146  rebuildQueue = true;
1147  }
1148  }
1149  }
1150 
1151  //Now, if we added a goal and have previously pruned starts, we will have to do the same on those
1152  if (addedGoal == true && prunedStartVertices_.empty() == false)
1153  {
1154  //Variable
1155  //An iterator to the list of pruned starts
1156  std::list<VertexPtr>::iterator psIter = prunedStartVertices_.begin();
1157 
1158  //Consider each one
1159  while (psIter != prunedStartVertices_.end())
1160  {
1161  //Mark as unpruned
1162  (*psIter)->markUnpruned();
1163 
1164  //Check if it should be readded (i.e., would it be pruned *now*?)
1165  if (intQueue_->vertexPruneCondition(*psIter) == true)
1166  {
1167  //It would be pruned, so remark as pruned
1168  (*psIter)->markPruned();
1169 
1170  //and move onto the next:
1171  ++psIter;
1172  }
1173  else
1174  {
1175  //It would not be pruned, readd it!
1176  //Add it back to the list
1177  startVertices_.push_back(*psIter);
1178 
1179  //Add to the queue as a vertex. It is not a sample, so skip that step:
1180  this->addVertex(*psIter, false);
1181 
1182  //Mark what we've added:
1183  addedStart = true;
1184 
1185  //Remove the start from the list, this returns the next iterator
1186  psIter = prunedStartVertices_.erase(psIter);
1187  }
1188  }
1189  }
1190 
1191  //If we've added a state, we have some updating to do.
1192  if (addedGoal == true || addedStart == true)
1193  {
1194  //Update the minimum cost
1195  for (std::list<VertexPtr>::const_iterator sIter = startVertices_.begin(); sIter != startVertices_.end(); ++sIter)
1196  {
1197  //Take the better of the min cost so far and the cost-to-go from this start
1198  minCost_ = opt_->betterCost(minCost_, this->costToGoHeuristic(*sIter));
1199  }
1200 
1201  //If we have at least one start and goal, allocate a sampler
1202  if (startVertices_.size() > 0u && goalVertices_.size() > 0u)
1203  {
1204  //There is a start and goal, allocate
1205  sampler_ = opt_->allocInformedStateSampler(Planner::pdef_, std::numeric_limits<unsigned int>::max());
1206  }
1207  //No else, this will get allocated when we get the updated start/goal.
1208 
1209  //Was there an existing queue that needs to be rebuilt?
1210  if (rebuildQueue == true)
1211  {
1212  //There was, inform
1213  OMPL_INFORM("%s: Updating starts/goals and rebuilding the queue.", Planner::getName().c_str());
1214 
1215  //Flag the queue as unsorted downstream from every existing start.
1216  for (std::list<VertexPtr>::const_iterator sIter = startVertices_.begin(); sIter != startVertices_.end(); ++sIter)
1217  {
1218  intQueue_->markVertexUnsorted(*sIter);
1219  }
1220 
1221  //Resort the queue.
1222  this->resort();
1223  }
1224  //No else
1225  }
1226  //No else, why were we called?
1227 
1228  //Make sure that if we have a goal, we also have a start, since there's no way to wait for more *starts*
1229  if (goalVertices_.empty() == false && startVertices_.empty() == true)
1230  {
1231  OMPL_WARN("%s, The problem has a goal but not a start. As PlannerInputStates provides no method to wait for a _start_ state, this will likely be problematic.", Planner::getName().c_str());
1232  }
1233  //No else
1234  }
1235 
1236 
1237 
1239  {
1240  //Are there superfluous starts to prune?
1241  if (startVertices_.size() > 1u)
1242  {
1243  //Yes, Iterate through the list
1244 
1245  //Variable
1246  //The iterator to the start:
1247  std::list<VertexPtr>::iterator startIter = startVertices_.begin();
1248 
1249  //Run until at the end:
1250  while (startIter != startVertices_.end())
1251  {
1252  //Check if this start has met the criteria to be pruned
1253  if (intQueue_->vertexPruneCondition(*startIter) == true)
1254  {
1255  //It has, update counters. By definition of the heuristics, start vertices are either in the tree or are deleted. Since we're pruning this one, that means we're going all the way to remove it:
1258 
1259  //Remove the start vertex completely from the queue, they don't have parents
1260  intQueue_->eraseVertex(*startIter, false, vertexNN_, freeStateNN_, &recycledSamples_);
1261 
1262  //Store the start vertex in the pruned list, in case it later needs to be readded:
1263  prunedStartVertices_.push_back(*startIter);
1264 
1265  //Remove from the list, this returns the next iterator
1266  startIter = startVertices_.erase(startIter);
1267  }
1268  else
1269  {
1270  //Still valid, move to the next one:
1271  ++startIter;
1272  }
1273  }
1274  }
1275  //No else, can't prune 1 start.
1276 
1277  //Are there superfluous goals to prune?
1278  if (goalVertices_.size() > 1u)
1279  {
1280  //Yes, Iterate through the list
1281 
1282  //Variable
1283  //The iterator to the start:
1284  std::list<VertexPtr>::iterator goalIter = goalVertices_.begin();
1285 
1286  //Run until at the end:
1287  while (goalIter != goalVertices_.end())
1288  {
1289  //Check if this start has met the criteria to be pruned
1290  if (intQueue_->vertexPruneCondition(*goalIter) == true)
1291  {
1292  //It has, remove the goal vertex completely
1293  //Check if this vertex is in the tree
1294  if ((*goalIter)->isInTree() == true)
1295  {
1296  //It is, increment the counters
1299 
1300  //And erase it from the queue:
1301  intQueue_->eraseVertex(*goalIter, (*goalIter)->hasParent(), vertexNN_, freeStateNN_, &recycledSamples_);
1302 
1303  //Store the start vertex in the pruned list, in case it later needs to be readded:
1304  prunedGoalVertices_.push_back(*goalIter);
1305 
1306  //Remove from the list, this returns the next iterator
1307  goalIter = goalVertices_.erase(goalIter);
1308  }
1309  else
1310  {
1311  //It is not, so we just delete it like a sample
1312  this->dropSample(*goalIter);
1313 
1314  //Remove from the list, this returns the next iterator
1315  goalIter = goalVertices_.erase(goalIter);
1316  }
1317  }
1318  else
1319  {
1320  //The goal is still valid, get the next
1321  ++goalIter;
1322  }
1323  }
1324  }
1325  //No else, can't prune 1 goal.
1326  }
1327 
1328 
1329 
1331  {
1332  //Are we dropping samples anytime we prune?
1333  if (dropSamplesOnPrune_ == true)
1334  {
1335  //We are, update the pruned counter
1337 
1338  //and the number of uniform samples
1339  numUniformStates_ = 0u;
1340 
1341  //Then remove all of the samples
1342  freeStateNN_->clear();
1343  }
1344  else
1345  {
1346  //Variable:
1347  //The list of samples:
1348  std::vector<VertexPtr> samples;
1349 
1350  //Get the list of samples
1351  freeStateNN_->list(samples);
1352 
1353  //Iterate through the list and remove any samples that have a heuristic larger than the bestCost_
1354  for (unsigned int i = 0u; i < samples.size(); ++i)
1355  {
1356  //Check if this state should be pruned:
1357  if (intQueue_->samplePruneCondition(samples.at(i)) == true)
1358  {
1359  //Yes, remove it
1360  this->dropSample(samples.at(i));
1361  }
1362  //No else, keep.
1363  }
1364  }
1365  }
1366 
1367 
1368 
1370  {
1372  return Planner::si_->checkMotion(edge.first->stateConst(), edge.second->stateConst());
1373  }
1374 
1375 
1376 
1378  {
1379  //Update the counter:
1381 
1382  //Remove from the list of samples
1383  freeStateNN_->remove(oldSample);
1384 
1385  //Mark the sample as pruned
1386  oldSample->markPruned();
1387  }
1388 
1389 
1390 
1391  void BITstar::addEdge(const VertexPtrPair& newEdge, const ompl::base::Cost& edgeCost, const bool& removeFromFree, const bool& updateDescendants)
1392  {
1393  if (newEdge.first->isInTree() == false)
1394  {
1395  throw ompl::Exception("Adding an edge from a vertex not connected to the graph");
1396  }
1397 
1398  //This should be a debug-level-only assert some day:
1399  /*
1400  if (opt_->isCostEquivalentTo(this->trueEdgeCost(newEdge), edgeCost) == false)
1401  {
1402  throw ompl::Exception("You have passed the wrong edge cost to addEdge.");
1403  }
1404  */
1405 
1406  //If the vertex is currently in the tree, we need to rewire
1407  if (newEdge.second->hasParent() == true)
1408  {
1409  //Replace the edge
1410  this->replaceParent(newEdge, edgeCost, updateDescendants);
1411  }
1412  else
1413  {
1414  //If not, we just add the vertex, first mark the target vertex as no longer new and unexpanded:
1415  newEdge.second->markUnexpandedToSamples();
1416  newEdge.second->markUnexpandedToVertices();
1417 
1418  //Then add a child to the parent, not updating costs:
1419  newEdge.first->addChild(newEdge.second, false);
1420 
1421  //Add a parent to the child, updating descendant costs if requested:
1422  newEdge.second->addParent(newEdge.first, edgeCost, updateDescendants);
1423 
1424  //Then add to the queues as necessary
1425  this->addVertex(newEdge.second, removeFromFree);
1426  }
1427 
1428  //If the path to the goal has changed, we may need to update the cached info about the solution cost or solution length:
1429  this->updateGoalVertex();
1430  }
1431 
1432 
1433 
1434  void BITstar::replaceParent(const VertexPtrPair& newEdge, const ompl::base::Cost& edgeCost, const bool& updateDescendants)
1435  {
1436  if (newEdge.second->getParent() == newEdge.first)
1437  {
1438  throw ompl::Exception("The new and old parents of the given rewiring are the same.");
1439  }
1440 
1441  //This would be a good debug-level-only assert
1442  if (opt_->isCostBetterThan(newEdge.second->getCost(), opt_->combineCosts(newEdge.first->getCost(), edgeCost)) == true)
1443  {
1444  throw ompl::Exception("The new edge will increase the cost-to-come of the vertex!");
1445  }
1446 
1447  //Increment our counter:
1448  ++numRewirings_;
1449 
1450  //Remove the child from the parent, not updating costs
1451  newEdge.second->getParent()->removeChild(newEdge.second, false);
1452 
1453  //Remove the parent from the child, not updating costs
1454  newEdge.second->removeParent(false);
1455 
1456  //Add the child to the parent, not updating costs
1457  newEdge.first->addChild(newEdge.second, false);
1458 
1459  //Add the parent to the child. This updates the cost of the child as well as all it's descendents (if requested).
1460  newEdge.second->addParent(newEdge.first, edgeCost, updateDescendants);
1461 
1462  //Mark the queues as unsorted below this child
1463  intQueue_->markVertexUnsorted(newEdge.second);
1464  }
1465 
1466 
1467 
1469  {
1470  //Variable
1471  //Whether we've updated the goal, be pessimistic.
1472  bool goalUpdated = false;
1473  //The the new goal, start with the current goal
1474  VertexPtr newBestGoal = curGoalVertex_;
1475  //The new cost, start as the current bestCost_
1476  ompl::base::Cost newCost = bestCost_;
1477 
1478  //Iterate through the list of goals, and see if the solution has changed
1479  for (std::list<VertexPtr>::const_iterator gIter = goalVertices_.begin(); gIter != goalVertices_.end(); ++gIter)
1480  {
1481  //First, is this goal even in the tree?
1482  if ((*gIter)->isInTree() == true)
1483  {
1484  //Next, is there currently a solution?
1485  if (static_cast<bool>(newBestGoal) == true)
1486  {
1487  //There is already a solution, is it to to this goal?
1488  if (*gIter == newBestGoal)
1489  {
1490  //Ah-ha, We meet again! Are we doing any better? We check the length as sometimes the path length changes with minimal change in cost.
1491  if (opt_->isCostEquivalentTo((*gIter)->getCost(), newCost) == false || ((*gIter)->getDepth() + 1u) != bestLength_)
1492  {
1493  //The path to the current best goal has changed, so we need to update it.
1494  goalUpdated = true;
1495  newBestGoal = *gIter;
1496  newCost = newBestGoal->getCost();
1497  }
1498  //No else, no change
1499  }
1500  else
1501  {
1502  //It is not to this goal, we have a second solution! What an easy problem... but is it better?
1503  if (opt_->isCostBetterThan((*gIter)->getCost(), newCost) == true)
1504  {
1505  //It is! Save this as a better goal:
1506  goalUpdated = true;
1507  newBestGoal = *gIter;
1508  newCost = newBestGoal->getCost();
1509  }
1510  //No else, not a better solution
1511  }
1512  }
1513  else
1514  {
1515  //There isn't a preexisting solution, that means that any goal is an update:
1516  goalUpdated = true;
1517  newBestGoal = *gIter;
1518  newCost = newBestGoal->getCost();
1519  }
1520  }
1521  //No else, can't be a better solution if it's not in the spanning tree, can it?
1522  }
1523 
1524  //Did we update the goal?
1525  if (goalUpdated == true)
1526  {
1527  //We have a better solution!
1528  if (hasSolution_ == false)
1529  {
1530  approximateSoln_ = false;
1531  approximateDiff_ = -1.0;
1532  }
1533 
1534  //Mark that we have a solution
1535  hasSolution_ = true;
1536  intQueue_->hasSolution();
1537 
1538  //Store the current goal
1539  curGoalVertex_ = newBestGoal;
1540 
1541  //Update the best cost:
1542  bestCost_ = newCost;
1543 
1544  //and best length
1545  bestLength_ = curGoalVertex_->getDepth() + 1u;
1546 
1547  //Update the queue threshold:
1548  intQueue_->setThreshold(bestCost_);
1549 
1550  //Stop the solution loop if enabled:
1552 
1553  //Brag:
1554  this->goalMessage();
1555 
1556  //If enabled, pass the intermediate solution back through the call back:
1557  if (static_cast<bool>(Planner::pdef_->getIntermediateSolutionCallback()) == true)
1558  {
1559  //The form of path passed to the intermediate solution callback is not well documented, but it *appears* that it's not supposed
1560  //to include the start or goal; however, that makes no sense for multiple start/goal problems, so we're going to include it anyway (sorry).
1561  //Similarly, it appears to be ordered as (goal, goal-1, goal-2,...start+1, start) which conveniently allows us to reuse code.
1562  Planner::pdef_->getIntermediateSolutionCallback()(this, this->bestPathFromGoalToStart(), bestCost_);
1563  }
1564  }
1565  //No else, the goal didn't change
1566  }
1567 
1568 
1569 
1570  void BITstar::addSample(const VertexPtr& newSample)
1571  {
1572  //Mark as new
1573  newSample->markNew();
1574 
1575  //Add to the list of new samples
1576  newSamples_.push_back(newSample);
1577 
1578  //Add to the NN structure:
1579  freeStateNN_->add(newSample);
1580  }
1581 
1582 
1583 
1584  void BITstar::addVertex(const VertexPtr& newVertex, const bool& removeFromFree)
1585  {
1586  //Make sure it's connected first, so that the queue gets updated properly. This is a day of debugging I'll never get back
1587  if (newVertex->isInTree() == false)
1588  {
1589  throw ompl::Exception("Vertices must be connected to the graph before adding");
1590  }
1591 
1592  //Remove the vertex from the list of samples (if it even existed)
1593  if (removeFromFree == true)
1594  {
1595  freeStateNN_->remove(newVertex);
1596  }
1597  //No else
1598 
1599  //Add to the NN structure:
1600  vertexNN_->add(newVertex);
1601 
1602  //Add to the queue:
1603  intQueue_->insertVertex(newVertex);
1604 
1605  //Increment the number of vertices added:
1606  ++numVertices_;
1607  }
1608 
1609 
1610 
1611  unsigned int BITstar::nearestSamples(const VertexPtr& vertex, std::vector<VertexPtr>* neighbourSamples)
1612  {
1613  //Make sure sampling has happened first:
1614  this->updateSamples(vertex);
1615 
1616  //Increment our counter:
1618 
1619  if (useKNearest_ == true)
1620  {
1621  freeStateNN_->nearestK(vertex, k_, *neighbourSamples);
1622  return k_;
1623  }
1624  else
1625  {
1626  freeStateNN_->nearestR(vertex, r_, *neighbourSamples);
1627  return 0u;
1628  }
1629  }
1630 
1631 
1632 
1633  unsigned int BITstar::nearestVertices(const VertexPtr& vertex, std::vector<VertexPtr>* neighbourVertices)
1634  {
1635  //Increment our counter:
1637 
1638  if (useKNearest_ == true)
1639  {
1640  vertexNN_->nearestK(vertex, k_, *neighbourVertices);
1641  return k_;
1642  }
1643  else
1644  {
1645  vertexNN_->nearestR(vertex, r_, *neighbourVertices);
1646  return 0u;
1647  }
1648  }
1649 
1650 
1651 
1652  double BITstar::nnDistance(const VertexConstPtr& a, const VertexConstPtr& b) const
1653  {
1654  //Using RRTstar as an example, this order gives us the distance FROM the queried state TO the other neighbours in the structure.
1655  //The distance function between two states
1656  if (!a->stateConst())
1657  {
1658  throw ompl::Exception("a->state is unallocated");
1659  }
1660  if (!b->stateConst())
1661  {
1662  throw ompl::Exception("b->state is unallocated");
1663  }
1664  return Planner::si_->distance(b->stateConst(), a->stateConst());
1665  }
1666 
1667 
1668 
1670  {
1671  return opt_->combineCosts( this->costToComeHeuristic(vertex), this->costToGoHeuristic(vertex) );
1672  }
1673 
1674 
1675 
1677  {
1678  return opt_->combineCosts( vertex->getCost(), this->costToGoHeuristic(vertex) );
1679  }
1680 
1681 
1683  {
1684  return this->combineCosts(this->costToComeHeuristic(edgePair.first), this->edgeCostHeuristic(edgePair), this->costToGoHeuristic(edgePair.second));
1685  }
1686 
1687 
1688 
1690  {
1691  return opt_->combineCosts(this->currentHeuristicEdgeTarget(edgePair), this->costToGoHeuristic(edgePair.second));
1692  }
1693 
1694 
1695 
1697  {
1698  return opt_->combineCosts(edgePair.first->getCost(), this->edgeCostHeuristic(edgePair));
1699  }
1700 
1701 
1702 
1704  {
1705  //Variable
1706  //The current best cost to the state, initialize to infinity
1707  ompl::base::Cost curBest = opt_->infiniteCost();
1708 
1709  //Iterate over the list of starts, finding the minimum estimated cost-to-come to the state
1710  for (std::list<VertexPtr>::const_iterator startIter = startVertices_.begin(); startIter != startVertices_.end(); ++startIter)
1711  {
1712  //Update the cost-to-come as the better of the best so far and the new one
1713  curBest = opt_->betterCost(curBest, opt_->motionCostHeuristic((*startIter)->stateConst(), vertex->stateConst()));
1714  }
1715 
1716  //Return
1717  return curBest;
1718  }
1719 
1720 
1721 
1723  {
1724  return opt_->motionCostHeuristic(edgePair.first->stateConst(), edgePair.second->stateConst());
1725  }
1726 
1727 
1728 
1730  {
1731  //Variable
1732  //The current best cost to a goal from the state, initialize to infinity
1733  ompl::base::Cost curBest = opt_->infiniteCost();
1734 
1735  //Iterate over the list of goals, finding the minimum estimated cost-to-go from the state
1736  for (std::list<VertexPtr>::const_iterator goalIter = goalVertices_.begin(); goalIter != goalVertices_.end(); ++goalIter)
1737  {
1738  //Update the cost-to-go as the better of the best so far and the new one
1739  curBest = opt_->betterCost(curBest, opt_->motionCostHeuristic(vertex->stateConst(), (*goalIter)->stateConst()));
1740  }
1741 
1742  //Return
1743  return curBest;
1744  }
1745 
1746 
1748  {
1749  return opt_->motionCost(edgePair.first->stateConst(), edgePair.second->stateConst());
1750  }
1751 
1752 
1753 
1755  {
1756  //Even though the problem domain is defined by prunedCost_ (the cost the last time we pruned), there is no point generating samples outside bestCost_ (which may be less).
1757  if (useJustInTimeSampling_ == true)
1758  {
1759  return opt_->betterCost(bestCost_, opt_->combineCosts(this->lowerBoundHeuristicVertex(vertex), ompl::base::Cost(2.0 * r_)));
1760  }
1761  else
1762  {
1763  return bestCost_;
1764  }
1765  }
1766 
1767 
1768 
1770  {
1771  //If b is better than a, then a is worse than b
1772  return opt_->isCostBetterThan(b, a);
1773  }
1774 
1775 
1776 
1778  {
1779  //If a is better than b, or b is better than a, then they are not equal
1780  return opt_->isCostBetterThan(a,b) || opt_->isCostBetterThan(b,a);
1781  }
1782 
1783 
1784 
1786  {
1787  //If b is not better than a, then a is better than, or equal to, b
1788  return !opt_->isCostBetterThan(b, a);
1789  }
1790 
1791 
1792 
1794  {
1795  //If a is not better than b, than a is worse than, or equal to, b
1796  return !opt_->isCostBetterThan(a,b);
1797  }
1798 
1799 
1800 
1802  {
1803  return opt_->combineCosts(a, opt_->combineCosts(b, c));
1804  }
1805 
1806 
1807 
1809  {
1810  return opt_->combineCosts(a, this->combineCosts(b, c, d));
1811  }
1812 
1813 
1814 
1815  double BITstar::fractionalChange(const ompl::base::Cost& newCost, const ompl::base::Cost& oldCost) const
1816  {
1817  return this->fractionalChange(newCost, oldCost, oldCost);
1818  }
1819 
1820 
1821 
1822  double BITstar::fractionalChange(const ompl::base::Cost& newCost, const ompl::base::Cost& oldCost, const ompl::base::Cost& refCost) const
1823  {
1824  //If the old cost is not finite, than we call that infinite percent improvement
1825  if (opt_->isFinite(oldCost) == false)
1826  {
1827  //Return infinity (but not beyond)
1828  return std::numeric_limits<double>::infinity();
1829  }
1830  else
1831  {
1832  //Calculate and return
1833  return ( newCost.value() - oldCost.value() )/refCost.value();
1834  }
1835  }
1836 
1837 
1838 
1840  {
1841  //Calculate the k-nearest constant
1842  k_rgg_ = this->minimumRggK();
1843 
1844  //Update the actual terms
1845  this->updateNearestTerms();
1846  }
1847 
1848 
1849 
1851  {
1852  //Variables:
1853  //The number of uniformly distributed states:
1854  unsigned int N;
1855 
1856  //Calculate the number of N, are we dropping samples?
1857  if (dropSamplesOnPrune_ == true)
1858  {
1859  //We arre, so we've been tracking the number of uniform states, just us that
1860  N = numUniformStates_;
1861  }
1862  else
1863  {
1864  //We are not, so the all vertices and samples are uniform, less the starts and goals.
1865  N = vertexNN_->size() + freeStateNN_->size() - startVertices_.size() - goalVertices_.size();
1866  }
1867 
1868  //In general, we calculate the terms considering the future samples. This is only not the case when it's the initial call (i.e., the 0 batch):
1869  if (numBatches_ != 0u)
1870  {
1871  N = N + samplesPerBatch_;
1872  }
1873  //No else
1874 
1875 
1876  //If we only have starts and goals, be lazy
1877  if (N == 0u)
1878  {
1879  k_ = startVertices_.size() + goalVertices_.size();
1880  r_ = std::numeric_limits<double>::infinity();
1881  }
1882  else
1883  {
1884  if (useKNearest_ == true)
1885  {
1886  k_ = this->calculateK(N);
1887  }
1888  else
1889  {
1890  r_ = this->calculateR(N);
1891  }
1892  }
1893  }
1894 
1895 
1896 
1897  double BITstar::calculateR(unsigned int N) const
1898  {
1899  //Variables
1900  //The dimension cast as a double for readibility;
1901  double dimDbl = static_cast<double>(Planner::si_->getStateDimension());
1902  //The size of the graph
1903  double cardDbl = static_cast<double>(N);
1904 
1905  //Calculate the term and return
1906  return this->minimumRggR()*std::pow( std::log(cardDbl)/cardDbl, 1/dimDbl );
1907  }
1908 
1909 
1910 
1911  unsigned int BITstar::calculateK(unsigned int N) const
1912  {
1913  //Calculate the term and return
1914  return std::ceil( k_rgg_ * std::log(static_cast<double>(N)) );
1915  }
1916 
1917 
1918 
1919  double BITstar::minimumRggR() const
1920  {
1921  //Variables
1922  //The dimension cast as a double for readibility;
1923  double dimDbl = static_cast<double>(Planner::si_->getStateDimension());
1924 
1925  //Calculate the term and return
1926  return rewireFactor_*2.0*std::pow( (1.0 + 1.0/dimDbl)*( prunedMeasure_/unitNBallMeasure(Planner::si_->getStateDimension()) ), 1.0/dimDbl ); //RRG radius (biggest for unit-volume problem)
1927  //return rewireFactor_*std::pow( 2.0*(1.0 + 1.0/dimDbl)*( prunedMeasure_/unitNBallMeasure(Planner::si_->getStateDimension()) ), 1.0/dimDbl ); //RRT* radius (smaller for unit-volume problem)
1928  //return rewireFactor_*2.0*std::pow( (1.0/dimDbl)*( prunedMeasure_/unitNBallMeasure(Planner::si_->getStateDimension()) ), 1.0/dimDbl ); //FMT* radius (smallest for R2, equiv to RRT* for R3 and then middle for higher d. All unit-volume)
1929  }
1930 
1931 
1932 
1933  double BITstar::minimumRggK() const
1934  {
1935  //Variables
1936  //The dimension cast as a double for readibility;
1937  double dimDbl = static_cast<double>(Planner::si_->getStateDimension());
1938 
1939  //Calculate the term and return
1940  return rewireFactor_*(boost::math::constants::e<double>() + (boost::math::constants::e<double>() / dimDbl)); //RRG k-nearest
1941  }
1942 
1943 
1944 
1946  {
1947  OMPL_INFORM("%s (%u iters): Found a solution of cost %.4f (%u vertices) from %u samples by processing %u edges (%u collision checked) to create %u vertices and perform %u rewirings. The graph currently has %u vertices.", Planner::getName().c_str(), numIterations_, bestCost_.value(), bestLength_, numSamples_, numEdgesProcessed_, numEdgeCollisionChecks_, numVertices_, numRewirings_, vertexNN_->size());
1948  }
1949 
1950 
1951 
1953  {
1954  OMPL_INFORM("%s: Finished with a solution of cost %.4f (%u vertices) found from %u samples by processing %u edges (%u collision checked) to create %u vertices and perform %u rewirings. The final graph has %u vertices.", Planner::getName().c_str(), bestCost_.value(), bestLength_, numSamples_, numEdgesProcessed_, numEdgeCollisionChecks_, numVertices_, numRewirings_, vertexNN_->size());
1955  }
1956 
1957 
1958 
1960  {
1961  OMPL_INFORM("%s (%u iters): Did not find a solution from %u samples after processing %u edges (%u collision checked) to create %u vertices and perform %u rewirings. The final graph has %u vertices.", Planner::getName().c_str(), numIterations_, numSamples_, numEdgesProcessed_, numEdgeCollisionChecks_, numVertices_, numRewirings_, vertexNN_->size());
1962  }
1963 
1964 
1965 
1966  void BITstar::statusMessage(const ompl::msg::LogLevel& msgLevel, const std::string& status) const
1967  {
1968  //Check if we need to create the message
1969  if (msgLevel >= ompl::msg::getLogLevel())
1970  {
1971  //Variable
1972  //The message as a stream:
1973  std::stringstream outputStream;
1974 
1975  //Create the stream:
1976  //The name of the planner
1977  outputStream << Planner::getName();
1978  outputStream << " (";
1979  //The current path cost:
1980  outputStream << "l: " << std::setw(6) << std::setfill(' ') << std::setprecision(5) << bestCost_.value();
1981  //The number of batches:
1982  outputStream << ", b: " << std::setw(5) << std::setfill(' ') << numBatches_;
1983  //The number of iterations
1984  outputStream << ", i: " << std::setw(5) << std::setfill(' ') << numIterations_;
1985  //The number of states current in the graph
1986  outputStream << ", g: " << std::setw(5) << std::setfill(' ') << vertexNN_->size();
1987  //The number of free states
1988  outputStream << ", f: " << std::setw(5) << std::setfill(' ') << freeStateNN_->size();
1989  //The number edges in the queue:
1990  outputStream << ", q: " << std::setw(5) << std::setfill(' ') << intQueue_->numEdges();
1991  //The total number of edges taken out of the queue:
1992  outputStream << ", t: " << std::setw(5) << std::setfill(' ') << numEdgesProcessed_;
1993  //The number of samples generated
1994  outputStream << ", s: " << std::setw(5) << std::setfill(' ') << numSamples_;
1995  //The number of vertices ever added to the graph:
1996  outputStream << ", v: " << std::setw(5) << std::setfill(' ') << numVertices_;
1997  //The number of prunings:
1998  outputStream << ", p: " << std::setw(5) << std::setfill(' ') << numPrunings_;
1999  //The number of rewirings:
2000  outputStream << ", r: " << std::setw(5) << std::setfill(' ') << numRewirings_;
2001  //The number of nearest-neighbour calls
2002  outputStream << ", n: " << std::setw(5) << std::setfill(' ') << numNearestNeighbours_;
2003  //The number of state collision checks:
2004  outputStream << ", c(s): " << std::setw(5) << std::setfill(' ') << numStateCollisionChecks_;
2005  //The number of edge collision checks:
2006  outputStream << ", c(e): " << std::setw(5) << std::setfill(' ') << numEdgeCollisionChecks_;
2007  outputStream << "): ";
2008  //The message:
2009  outputStream << status;
2010 
2011 
2012  if (msgLevel == ompl::msg::LOG_DEBUG)
2013  {
2014  OMPL_DEBUG("%s", outputStream.str().c_str());
2015  }
2016  else if (msgLevel == ompl::msg::LOG_INFO)
2017  {
2018  OMPL_INFORM("%s", outputStream.str().c_str());
2019  }
2020  else if (msgLevel == ompl::msg::LOG_WARN)
2021  {
2022  OMPL_WARN("%s", outputStream.str().c_str());
2023  }
2024  else if (msgLevel == ompl::msg::LOG_ERROR)
2025  {
2026  OMPL_ERROR("%s", outputStream.str().c_str());
2027  }
2028  else
2029  {
2030  throw ompl::Exception("Log level not recognized");
2031  }
2032  }
2033  //No else, this message is below the log level
2034  }
2036 
2037 
2038 
2040  //Boring sets/gets (Public) and progress properties (Protected):
2041  void BITstar::setRewireFactor(double rewireFactor)
2042  {
2043  rewireFactor_ = rewireFactor;
2044 
2045  //Check if there's things to update
2046  if (this->isSetup() == true)
2047  {
2048  //Reinitialize the terms:
2049  this->initializeNearestTerms();
2050  }
2051  }
2052 
2053 
2054 
2056  {
2057  return rewireFactor_;
2058  }
2059 
2060 
2061 
2062  void BITstar::setSamplesPerBatch(unsigned int n)
2063  {
2064  samplesPerBatch_ = n;
2065  }
2066 
2067 
2068 
2069  unsigned int BITstar::getSamplesPerBatch() const
2070  {
2071  return samplesPerBatch_;
2072  }
2073 
2074 
2075 
2076  void BITstar::setKNearest(bool useKNearest)
2077  {
2078  //Check if the flag has changed
2079  if (useKNearest != useKNearest_)
2080  {
2081  //If the planner is default named, we change it:
2082  if (useKNearest_ == true && Planner::getName() == "kBITstar")
2083  {
2084  //It's current the default k-nearest BIT* name, and we're toggling, so set to the default r-disc
2085  Planner::setName("BITstar");
2086  }
2087  else if (useKNearest_ == false && Planner::getName() == "BITstar")
2088  {
2089  //It's current the default r-disc BIT* name, and we're toggling, so set to the default k-nearest
2090  Planner::setName("kBITstar");
2091  }
2092  //It's not default named, don't change it
2093 
2094  //Set the k-nearest flag
2095  useKNearest_ = useKNearest;
2096 
2097  if (useKNearest_ == true)
2098  {
2099  //Check that we're not doing JIT
2100  if (useJustInTimeSampling_ == true)
2101  {
2102  throw ompl::Exception("JIT sampling does not work with the k-nearest variant of BIT*.");
2103  }
2104  }
2105 
2106  //Check if there's things to update
2107  if (this->isSetup() == true)
2108  {
2109  //Reinitialize the terms:
2110  this->initializeNearestTerms();
2111  }
2112  }
2113  //No else, it didn't change.
2114  }
2115 
2116 
2117 
2119  {
2120  return useKNearest_;
2121  }
2122 
2123 
2125  {
2126  useStrictQueueOrdering_ = beStrict;
2127  }
2128 
2129 
2130 
2132  {
2133  return useStrictQueueOrdering_;
2134  }
2135 
2136 
2137 
2139  {
2140  if (prune == false)
2141  {
2142  OMPL_WARN("%s: Turning pruning off has never really been tested.", Planner::getName().c_str());
2143  }
2144 
2145  usePruning_ = prune;
2146  }
2147 
2148 
2149 
2150  bool BITstar::getPruning() const
2151  {
2152  return usePruning_;
2153  }
2154 
2155 
2156 
2158  {
2159  if (fractionalChange < 0.0 || fractionalChange > 1.0)
2160  {
2161  throw ompl::Exception("Prune threshold must be specified as a fraction between [0, 1].");
2162  }
2163 
2165  }
2166 
2167 
2168 
2170  {
2171  return pruneFraction_;
2172  }
2173 
2174 
2175 
2177  {
2178  delayRewiring_ = delayRewiring;
2179 
2180  //Configure queue if constructed:
2181  if (intQueue_)
2182  {
2183  intQueue_->setDelayedRewiring(delayRewiring_);
2184  }
2185  }
2186 
2187 
2188 
2190  {
2191  return delayRewiring_;
2192  }
2193 
2194 
2195 
2197  {
2198  if (useJit == true)
2199  {
2200  OMPL_WARN("%s: Just-in-time sampling is experimental and currently only implemented for problems seeking to minimize path-length.", Planner::getName().c_str());
2201 
2202  //Assert that this the r-disc connection scheme
2203  if (useKNearest_ == true)
2204  {
2205  throw ompl::Exception("JIT sampling does not work with the k-nearest variant of BIT*.");
2206  }
2207  }
2208 
2209  //Store
2210  useJustInTimeSampling_ = useJit;
2211  }
2212 
2213 
2214 
2216  {
2217  return useJustInTimeSampling_;
2218  }
2219 
2220 
2221 
2222  void BITstar::setDropSamplesOnPrune(bool dropSamples)
2223  {
2224  //If we're turning the function on, make sure the number of uniform states is up to date.
2225  if (dropSamples == true && dropSamplesOnPrune_ == false)
2226  {
2227  //Start at 0
2228  numUniformStates_ = 0u;
2229 
2230  //Add vertices and samples, if they exist
2231  if (static_cast<bool>(vertexNN_) == true)
2232  {
2234  }
2235  if (static_cast<bool>(freeStateNN_) == true)
2236  {
2238  }
2239 
2240  //Remove starts and goals if this won't make us negative. This protects against the case where the problem is setup with starts/goals but not started yet
2241  if (numUniformStates_ >= (startVertices_.size() + goalVertices_.size()))
2242  {
2244  }
2245  }
2246 
2247  dropSamplesOnPrune_ = dropSamples;
2248  }
2249 
2250 
2251 
2253  {
2254  return dropSamplesOnPrune_;
2255  }
2256 
2257 
2258 
2259  void BITstar::setStopOnSolnImprovement(bool stopOnChange)
2260  {
2261  stopOnSolnChange_ = stopOnChange;
2262  }
2263 
2264 
2265 
2267  {
2268  return stopOnSolnChange_;
2269  }
2270 
2271 
2272 
2274  {
2275  return bestCost_;
2276  }
2277 
2278 
2279 
2281  {
2282  return std::to_string(this->bestCost().value());
2283  }
2284 
2285 
2286 
2288  {
2289  return std::to_string(bestLength_);
2290  }
2291 
2292 
2293 
2295  {
2296  return std::to_string(freeStateNN_->size());
2297  }
2298 
2299 
2300 
2302  {
2303  return std::to_string(vertexNN_->size());
2304  }
2305 
2306 
2307 
2309  {
2310  return std::to_string(intQueue_->numVertices());
2311  }
2312 
2313 
2314 
2316  {
2317  return std::to_string(intQueue_->numEdges());
2318  }
2319 
2320 
2321 
2322  unsigned int BITstar::numIterations() const
2323  {
2324  return numIterations_;
2325  }
2326 
2327 
2328 
2330  {
2331  return std::to_string(this->numIterations());
2332  }
2333 
2334 
2335 
2336  unsigned int BITstar::numBatches() const
2337  {
2338  return numBatches_;
2339  }
2340 
2341 
2342 
2344  {
2345  return std::to_string(this->numBatches());
2346  }
2347 
2348 
2349 
2351  {
2352  return std::to_string(numPrunings_);
2353  }
2354 
2355 
2356 
2358  {
2359  return std::to_string(numSamples_);
2360  }
2361 
2362 
2363 
2365  {
2366  return std::to_string(numVertices_);
2367  }
2368 
2369 
2370 
2372  {
2373  return std::to_string(numFreeStatesPruned_);
2374  }
2375 
2376 
2377 
2379  {
2380  return std::to_string(numVerticesDisconnected_);
2381  }
2382 
2383 
2384 
2386  {
2387  return std::to_string(numRewirings_);
2388  }
2389 
2390 
2391 
2393  {
2394  return std::to_string(numStateCollisionChecks_);
2395  }
2396 
2397 
2398 
2400  {
2401  return std::to_string(numEdgeCollisionChecks_);
2402  }
2403 
2404 
2405 
2407  {
2408  return std::to_string(numNearestNeighbours_);
2409  }
2410 
2411 
2412 
2414  {
2415  return std::to_string(numEdgesProcessed_);
2416  }
2418  }//geometric
2419 }//ompl
void publishSolution()
Publish the found solution to the ProblemDefinition.
Definition: BITstar.cpp:976
unsigned int numEdgeCollisionChecks_
The number of edge collision checks. Accessible via edgeCollisionCheckProgressProperty.
Definition: BITstar.h:631
VertexPtrNNPtr freeStateNN_
The unconnected samples as a nearest-neighbours datastructure. Sorted by nnDistance. Size accessible via currentFreeProgressProperty.
Definition: BITstar.h:543
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
double k_rgg_
The minimum k-nearest RGG connection term. Only a function of state dimension, so can be calculated o...
Definition: BITstar.h:564
unsigned int getSamplesPerBatch() const
Get the number of samplers per batch.
Definition: BITstar.cpp:2069
void updateSamples(const VertexConstPtr &vertex)
Update the list of free samples.
Definition: BITstar.cpp:811
unsigned int numVerticesDisconnected_
The number of graph vertices that get disconnected. These either return to being free samples or are ...
Definition: BITstar.h:622
std::list< VertexPtr > startVertices_
The start states of the problem as vertices.
Definition: BITstar.h:528
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Definition: PlannerData.h:163
virtual ~BITstar()
Destruct!
Definition: BITstar.cpp:185
ompl::base::OptimizationObjectivePtr opt_
Optimization objective copied from ProblemDefinition.
Definition: BITstar.h:525
bool useJustInTimeSampling_
Whether to use just-in-time sampling (param)
Definition: BITstar.h:664
std::string bestCostProgressProperty() const
Retrieve the best exact-solution cost found as a planner-progress property. (bestCost_) ...
Definition: BITstar.cpp:2280
void setNearestNeighbors()
Set a different nearest neighbours datastructure.
Definition: BITstar.cpp:587
void setApproximate(double difference)
Specify that the solution is approximate and set the difference to the goal.
ompl::base::Cost costToComeHeuristic(const VertexConstPtr &vertex) const
Calculate a heuristic estimate of the cost-to-come for a Vertex.
Definition: BITstar.cpp:1703
unsigned int numNearestNeighbours_
The number of nearest neighbour calls. Accessible via nearestNeighbourProgressProperty.
Definition: BITstar.h:634
void dropSample(VertexPtr oldSample)
Actually remove a sample from its NN struct.
Definition: BITstar.cpp:1377
void log(const char *file, int line, LogLevel level, const char *m,...)
Root level logging function. This should not be invoked directly, but rather used via a logging macro...
Definition: Console.cpp:120
ompl::base::Cost bestCost() const
Retrieve the best exact-solution cost found.
Definition: BITstar.cpp:2273
unsigned int numIterations() const
Get the number of iterations completed.
Definition: BITstar.cpp:2322
ompl::base::InformedSamplerPtr sampler_
State sampler.
Definition: BITstar.h:522
bool optimized_
True if the solution was optimized to meet the specified optimization criterion.
std::list< VertexPtr > prunedGoalVertices_
Any goal states of the problem that have been pruned.
Definition: BITstar.h:537
bool stopLoop_
A manual stop on the solve loop.
Definition: BITstar.h:591
double r_
The current r-disc RGG connection radius.
Definition: BITstar.h:561
unsigned int numPrunings_
The number of times the graph/samples have been pruned. Accessible via pruningProgressProperty.
Definition: BITstar.h:610
Representation of a solution to a planning problem.
ompl::base::Cost lowerBoundHeuristicEdge(const VertexConstPtrPair &edgePair) const
Calculates a heuristic estimate of the cost of a solution constrained to go through an edge...
Definition: BITstar.cpp:1682
unsigned int numIterations_
The number of iterations run. Accessible via iterationProgressProperty.
Definition: BITstar.h:604
std::string verticesConstructedProgressProperty() const
Retrieve the total number of vertices added to the graph as a planner-progress property. (numVertices_)
Definition: BITstar.cpp:2364
void setKNearest(bool useKNearest)
Enable a k-nearest search for instead of an r-disc search.
Definition: BITstar.cpp:2076
bool getStrictQueueOrdering() const
Get whether strict queue ordering is in use.
Definition: BITstar.cpp:2131
std::string verticesDisconnectedProgressProperty() const
Retrieve the number of graph vertices that are disconnected and either returned to the set of free sa...
Definition: BITstar.cpp:2378
IntegratedQueuePtr intQueue_
The integrated queue of vertices to expand and edges to process ordered on "f-value", i.e., estimated solution cost. Remaining vertex queue "size" and edge queue size are accessible via vertexQueueSizeProgressProperty and edgeQueueSizeProgressProperty, respectively.
Definition: BITstar.h:549
unsigned int nearestVertices(const VertexPtr &vertex, std::vector< VertexPtr > *neighbourVertices)
Get the nearest samples from the vertexNN_ using the appropriate "near" definition (i...
Definition: BITstar.cpp:1633
virtual bool prune()
Prune the problem. Returns true if pruning was done.
Definition: BITstar.cpp:890
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
bool isCostWorseThanOrEquivalentTo(const ompl::base::Cost &a, const ompl::base::Cost &b) const
Compare whether cost a is worse or equivalent to cost b by checking that a is not better than b...
Definition: BITstar.cpp:1793
std::shared_ptr< NearestNeighbors< VertexPtr > > VertexPtrNNPtr
The OMPL::NearestNeighbors structure.
Definition: BITstar.h:137
virtual void iterate()
A single iteration.
Definition: BITstar.cpp:672
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...
bool hasSolution_
If we&#39;ve found a solution yet.
Definition: BITstar.h:588
bool getPruning() const
Get whether graph and sample pruning is in use.
Definition: BITstar.cpp:2150
virtual std::string totalStatesCreatedProgressProperty() const
Retrieve the total number of states generated as a planner-progress property. (numSamples_) ...
Definition: BITstar.cpp:2357
std::string edgeCollisionCheckProgressProperty() const
Retrieve the number of edge (or motion) collision checks (i.e., calls to SpaceInformation::checkMotio...
Definition: BITstar.cpp:2399
ompl::base::Cost costToGoHeuristic(const VertexConstPtr &vertex) const
Calculate a heuristic estimate of the cost-to-go for a Vertex.
Definition: BITstar.cpp:1729
bool checkEdge(const VertexConstPtrPair &edge)
Checks an edge for collision. A wrapper to SpaceInformation->checkMotion that tracks number of collis...
Definition: BITstar.cpp:1369
ompl::base::Cost minCost_
The minimum possible solution cost. I.e., the heuristic value of the goal.
Definition: BITstar.h:582
unsigned int nearestSamples(const VertexPtr &vertex, std::vector< VertexPtr > *neighbourSamples)
Get the nearest samples from the freeStateNN_ using the appropriate "near" definition (i...
Definition: BITstar.cpp:1611
double minimumRggR() const
Calculate the lower-bounding radius RGG term for asymptotic almost-sure convergence to the optimal pa...
Definition: BITstar.cpp:1919
std::string vertexQueueSizeProgressProperty() const
Retrieve the current number of vertices in the expansion queue as a planner-progress property...
Definition: BITstar.cpp:2308
bool usePruning_
Whether to use graph pruning (param)
Definition: BITstar.h:655
virtual void getPlannerData(base::PlannerData &data) const
Get results.
Definition: BITstar.cpp:450
void pruneStartsGoals()
Prune the starts and goals that have a solution heuristic that is not less than bestCost_.
Definition: BITstar.cpp:1238
std::string currentFreeProgressProperty() const
Retrieve the current number of free samples as a planner-progress property. (size of freeStateNN_) ...
Definition: BITstar.cpp:2294
bool isCostNotEquivalentTo(const ompl::base::Cost &a, const ompl::base::Cost &b) const
Compare whether cost a and cost b are not equivalent by checking if either a or b is better than the ...
Definition: BITstar.cpp:1777
unsigned int bestLength_
The number of vertices in the best solution found to date. Accessible via bestLengthProgressProperty...
Definition: BITstar.h:573
void updateStartAndGoalStates(const base::PlannerTerminationCondition &ptc)
Adds any new goals or starts that have appeared in the problem definition to the list of vertices and...
Definition: BITstar.cpp:1043
virtual void endSuccessMessage() const
The message printed when solve finishes successfully.
Definition: BITstar.cpp:1952
unsigned int numBatches() const
Retrieve the number of batches processed as the raw data. (numBatches_)
Definition: BITstar.cpp:2336
void setDelayRewiringUntilInitialSolution(bool delayRewiring)
Delay the consideration of rewiring edges until an initial solution is found. When multiple batches a...
Definition: BITstar.cpp:2176
double fractionalChange(const ompl::base::Cost &newCost, const ompl::base::Cost &oldCost) const
Calculate the fractional change of cost "newCost" from "oldCost" relative to "oldCost", i.e., (newCost - oldCost)/oldCost.
Definition: BITstar.cpp:1815
double unitNBallMeasure(unsigned int N)
The Lebesgue measure (i.e., "volume") of an n-dimensional ball with a unit radius.
PlannerTerminationCondition plannerAlwaysTerminatingCondition()
Simple termination condition that always returns true. The termination condition will always be met...
void estimateMeasures()
A debug function: Estimate the measure of the free/obstace space via sampling.
Definition: BITstar.cpp:607
bool getJustInTimeSampling() const
Get whether we&#39;re using just-in-time sampling.
Definition: BITstar.cpp:2215
double approximateDiff_
The distance of the approximate solution, set to -1.0 for non approximate solutions.
Definition: BITstar.h:601
unsigned int numUniformStates_
The number of states (vertices or samples) that were generated from a uniform distribution. Only valid when refreshSamplesOnPrune_ is true, in which case it&#39;s used to calculate the RGG term of the uniform subgraph.
Definition: BITstar.h:558
std::shared_ptr< const Vertex > VertexConstPtr
A constant vertex shared pointer.
Definition: BITstar.h:125
double uniform01()
Generate a random real between 0 and 1.
Definition: RandomNumbers.h:69
virtual bool resort()
Resort the queue. Returns true if any pruning was done.
Definition: BITstar.cpp:948
BITstar(const base::SpaceInformationPtr &si, const std::string &name="BITstar")
Construct!
Definition: BITstar.cpp:74
void setSamplesPerBatch(unsigned int n)
Set the number of samplers per batch.
Definition: BITstar.cpp:2062
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition: PlannerData.h:59
void setStrictQueueOrdering(bool beStrict)
Enable "strict sorting" of the edge queue. Rewirings can change the position in the queue of an edge...
Definition: BITstar.cpp:2124
unsigned int numFreeStatesPruned_
The number of free states that have been pruned. Accessible via statesPrunedProgressProperty.
Definition: BITstar.h:619
Main namespace. Contains everything in this library.
Definition: Cost.h:42
virtual void updateNearestTerms()
Update the appropriate nearest-neighbour terms, r_ and k_. Performs this calculation considering the ...
Definition: BITstar.cpp:1850
bool isCostBetterThanOrEquivalentTo(const ompl::base::Cost &a, const ompl::base::Cost &b) const
Compare whether cost a is better or equivalent to cost b by checking that b is not better than a...
Definition: BITstar.cpp:1785
void getEdgeQueue(std::vector< std::pair< VertexConstPtr, VertexConstPtr > > *edgesInQueue)
Get the whole messy set of edges in the queue. Expensive but helpful for some videos.
Definition: BITstar.cpp:572
std::string bestLengthProgressProperty() const
Retrieve the length of the best exact-solution found as a planner-progress property. (bestLength_)
Definition: BITstar.cpp:2287
double rewireFactor_
The rewiring factor, s, so that r_rrg = s r_rrg* > r_rrg* (param)
Definition: BITstar.h:646
ompl::base::Cost getNextEdgeValueInQueue()
Get the value of the next edge to be processed. Causes vertices in the queue to be expanded (if neces...
Definition: BITstar.cpp:543
std::string nearestNeighbourProgressProperty() const
Retrieve the number of nearest neighbour calls (i.e., NearestNeighbors<T>::nearestK(...) or NearestNeighbors<T>::nearestR(...)) as a planner-progress property. (numNearestNeighbours_)
Definition: BITstar.cpp:2406
std::vector< const ompl::base::State * > bestPathFromGoalToStart() const
Extract the best solution, ordered from the goal to the start and including both the goal and the sta...
Definition: BITstar.cpp:1017
bool approximateSoln_
If the solution is approximate.
Definition: BITstar.h:598
double getRewireFactor() const
Get the rewiring scale factor.
Definition: BITstar.cpp:2055
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
std::vector< VertexPtr > recycledSamples_
A copy of the vertices recycled into samples during this batch.
Definition: BITstar.h:555
bool getKNearest() const
Get whether a k-nearest search is being used.
Definition: BITstar.cpp:2118
double minimumRggK() const
Calculate the lower-bounding k-nearest RGG term for asymptotic almost-sure convergence to the optimal...
Definition: BITstar.cpp:1933
VertexPtr curGoalVertex_
The goal vertex of the current best solution.
Definition: BITstar.h:540
std::vector< VertexPtr > newSamples_
A copy of the new samples from this batch.
Definition: BITstar.h:552
double nnDistance(const VertexConstPtr &a, const VertexConstPtr &b) const
The distance function used for nearest neighbours. Calculates the distance directionally from the giv...
Definition: BITstar.cpp:1652
std::pair< VertexConstPtr, VertexConstPtr > VertexConstPtrPair
A pair of const vertices, i.e., an edge.
Definition: BITstar.h:135
LogLevel getLogLevel()
Retrieve the current level of logging data. Messages with lower logging levels will not be recorded...
Definition: Console.cpp:142
bool delayRewiring_
Whether to delay rewiring until a solution is found (param)
Definition: BITstar.h:661
unsigned int numEdgesProcessed_
The number of edges processed, in one way or other, from the queue. Accessible via edgesProcessedProg...
Definition: BITstar.h:637
unsigned int numSamples_
The number of states generated through sampling. Accessible via statesFromSamplingProgressProperty.
Definition: BITstar.h:613
double value() const
The value of the cost.
Definition: Cost.h:54
void addSample(const VertexPtr &newSample)
Add a sample.
Definition: BITstar.cpp:1570
virtual void setup()
Setup.
Definition: BITstar.cpp:191
void updateGoalVertex()
The special work that needs to be done to update the goal vertex is the solution has changed...
Definition: BITstar.cpp:1468
ompl::base::Cost currentHeuristicEdgeTarget(const VertexConstPtrPair &edgePair) const
Calculates a heuristic estimate of the cost of a path to the target of an edge, dependent on the cost...
Definition: BITstar.cpp:1696
ompl::base::Cost trueEdgeCost(const VertexConstPtrPair &edgePair) const
The true cost of an edge, including collisions.
Definition: BITstar.cpp:1747
std::pair< const ompl::base::State *, const ompl::base::State * > getNextEdgeInQueue()
Get the next edge to be processed. Causes vertices in the queue to be expanded (if necessary) and the...
Definition: BITstar.cpp:514
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...
ompl::base::Cost costSampled_
The total-heuristic cost up to which we&#39;ve sampled.
Definition: BITstar.h:585
A shared pointer wrapper for ompl::base::SpaceInformation.
std::string statesPrunedProgressProperty() const
Retrieve the number of states pruned from the problem as a planner-progress property. (numFreeStatesPruned_)
Definition: BITstar.cpp:2371
ompl::base::Cost lowerBoundHeuristicVertex(const VertexConstPtr &vertex) const
Calculates a heuristic estimate of the cost of a solution constrained to pass through a vertex...
Definition: BITstar.cpp:1669
bool stopOnSolnChange_
Whether to stop the planner as soon as the path changes (param)
Definition: BITstar.h:670
bool getStopOnSolnImprovement() const
Get whether BIT* stops each time a solution is found.
Definition: BITstar.cpp:2266
void setRewireFactor(double rewireFactor)
Set the rewiring scale factor, s, such that r_rrg = s r_rrg*.
Definition: BITstar.cpp:2041
std::string stateCollisionCheckProgressProperty() const
Retrieve the number of state collisions checks (i.e., calls to SpaceInformation::isValid(...)) as a planner-progress property. (numStateCollisionChecks_)
Definition: BITstar.cpp:2392
void setPruneThresholdFraction(double fractionalChange)
Set the fractional change in the solution cost necessary for pruning to occur.
Definition: BITstar.cpp:2157
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
ompl::RNG rng_
An instance of a random number generator.
Definition: BITstar.h:519
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
Definition: Console.h:66
std::pair< VertexPtr, VertexPtr > VertexPtrPair
A pair of vertices, i.e., an edge.
Definition: BITstar.h:133
virtual void clear()
Clear.
Definition: BITstar.cpp:324
std::string batchesProgressProperty() const
Retrieve the number of batches processed as a planner-progress property. (numBatches_) ...
Definition: BITstar.cpp:2343
bool getDropSamplesOnPrune() const
Get whether unconnected samples are dropped on pruning.
Definition: BITstar.cpp:2252
bool useKNearest_
Option to use k-nearest search for rewiring (param)
Definition: BITstar.h:652
void setJustInTimeSampling(bool useJit)
Delay the generation of samples until they are necessary. This only works when using an r-disc connec...
Definition: BITstar.cpp:2196
The exception type for ompl.
Definition: Exception.h:47
ompl::base::Cost currentHeuristicEdge(const VertexConstPtrPair &edgePair) const
Calculates a heuristic estimate of the cost of a solution constrained to go through an edge...
Definition: BITstar.cpp:1689
VertexPtrNNPtr vertexNN_
The vertices as a nearest-neighbours data structure. Sorted by nnDistance. Size accessible via curren...
Definition: BITstar.h:546
#define OMPL_DEBUG(fmt,...)
Log a formatted debugging string.
Definition: Console.h:70
bool dropSamplesOnPrune_
Whether to refresh (i.e., forget) unconnected samples on pruning (param)
Definition: BITstar.h:667
bool useStrictQueueOrdering_
Whether to use a strict-queue ordering (param)
Definition: BITstar.h:643
base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
Solve.
Definition: BITstar.cpp:413
std::list< VertexPtr > goalVertices_
The goal states of the problem as vertices.
Definition: BITstar.h:531
unsigned int numRewirings_
The number of times a state in the graph was rewired. Accessible via rewiringProgressProperty.
Definition: BITstar.h:625
void addVertex(const VertexPtr &newVertex, const bool &removeFromFree)
Add a vertex to the graph.
Definition: BITstar.cpp:1584
unsigned int numVertices_
The number of vertices ever added to the graph. Will count vertices twice if they spend any time disc...
Definition: BITstar.h:616
void pruneSamples()
Prune all samples with a solution heuristic that is not less than the bestCost_.
Definition: BITstar.cpp:1330
ompl::base::Cost currentHeuristicVertex(const VertexConstPtr &vertex) const
Calculates a heuristic estimate of the cost of a solution constrained to pass through a vertex...
Definition: BITstar.cpp:1676
void newBatch()
Initialize variables for a new batch.
Definition: BITstar.cpp:763
unsigned int k_
The current k-nearest RGG connection number.
Definition: BITstar.h:567
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.
double calculateR(unsigned int N) const
Calculate the r for r-disc nearest neighbours, a function of the current graph.
Definition: BITstar.cpp:1897
ompl::base::Cost prunedCost_
The cost to which the graph has been pruned. We will only prune the graph if bestCost_ is less than t...
Definition: BITstar.h:576
bool isCostWorseThan(const ompl::base::Cost &a, const ompl::base::Cost &b) const
Compare whether cost a is worse than cost b by checking whether b is better than a.
Definition: BITstar.cpp:1769
void getVertexQueue(std::vector< VertexConstPtr > *verticesInQueue)
Get the whole set of vertices to be expanded. Expensive but helpful for some videos.
Definition: BITstar.cpp:579
ompl::base::Cost combineCosts(const ompl::base::Cost &a, const ompl::base::Cost &b, const ompl::base::Cost &c) const
Combine 3 costs.
Definition: BITstar.cpp:1801
std::string edgeQueueSizeProgressProperty() const
Retrieve the current number of edges in the search queue as a planner-progress property. (The size of the edge subqueue of intQueue_)
Definition: BITstar.cpp:2315
unsigned int numBatches_
The number of batches processed. Accessible via batchesProgressProperty.
Definition: BITstar.h:607
ompl::base::Cost neighbourhoodCost(const VertexConstPtr &vertex) const
Calculate the max req&#39;d cost to define a neighbourhood around a state. Currently only implemented for...
Definition: BITstar.cpp:1754
virtual void statusMessage(const ompl::msg::LogLevel &msgLevel, const std::string &status) const
A debug-level status message for debugging.
Definition: BITstar.cpp:1966
void addEdge(const VertexPtrPair &newEdge, const ompl::base::Cost &edgeCost, const bool &removeFromFree, const bool &updateDescendants)
Add an edge from the edge queue to the tree. Will add the state to the vertex queue if it&#39;s new to th...
Definition: BITstar.cpp:1391
virtual void endFailureMessage() const
The message printed when solve finishes unsuccessfully.
Definition: BITstar.cpp:1959
std::string edgesProcessedProgressProperty() const
Retrieve the total number of edges processed from the queue as a planner-progress property...
Definition: BITstar.cpp:2413
void setDropSamplesOnPrune(bool dropSamples)
Drop all unconnected samples when pruning, regardless of their heuristic value. This provides a metho...
Definition: BITstar.cpp:2222
double prunedMeasure_
The measure of the problem domain when we pruned the graph.
Definition: BITstar.h:579
void setPruning(bool prune)
Enable pruning of vertices/samples that CANNOT improve the current solution. When a vertex in the gra...
Definition: BITstar.cpp:2138
SpaceInformationPtr si_
The space information for which planning is done.
Definition: Planner.h:398
std::string iterationProgressProperty() const
Retrieve the number of iterations as a planner-progress property. (numIterations_) ...
Definition: BITstar.cpp:2329
std::string pruningProgressProperty() const
Retrieve the number of graph prunings performed as a planner-progress property. (numPrunings_) ...
Definition: BITstar.cpp:2350
void initializeNearestTerms()
Initialize the nearest-neighbour terms.
Definition: BITstar.cpp:1839
std::shared_ptr< Vertex > VertexPtr
A vertex shared pointer.
Definition: BITstar.h:120
bool getDelayRewiringUntilInitialSolution() const
Get whether BIT* is delaying rewiring until a solution is found.
Definition: BITstar.cpp:2189
double getPruneThresholdFraction() const
Get the fractional change in the solution cost necessary for pruning to occur.
Definition: BITstar.cpp:2169
std::list< VertexPtr > prunedStartVertices_
Any start states of the problem that have been pruned.
Definition: BITstar.h:534
LogLevel
The set of priorities for message logging.
Definition: Console.h:85
double pruneFraction_
The fractional decrease in solution cost required to trigger pruning (param)
Definition: BITstar.h:658
ompl::base::Cost bestCost_
The best cost found to date. This is the maximum total-heuristic cost of samples we&#39;ll consider...
Definition: BITstar.h:570
unsigned int samplesPerBatch_
The number of samples per batch (param)
Definition: BITstar.h:649
std::string rewiringProgressProperty() const
Retrieve the number of global-search edges that rewired the graph as a planner-progress property...
Definition: BITstar.cpp:2385
void replaceParent(const VertexPtrPair &newEdge, const ompl::base::Cost &edgeCost, const bool &updateDescendants)
Replace the parent edge with the given new edge and cost.
Definition: BITstar.cpp:1434
std::string currentVertexProgressProperty() const
Retrieve the current number of vertices in the graph as a planner-progress property. (Size of vertexNN_)
Definition: BITstar.cpp:2301
unsigned int calculateK(unsigned int N) const
Calculate the k for k-nearest neighours, a function of the current graph.
Definition: BITstar.cpp:1911
void setPlannerName(const std::string &name)
Set the name of the planner used to compute this solution.
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition: Cost.h:47
ompl::base::Cost edgeCostHeuristic(const VertexConstPtrPair &edgePair) const
Calculate a heuristic estimate of the cost an edge between two Vertices.
Definition: BITstar.cpp:1722
bool isSetup() const
Check if setup() was called for this planner.
Definition: Planner.cpp:107
void setStopOnSolnImprovement(bool stopOnChange)
Stop the planner each time a solution improvement is found. Useful for examining the intermediate sol...
Definition: BITstar.cpp:2259
unsigned int numStateCollisionChecks_
The number of state collision checks. Accessible via stateCollisionCheckProgressProperty.
Definition: BITstar.h:628
virtual void goalMessage() const
The message printed when a goal is found/improved.
Definition: BITstar.cpp:1945
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