EST.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2015, Rice University
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Rice University nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 /* Author: Ryan Luna */
36 
37 #include "ompl/geometric/planners/est/EST.h"
38 #include "ompl/base/goals/GoalSampleableRegion.h"
39 #include "ompl/tools/config/SelfConfig.h"
40 #include <limits>
41 #include <cassert>
42 
43 ompl::geometric::EST::EST(const base::SpaceInformationPtr &si) : base::Planner(si, "EST")
44 {
46  specs_.directed = true;
47  goalBias_ = 0.05;
48  maxDistance_ = 0.0;
49  lastGoalMotion_ = NULL;
50 
51  Planner::declareParam<double>("range", this, &EST::setRange, &EST::getRange, "0.:1.:10000.");
52  Planner::declareParam<double>("goal_bias", this, &EST::setGoalBias, &EST::getGoalBias, "0.:.05:1.");
53 }
54 
55 ompl::geometric::EST::~EST()
56 {
57  freeMemory();
58 }
59 
61 {
62  Planner::setup();
65 
66  // Make the neighborhood radius smaller than sampling range to keep probabilities relatively high for rejection sampling
68 
69  if (!nn_)
70  nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion*>(this));
71  nn_->setDistanceFunction(std::bind(&EST::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
72 }
73 
75 {
76  Planner::clear();
77  sampler_.reset();
78  freeMemory();
79  if (nn_)
80  nn_->clear();
81 
82  motions_.clear();
83  pdf_.clear();
84  lastGoalMotion_ = NULL;
85 }
86 
88 {
89  for(size_t i = 0; i < motions_.size(); ++i)
90  {
91  if (motions_[i]->state)
92  si_->freeState(motions_[i]->state);
93  delete motions_[i];
94  }
95 }
96 
98 {
99  checkValidity();
100  base::Goal *goal = pdef_->getGoal().get();
101  base::GoalSampleableRegion *goal_s = dynamic_cast<base::GoalSampleableRegion*>(goal);
102 
103  std::vector<Motion*> neighbors;
104 
105  while (const base::State *st = pis_.nextStart())
106  {
107  Motion *motion = new Motion(si_);
108  si_->copyState(motion->state, st);
109 
110  nn_->nearestR(motion, nbrhoodRadius_, neighbors);
111  addMotion(motion, neighbors);
112  }
113 
114  if (motions_.size() == 0)
115  {
116  OMPL_ERROR("%s: There are no valid initial states!", getName().c_str());
118  }
119 
120  if (!sampler_)
121  sampler_ = si_->allocValidStateSampler();
122 
123  OMPL_INFORM("%s: Starting planning with %u states already in datastructure", getName().c_str(), motions_.size());
124 
125  Motion *solution = NULL;
126  Motion *approxsol = NULL;
127  double approxdif = std::numeric_limits<double>::infinity();
128  base::State *xstate = si_->allocState();
129  Motion* xmotion = new Motion();
130 
131  while (ptc == false)
132  {
133  // Select a state to expand from
134  Motion *existing = pdf_.sample(rng_.uniform01());
135  assert(existing);
136 
137  // Sample random state in the neighborhood (with goal biasing)
138  if (goal_s && rng_.uniform01() < goalBias_ && goal_s->canSample())
139  {
140  goal_s->sampleGoal(xstate);
141 
142  // Compute neighborhood of candidate motion
143  xmotion->state = xstate;
144  nn_->nearestR(xmotion, nbrhoodRadius_, neighbors);
145  }
146  else
147  {
148  // Sample a state in the neighborhood
149  if (!sampler_->sampleNear(xstate, existing->state, maxDistance_))
150  continue;
151 
152  // Compute neighborhood of candidate state
153  xmotion->state = xstate;
154  nn_->nearestR(xmotion, nbrhoodRadius_, neighbors);
155 
156  // reject state with probability proportional to neighborhood density
157  if (neighbors.size())
158  {
159  double p = 1.0 - (1.0 / neighbors.size());
160  if (rng_.uniform01() < p)
161  continue;
162  }
163  }
164 
165  // Is motion good?
166  if (si_->checkMotion(existing->state, xstate))
167  {
168  // create a motion
169  Motion *motion = new Motion(si_);
170  si_->copyState(motion->state, xstate);
171  motion->parent = existing;
172 
173  // add it to everything
174  addMotion(motion, neighbors);
175 
176  // done?
177  double dist = 0.0;
178  bool solved = goal->isSatisfied(motion->state, &dist);
179  if (solved)
180  {
181  approxdif = dist;
182  solution = motion;
183  break;
184  }
185  if (dist < approxdif)
186  {
187  approxdif = dist;
188  approxsol = motion;
189  }
190  }
191  }
192 
193  bool solved = false;
194  bool approximate = false;
195  if (solution == NULL)
196  {
197  solution = approxsol;
198  approximate = true;
199  }
200 
201  if (solution != NULL)
202  {
203  lastGoalMotion_ = solution;
204 
205  // construct the solution path
206  std::vector<Motion*> mpath;
207  while (solution != NULL)
208  {
209  mpath.push_back(solution);
210  solution = solution->parent;
211  }
212 
213  // set the solution path
214  PathGeometric *path = new PathGeometric(si_);
215  for (int i = mpath.size() - 1 ; i >= 0 ; --i)
216  path->append(mpath[i]->state);
217  pdef_->addSolutionPath(base::PathPtr(path), approximate, approxdif, getName());
218  solved = true;
219  }
220 
221  si_->freeState(xstate);
222  delete xmotion;
223 
224  OMPL_INFORM("%s: Created %u states", getName().c_str(), motions_.size());
225 
226  return base::PlannerStatus(solved, approximate);
227 }
228 
229 void ompl::geometric::EST::addMotion(Motion *motion, const std::vector<Motion*>& neighbors)
230 {
231  // Updating neighborhood size counts
232  for(size_t i = 0; i < neighbors.size(); ++i)
233  {
234  PDF<Motion*>::Element *elem = neighbors[i]->element;
235  double w = pdf_.getWeight(elem);
236  pdf_.update(elem, w / (w + 1.));
237  }
238 
239  // now add new motion to the data structures
240  motion->element = pdf_.add(motion, 1. / (neighbors.size() + 1.)); // +1 for self
241  motions_.push_back(motion);
242  nn_->add(motion);
243 }
244 
246 {
247  Planner::getPlannerData(data);
248 
249  if (lastGoalMotion_)
251 
252  for (unsigned int i = 0 ; i < motions_.size() ; ++i)
253  {
254  if (motions_[i]->parent == NULL)
256  else
257  data.addEdge(base::PlannerDataVertex(motions_[i]->parent->state),
258  base::PlannerDataVertex(motions_[i]->state));
259  }
260 }
bool approximateSolutions
Flag indicating whether the planner is able to compute approximate solutions.
Definition: Planner.h:212
RNG rng_
The random number generator.
Definition: EST.h:181
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Definition: PlannerData.h:163
void addMotion(Motion *motion, const std::vector< Motion * > &neighbors)
Add a motion to the exploration tree.
Definition: EST.cpp:229
Motion * lastGoalMotion_
The most recent goal motion. Used for PlannerData computation.
Definition: EST.h:184
double maxDistance_
The maximum length of a motion to be added to a tree.
Definition: EST.h:175
unsigned int addGoalVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
Abstract definition of goals.
Definition: Goal.h:62
base::ValidStateSamplerPtr sampler_
Valid state sampler.
Definition: EST.h:169
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
double nbrhoodRadius_
The radius considered for neighborhood.
Definition: EST.h:178
virtual void setup()
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
Definition: EST.cpp:60
void append(const base::State *state)
Append state to the end of this path. The memory for state is copied.
ProblemDefinitionPtr pdef_
The user set problem definition.
Definition: Planner.h:401
base::State * state
The state contained by the motion.
Definition: EST.h:138
bool directed
Flag indicating whether the planner is able to account for the fact that the validity of a motion fro...
Definition: Planner.h:220
virtual void sampleGoal(State *st) const =0
Sample a state in the goal region.
The definition of a motion.
Definition: EST.h:120
double uniform01()
Generate a random real between 0 and 1.
Definition: RandomNumbers.h:69
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition: PlannerData.h:59
Invalid start state or no start state specified.
Definition: PlannerStatus.h:56
Abstract definition of a goal region that can be sampled.
double getRange() const
Get the range the planner is using.
Definition: EST.h:108
std::vector< Motion * > motions_
The set of all states in the tree.
Definition: EST.h:157
PDF< Motion * > pdf_
The probability distribution function over states in the tree.
Definition: EST.h:160
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
PDF< Motion * >::Element * element
A pointer to the corresponding element in the probability distribution function.
Definition: EST.h:144
virtual void getPlannerData(base::PlannerData &data) const
Get information about the current run of the motion planner. Repeated calls to this function will upd...
Definition: EST.cpp:245
A class to store the exit status of Planner::solve()
Definition: PlannerStatus.h:48
virtual bool addEdge(unsigned int v1, unsigned int v2, const PlannerDataEdge &edge=PlannerDataEdge(), Cost weight=Cost(1.0))
Adds a directed edge between the given vertex indexes. An optional edge structure and weight can be s...
virtual base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
Function that can solve the motion planning problem. This function can be called multiple times on th...
Definition: EST.cpp:97
bool canSample() const
Return true if maxSampleCount() > 0, since in this case samples can certainly be produced.
A shared pointer wrapper for ompl::base::SpaceInformation.
unsigned int addStartVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
Definition of an abstract state.
Definition: State.h:50
virtual void checkValidity()
Check to see if the planner is in a working state (setup has been called, a goal was set...
Definition: Planner.cpp:100
virtual bool isSatisfied(const State *st) const =0
Return true if the state satisfies the goal constraints.
void setRange(double distance)
Set the range the planner is supposed to use.
Definition: EST.h:102
PlannerInputStates pis_
Utility class to extract valid input states.
Definition: Planner.h:404
A class that will hold data contained in the PDF.
Definition: PDF.h:53
std::shared_ptr< NearestNeighbors< Motion * > > nn_
A nearest-neighbors datastructure containing the tree of motions.
Definition: EST.h:154
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition: Planner.h:410
const State * nextStart()
Return the next valid start state or nullptr if no more valid start states are available.
Definition: Planner.cpp:230
virtual void clear()
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
Definition: EST.cpp:74
double getGoalBias() const
Get the goal bias the planner is using.
Definition: EST.h:92
void freeMemory()
Free the memory allocated by this planner.
Definition: EST.cpp:87
void setGoalBias(double goalBias)
In the process of randomly selecting states in the state space to attempt to go towards, the algorithm may in fact choose the actual goal state, if it knows it, with some probability. This probability is a real number between 0.0 and 1.0; its value should usually be around 0.05 and should not be too large. It is probably a good idea to use the default value.
Definition: EST.h:86
void configurePlannerRange(double &range)
Compute what a good length for motion segments is.
Definition: SelfConfig.cpp:230
This class contains methods that automatically configure various parameters for motion planning...
Definition: SelfConfig.h:60
double distanceFunction(const Motion *a, const Motion *b) const
Compute distance between motions (actually distance between contained states)
Definition: EST.h:148
EST(const base::SpaceInformationPtr &si)
Constructor.
Definition: EST.cpp:43
Motion * parent
The parent motion in the exploration tree.
Definition: EST.h:141
Definition of a geometric path.
Definition: PathGeometric.h:60
SpaceInformationPtr si_
The space information for which planning is done.
Definition: Planner.h:398
double goalBias_
The fraction of time the goal is picked as the state to expand towards (if such a state is available)...
Definition: EST.h:172
const std::string & getName() const
Get the name of the planner.
Definition: Planner.cpp:55
A shared pointer wrapper for ompl::base::Path.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition: Console.h:68