Syclop.h
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Rice University
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Rice University nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 /* Author: Matt Maly */
36 
37 #ifndef OMPL_CONTROL_PLANNERS_SYCLOP_SYCLOP_
38 #define OMPL_CONTROL_PLANNERS_SYCLOP_SYCLOP_
39 
40 #include <boost/graph/astar_search.hpp>
41 #include <boost/graph/graph_traits.hpp>
42 #include <boost/graph/adjacency_list.hpp>
43 #include <unordered_map>
44 #include "ompl/control/planners/PlannerIncludes.h"
45 #include "ompl/control/planners/syclop/Decomposition.h"
46 #include "ompl/control/planners/syclop/GridDecomposition.h"
47 #include "ompl/datastructures/PDF.h"
48 #include "ompl/util/Hash.h"
49 #include <map>
50 #include <vector>
51 
52 namespace ompl
53 {
54  namespace control
55  {
71  class Syclop : public base::Planner
72  {
73  public:
89  typedef std::function<double(int, int)> EdgeCostFactorFn;
90 
92  typedef std::function<void(int, int, std::vector<int>&)> LeadComputeFn;
93 
95  Syclop(const SpaceInformationPtr& si, const DecompositionPtr &d, const std::string& plannerName) : ompl::base::Planner(si, plannerName),
96  numFreeVolSamples_(Defaults::NUM_FREEVOL_SAMPLES),
97  probShortestPath_(Defaults::PROB_SHORTEST_PATH),
98  probKeepAddingToAvail_(Defaults::PROB_KEEP_ADDING_TO_AVAIL),
99  numRegionExpansions_(Defaults::NUM_REGION_EXPANSIONS),
100  numTreeSelections_(Defaults::NUM_TREE_SELECTIONS),
101  probAbandonLeadEarly_(Defaults::PROB_ABANDON_LEAD_EARLY),
102  siC_(si.get()),
103  decomp_(d),
104  covGrid_(Defaults::COVGRID_LENGTH, decomp_),
105  graphReady_(false),
106  numMotions_(0)
107  {
109 
110  Planner::declareParam<int> ("free_volume_samples", this, &Syclop::setNumFreeVolumeSamples, &Syclop::getNumFreeVolumeSamples, "10000:10000:500000");
111  Planner::declareParam<int> ("num_region_expansions", this, &Syclop::setNumRegionExpansions, &Syclop::getNumRegionExpansions, "10:10:500");
112  Planner::declareParam<int> ("num_tree_expansions", this, &Syclop::setNumTreeExpansions, &Syclop::getNumTreeExpansions, "0:1:100");
113  Planner::declareParam<double>("prob_abandon_lead_early", this, &Syclop::setProbAbandonLeadEarly, &Syclop::getProbAbandonLeadEarly, "0.:.05:1.");
114  Planner::declareParam<double>("prob_add_available_regions", this, &Syclop::setProbAddingToAvailableRegions, &Syclop::getProbAddingToAvailableRegions, "0.:.05:1.");
115  Planner::declareParam<double>("prob_shortest_path_lead", this, &Syclop::setProbShortestPathLead, &Syclop::getProbShortestPathLead, "0.:.05:1.");
116  }
117 
118  virtual ~Syclop()
119  {
120  }
121 
124 
125  virtual void setup();
126 
127  virtual void clear();
128 
133 
136 
138  void setLeadComputeFn(const LeadComputeFn& compute);
139 
141  void addEdgeCostFactor(const EdgeCostFactorFn& factor);
142 
144  void clearEdgeCostFactors();
145 
148  {
149  return numFreeVolSamples_;
150  }
151 
154  void setNumFreeVolumeSamples (int numSamples)
155  {
156  numFreeVolSamples_ = numSamples;
157  }
158 
161  double getProbShortestPathLead () const
162  {
163  return probShortestPath_;
164  }
165 
168  void setProbShortestPathLead (double probability)
169  {
170  probShortestPath_ = probability;
171  }
172 
176  {
177  return probKeepAddingToAvail_;
178  }
179 
182  void setProbAddingToAvailableRegions (double probability)
183  {
184  probKeepAddingToAvail_ = probability;
185  }
186 
190  {
191  return numRegionExpansions_;
192  }
193 
196  void setNumRegionExpansions (int regionExpansions)
197  {
198  numRegionExpansions_ = regionExpansions;
199  }
200 
203  int getNumTreeExpansions () const
204  {
205  return numTreeSelections_;
206  }
207 
210  void setNumTreeExpansions (int treeExpansions)
211  {
212  numTreeSelections_ = treeExpansions;
213  }
214 
217  double getProbAbandonLeadEarly () const
218  {
219  return probAbandonLeadEarly_;
220  }
221 
224  void setProbAbandonLeadEarly (double probability)
225  {
226  probAbandonLeadEarly_ = probability;
227  }
229 
231  struct Defaults
232  {
233  static const int NUM_FREEVOL_SAMPLES = 100000;
234  static const int COVGRID_LENGTH = 128;
235  static const int NUM_REGION_EXPANSIONS = 100;
236  static const int NUM_TREE_SELECTIONS = 1;
237  // C++ standard prohibits non-integral static const member initialization
238  // These constants are set in Syclop.cpp. C++11 standard changes this
239  // with the constexpr keyword, but for compatibility this is not done.
240  static const double PROB_ABANDON_LEAD_EARLY /*= 0.25*/;
241  static const double PROB_KEEP_ADDING_TO_AVAIL /*= 0.50*/;
242  static const double PROB_SHORTEST_PATH /*= 0.95*/;
243  };
244 
245  protected:
246 
247  #pragma pack(push, 4) // push default byte alignment to stack and align the following structure to 4 byte boundary
248 
252  class Motion
253  {
254  public:
255  Motion() : state(nullptr), control(nullptr), parent(nullptr), steps(0)
256  {
257  }
259  Motion(const SpaceInformation *si) : state(si->allocState()), control(si->allocControl()), parent(nullptr), steps(0)
260  {
261  }
262  virtual ~Motion()
263  {
264  }
270  const Motion *parent;
272  unsigned int steps;
273  };
274  #pragma pack (pop) // Restoring default byte alignment
275 
276  #pragma pack(push, 4) // push default byte alignment to stack and align the following structure to 4 byte boundary
277 
278  class Region
279  {
280  public:
281  Region()
282  {
283  }
284  virtual ~Region()
285  {
286  }
287 
288 #if __cplusplus >= 201103L
289  Region(const Region&) = default;
290  Region& operator=(const Region&) = default;
291  Region(Region&&) = default;
292  Region& operator=(Region&&) = default;
293 #endif
294 
296  void clear()
297  {
298  motions.clear();
299  covGridCells.clear();
300  pdfElem = nullptr;
301  }
302 
304  std::set<int> covGridCells;
306  std::vector<Motion*> motions;
308  double volume;
310  double freeVolume;
314  double weight;
316  double alpha;
318  int index;
320  unsigned int numSelections;
323  };
324  #pragma pack (pop) // Restoring default byte alignment
325 
326  #pragma pack(push, 4) // push default byte alignment to stack and align the following structure to 4 byte boundary
327 
329  class Adjacency
330  {
331  public:
332  Adjacency()
333  {
334  }
335  virtual ~Adjacency()
336  {
337  }
339  void clear()
340  {
341  covGridCells.clear();
342  }
345  std::set<int> covGridCells;
347  const Region *source;
349  const Region *target;
351  double cost;
358  bool empty;
359  };
360  #pragma pack (pop) // Restoring default byte alignment
361 
363  virtual Motion* addRoot(const base::State *s) = 0;
364 
367  virtual void selectAndExtend(Region &region, std::vector<Motion*>& newMotions) = 0;
368 
370  inline const Region& getRegionFromIndex(const int rid) const
371  {
372  return graph_[boost::vertex(rid,graph_)];
373  }
374 
377 
380 
383 
386 
389 
392 
395 
398 
401 
402  private:
404 
405  struct HashRegionPair
406  {
407  size_t operator()(const std::pair<int,int> &p) const
408  {
409  std::size_t hash = std::hash<int>()(p.first);
410  hash_combine(hash, p.second);
411  return hash;
412  }
413  };
415 
416 
419  class CoverageGrid : public GridDecomposition
420  {
421  public:
422  CoverageGrid(const int len, const DecompositionPtr& d) : GridDecomposition(len, d->getDimension(), d->getBounds()), decomp(d)
423  {
424  }
425 
426  virtual ~CoverageGrid()
427  {
428  }
429 
432  virtual void project(const base::State *s, std::vector<double>& coord) const
433  {
434  decomp->project(s, coord);
435  }
436 
438  virtual void sampleFullState(const base::StateSamplerPtr& /*sampler*/, const std::vector<double>& /*coord*/, base::State* /*s*/) const
439  {
440  }
441 
442  protected:
443  const DecompositionPtr& decomp;
444  };
445 
446  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Region, Adjacency> RegionGraph;
447  typedef boost::graph_traits<RegionGraph>::vertex_descriptor Vertex;
448  typedef boost::graph_traits<RegionGraph>::vertex_iterator VertexIter;
449  typedef boost::property_map<RegionGraph, boost::vertex_index_t>::type VertexIndexMap;
450  typedef boost::graph_traits<RegionGraph>::edge_iterator EdgeIter;
451 
453  friend class DecompositionHeuristic;
454 
455  class DecompositionHeuristic : public boost::astar_heuristic<RegionGraph, double>
456  {
457  public:
458  DecompositionHeuristic(const Syclop *s, const Region &goal) : syclop(s), goalRegion(goal)
459  {
460  }
461 
462  double operator()(Vertex v)
463  {
464  const Region &region = syclop->getRegionFromIndex(v);
465  return region.alpha*goalRegion.alpha;
466  }
467  private:
468  const Syclop *syclop;
469  const Region &goalRegion;
470  };
471 
472  struct found_goal {};
473 
474  class GoalVisitor : public boost::default_astar_visitor
475  {
476  public:
477  GoalVisitor(const int goal) : goalRegion(goal)
478  {
479  }
480  void examine_vertex(Vertex v, const RegionGraph& /*g*/)
481  {
482  if (static_cast<int>(v) == goalRegion)
483  throw found_goal();
484  }
485  private:
486  const int goalRegion;
487  };
489 
491  class RegionSet
492  {
493  public:
494  int sampleUniform()
495  {
496  if (empty())
497  return -1;
498  return regions.sample(rng.uniform01());
499  }
500  void insert(const int r)
501  {
502  if (regToElem.count(r) == 0)
503  regToElem[r] = regions.add(r, 1);
504  else
505  {
506  PDF<int>::Element *elem = regToElem[r];
507  regions.update(elem, regions.getWeight(elem)+1);
508  }
509  }
510  void clear()
511  {
512  regions.clear();
513  regToElem.clear();
514  }
515  std::size_t size() const
516  {
517  return regions.size();
518  }
519  bool empty() const
520  {
521  return regions.empty();
522  }
523  private:
524  RNG rng;
525  PDF<int> regions;
526  std::unordered_map<int, PDF<int>::Element*> regToElem;
527  };
529 
531  void initRegion(Region &r);
532 
534  void setupRegionEstimates();
535 
537  void updateRegion(Region &r);
538 
540  void initEdge(Adjacency &a, const Region *source, const Region *target);
541 
543  void setupEdgeEstimates();
544 
546  void updateEdge(Adjacency &a);
547 
550  bool updateCoverageEstimate(Region &r, const base::State *s);
551 
554  bool updateConnectionEstimate(const Region &c, const Region &d, const base::State *s);
555 
558  void buildGraph();
559 
561  void clearGraphDetails();
562 
564  int selectRegion();
565 
567  void computeAvailableRegions();
568 
570  void defaultComputeLead(int startRegion, int goalRegion, std::vector<int>& lead);
571 
573  double defaultEdgeCost(int r, int s);
574 
576  LeadComputeFn leadComputeFn;
578  std::vector<int> lead_;
580  PDF<int> availDist_;
582  std::vector<EdgeCostFactorFn> edgeCostFactors_;
584  CoverageGrid covGrid_;
586  RegionGraph graph_;
588  bool graphReady_;
590  std::unordered_map<std::pair<int,int>, Adjacency*, HashRegionPair> regionsToEdge_;
592  unsigned int numMotions_;
594  RegionSet startRegions_;
596  RegionSet goalRegions_;
597  };
598  }
599 }
600 
601 #endif
bool approximateSolutions
Flag indicating whether the planner is able to compute approximate solutions.
Definition: Planner.h:212
Synergistic Combination of Layers of Planning.
Definition: Syclop.h:71
virtual void setup()
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
Definition: Syclop.cpp:48
double alpha
The coefficient contributed by this region to edge weights in lead computations.
Definition: Syclop.h:316
base::State * state
The state contained by the motion.
Definition: Syclop.h:266
Representation of an adjacency (a directed edge) between two regions in the Decomposition assigned to...
Definition: Syclop.h:329
std::set< int > covGridCells
The cells of the underlying coverage grid that contain tree motions from this region.
Definition: Syclop.h:304
int numLeadInclusions
The number of times this adjacency has been included in a lead.
Definition: Syclop.h:353
int numSelections
The number of times the low-level tree planner has selected motions from the source region when attem...
Definition: Syclop.h:356
Definition of an abstract control.
Definition: Control.h:48
int index
The index of the graph node corresponding to this region.
Definition: Syclop.h:318
RNG rng_
Random number generator.
Definition: Syclop.h:400
PDF< int >::Element * pdfElem
The Element corresponding to this region in the PDF of available regions.
Definition: Syclop.h:322
double volume
The volume of this region.
Definition: Syclop.h:308
Representation of a region in the Decomposition assigned to Syclop.
Definition: Syclop.h:278
std::function< void(int, int, std::vector< int > &)> LeadComputeFn
Leads should consist of a path of adjacent regions in the decomposition that start with the start reg...
Definition: Syclop.h:92
int getNumTreeExpansions() const
Get the number of calls to selectAndExtend() in the low-level tree planner for a given lead and regio...
Definition: Syclop.h:203
Motion(const SpaceInformation *si)
Constructor that allocates memory for the state and the control.
Definition: Syclop.h:259
std::vector< Motion * > motions
The tree motions contained in this region.
Definition: Syclop.h:306
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
double getProbAbandonLeadEarly() const
Get the probability [0,1] that a lead will be abandoned early, before a new region is chosen for expa...
Definition: Syclop.h:217
const SpaceInformation * siC_
Handle to the control::SpaceInformation object.
Definition: Syclop.h:394
DecompositionPtr decomp_
The high level decomposition used to focus tree expansion.
Definition: Syclop.h:397
A GridDecomposition is a Decomposition implemented using a grid.
Representation of a motion.
Definition: Syclop.h:252
int numTreeSelections_
The number of calls to selectAndExtend() in the low-level tree planner for a given lead and region...
Definition: Syclop.h:388
Control * control
The control contained by the motion.
Definition: Syclop.h:268
void clear()
Clears motions and coverage information from this region.
Definition: Syclop.h:296
double getProbShortestPathLead() const
Get the probability [0,1] that a lead will be computed as a shortest-path instead of a random-DFS...
Definition: Syclop.h:161
int numRegionExpansions_
The number of times a new region will be chosen and promoted for expansion from a given lead...
Definition: Syclop.h:385
virtual void clear()
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
Definition: Syclop.cpp:59
A container that supports probabilistic sampling over weighted data.
Definition: PDF.h:48
void clearEdgeCostFactors()
Clears all edge cost factors, making all edge weights equivalent to 1.
Definition: Syclop.cpp:223
const Region & getRegionFromIndex(const int rid) const
Returns a reference to the Region object with the given index. Assumes the index is valid...
Definition: Syclop.h:370
virtual base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
Continues solving until a solution is found or a given planner termination condition is met...
Definition: Syclop.cpp:70
Syclop(const SpaceInformationPtr &si, const DecompositionPtr &d, const std::string &plannerName)
Constructor. Requires a Decomposition, which Syclop uses to create high-level leads.
Definition: Syclop.h:95
Random number generation. An instance of this class cannot be used by multiple threads at once (membe...
Definition: RandomNumbers.h:58
Base class for a planner.
Definition: Planner.h:230
void addEdgeCostFactor(const EdgeCostFactorFn &factor)
Adds an edge cost factor to be used for edge weights between adjacent regions.
Definition: Syclop.cpp:218
bool empty
This value is true if and only if this adjacency's source and target regions both contain zero tree m...
Definition: Syclop.h:358
std::set< int > covGridCells
The cells of the underlying coverage grid that contain tree motions originating from direct connectio...
Definition: Syclop.h:345
const Region * source
The source region of this adjacency edge.
Definition: Syclop.h:347
std::function< double(int, int)> EdgeCostFactorFn
Each edge weight between two adjacent regions in the Decomposition is defined as a product of edge co...
Definition: Syclop.h:89
void setProbAbandonLeadEarly(double probability)
The probability that a lead will be abandoned early, before a new region is chosen for expansion...
Definition: Syclop.h:224
double cost
The cost of this adjacency edge, used in lead computations.
Definition: Syclop.h:351
A class to store the exit status of Planner::solve()
Definition: PlannerStatus.h:48
const Region * target
The target region of this adjacency edge.
Definition: Syclop.h:349
Definition of an abstract state.
Definition: State.h:50
double percentValidCells
The percent of free volume of this region.
Definition: Syclop.h:312
A shared pointer wrapper for ompl::control::SpaceInformation.
virtual void project(const base::State *s, std::vector< double > &coord) const =0
Project a given State to a set of coordinates in R^k, where k is the dimension of this Decomposition...
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition: Planner.h:410
double probShortestPath_
The probability that a lead will be computed as a shortest-path instead of a random-DFS.
Definition: Syclop.h:379
Contains default values for Syclop parameters.
Definition: Syclop.h:231
void setLeadComputeFn(const LeadComputeFn &compute)
Allows the user to override the lead computation function.
Definition: Syclop.cpp:213
int getNumRegionExpansions() const
Get the number of times a new region will be chosen and promoted for expansion from a given lead...
Definition: Syclop.h:189
unsigned int numSelections
The number of times this region has been selected for expansion.
Definition: Syclop.h:320
void setNumFreeVolumeSamples(int numSamples)
Set the number of states to sample when estimating free volume in the Decomposition.
Definition: Syclop.h:154
void setProbShortestPathLead(double probability)
Set the probability [0,1] that a lead will be computed as a shortest-path instead of a random-DFS...
Definition: Syclop.h:168
double probKeepAddingToAvail_
The probability that the set of available regions will be augmented.
Definition: Syclop.h:382
int getNumFreeVolumeSamples() const
Get the number of states to sample when estimating free volume in the Decomposition.
Definition: Syclop.h:147
virtual void selectAndExtend(Region &region, std::vector< Motion * > &newMotions)=0
Select a Motion from the given Region, and extend the tree from the Motion. Add any new motions creat...
A shared pointer wrapper for ompl::control::Decomposition.
double getProbAddingToAvailableRegions() const
Get the probability [0,1] that the set of available regions will be augmented.
Definition: Syclop.h:175
const Motion * parent
The parent motion in the tree.
Definition: Syclop.h:270
void clear()
Clears coverage information from this adjacency.
Definition: Syclop.h:339
double freeVolume
The free volume of this region.
Definition: Syclop.h:310
Space information containing necessary information for planning with controls. setup() needs to be ca...
int numFreeVolSamples_
The number of states to sample to estimate free volume in the Decomposition.
Definition: Syclop.h:376
void setNumTreeExpansions(int treeExpansions)
Set the number of calls to selectAndExtend() in the low-level tree planner for a given lead and regio...
Definition: Syclop.h:210
double probAbandonLeadEarly_
The probability that a lead will be abandoned early, before a new region is chosen for expansion...
Definition: Syclop.h:391
void setNumRegionExpansions(int regionExpansions)
Set the number of times a new region will be chosen and promoted for expansion from a given lead...
Definition: Syclop.h:196
double weight
The probabilistic weight of this region, used when sampling from PDF.
Definition: Syclop.h:314
virtual Motion * addRoot(const base::State *s)=0
Add State s as a new root in the low-level tree, and return the Motion corresponding to s...
void setProbAddingToAvailableRegions(double probability)
Set the probability [0,1] that the set of available regions will be augmented.
Definition: Syclop.h:182
unsigned int steps
The number of steps for which the control is applied.
Definition: Syclop.h:272