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();
63  tools::SelfConfig sc(si_, getName());
64  sc.configurePlannerRange(maxDistance_);
65 
66  // Make the neighborhood radius smaller than sampling range to keep probabilities relatively high for rejection sampling
67  nbrhoodRadius_ = maxDistance_ / 3.0;
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_)
250  data.addGoalVertex(base::PlannerDataVertex(lastGoalMotion_->state));
251 
252  for (unsigned int i = 0 ; i < motions_.size() ; ++i)
253  {
254  if (motions_[i]->parent == NULL)
255  data.addStartVertex(base::PlannerDataVertex(motions_[i]->state));
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
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
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
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.
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
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
#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 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
A class that will hold data contained in the PDF.
Definition: PDF.h:53
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition: Planner.h:410
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
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
A shared pointer wrapper for ompl::base::Path.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition: Console.h:68