SelfConfig.cpp
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: Ioan Sucan */
36 
37 #include "ompl/tools/config/SelfConfig.h"
38 #include "ompl/tools/config/MagicConstants.h"
39 #include "ompl/geometric/planners/rrt/RRTConnect.h"
40 #include "ompl/geometric/planners/rrt/RRT.h"
41 #include "ompl/geometric/planners/kpiece/LBKPIECE1.h"
42 #include "ompl/geometric/planners/kpiece/KPIECE1.h"
43 #include "ompl/control/planners/rrt/RRT.h"
44 #include "ompl/control/planners/kpiece/KPIECE1.h"
45 #include "ompl/util/Console.h"
46 #include <memory>
47 #include <algorithm>
48 #include <limits>
49 #include <cmath>
50 #include <map>
51 
53 namespace ompl
54 {
55  namespace tools
56  {
57 
58  class SelfConfig::SelfConfigImpl
59  {
60  friend class SelfConfig;
61 
62  public:
63 
64  SelfConfigImpl(const base::SpaceInformationPtr &si) :
65  wsi_(si), probabilityOfValidState_(-1.0), averageValidMotionLength_(-1.0)
66  {
67  }
68 
70  {
71  base::SpaceInformationPtr si = wsi_.lock();
72  checkSetup(si);
73  if (si && probabilityOfValidState_ < 0.0)
74  probabilityOfValidState_ = si->probabilityOfValidState(magic::TEST_STATE_COUNT);
75  return probabilityOfValidState_;
76  }
77 
79  {
80  base::SpaceInformationPtr si = wsi_.lock();
81  checkSetup(si);
82  if (si && averageValidMotionLength_ < 0.0)
83  averageValidMotionLength_ = si->averageValidMotionLength(magic::TEST_STATE_COUNT);
84  return averageValidMotionLength_;
85  }
86 
87  void configureValidStateSamplingAttempts(unsigned int &attempts)
88  {
89  if (attempts == 0)
91  }
92 
93  void configurePlannerRange(double &range, const std::string &context)
94  {
95  if (range < std::numeric_limits<double>::epsilon())
96  {
97  base::SpaceInformationPtr si = wsi_.lock();
98  if (si)
99  {
100  range = si->getMaximumExtent() * magic::MAX_MOTION_LENGTH_AS_SPACE_EXTENT_FRACTION;
101  OMPL_DEBUG("%sPlanner range detected to be %lf", context.c_str(), range);
102  }
103  else
104  OMPL_ERROR("%sUnable to detect planner range. SpaceInformation instance has expired.", context.c_str());
105  }
106  }
107 
108  void configureProjectionEvaluator(base::ProjectionEvaluatorPtr &proj, const std::string &context)
109  {
110  base::SpaceInformationPtr si = wsi_.lock();
111  checkSetup(si);
112  if (!proj && si)
113  {
114  OMPL_INFORM("%sAttempting to use default projection.", context.c_str());
115  proj = si->getStateSpace()->getDefaultProjection();
116  }
117  if (!proj)
118  throw Exception("No projection evaluator specified");
119  proj->setup();
120  }
121 
122  void print(std::ostream &out) const
123  {
124  base::SpaceInformationPtr si = wsi_.lock();
125  if (si)
126  {
127  out << "Configuration parameters for space '" << si->getStateSpace()->getName() << "'" << std::endl;
128  out << " - probability of a valid state is " << probabilityOfValidState_ << std::endl;
129  out << " - average length of a valid motion is " << averageValidMotionLength_ << std::endl;
130  }
131  else
132  out << "EXPIRED" << std::endl;
133  }
134 
135  bool expired() const
136  {
137  return wsi_.expired();
138  }
139 
140  private:
141 
142  void checkSetup(const base::SpaceInformationPtr &si)
143  {
144  if (si)
145  {
146  if (!si->isSetup())
147  {
148  si->setup();
149  probabilityOfValidState_ = -1.0;
150  averageValidMotionLength_ = -1.0;
151  }
152  }
153  else
154  {
155  probabilityOfValidState_ = -1.0;
156  averageValidMotionLength_ = -1.0;
157  }
158  }
159 
160  // we store weak pointers so that the SpaceInformation instances are not kept in
161  // memory until termination of the program due to the use of a static ConfigMap below
162  std::weak_ptr<base::SpaceInformation> wsi_;
163 
164  double probabilityOfValidState_;
165  double averageValidMotionLength_;
166 
167  std::mutex lock_;
168  };
169 
170  }
171 }
172 
173 std::mutex ompl::tools::SelfConfig::staticConstructorLock_;
175 
176 ompl::tools::SelfConfig::SelfConfig(const base::SpaceInformationPtr &si, const std::string &context) :
177  context_(context.empty() ? "" : context + ": ")
178 {
179  typedef std::map<base::SpaceInformation*, std::shared_ptr<SelfConfigImpl> > ConfigMap;
180 
181  std::unique_lock<std::mutex> smLock(staticConstructorLock_);
182 
183  static ConfigMap SMAP;
184 
185  // clean expired entries from the map
186  ConfigMap::iterator dit = SMAP.begin();
187  while (dit != SMAP.end())
188  {
189  if (dit->second->expired())
190  SMAP.erase(dit++);
191  else
192  ++dit;
193  }
194 
195  ConfigMap::const_iterator it = SMAP.find(si.get());
196 
197  if (it != SMAP.end())
198  impl_ = it->second.get();
199  else
200  {
201  impl_ = new SelfConfigImpl(si);
202  SMAP[si.get()].reset(impl_);
203  }
204 }
205 
206 ompl::tools::SelfConfig::~SelfConfig()
207 {
208 }
209 
210 /* ------------------------------------------------------------------------ */
211 
213 {
214  std::lock_guard<std::mutex> iLock(impl_->lock_);
215  return impl_->getProbabilityOfValidState();
216 }
217 
219 {
220  std::lock_guard<std::mutex> iLock(impl_->lock_);
221  return impl_->getAverageValidMotionLength();
222 }
223 
225 {
226  std::lock_guard<std::mutex> iLock(impl_->lock_);
227  impl_->configureValidStateSamplingAttempts(attempts);
228 }
229 
231 {
232  std::lock_guard<std::mutex> iLock(impl_->lock_);
233  impl_->configurePlannerRange(range, context_);
234 }
235 
237 {
238  std::lock_guard<std::mutex> iLock(impl_->lock_);
239  return impl_->configureProjectionEvaluator(proj, context_);
240 }
241 
242 void ompl::tools::SelfConfig::print(std::ostream &out) const
243 {
244  std::lock_guard<std::mutex> iLock(impl_->lock_);
245  impl_->print(out);
246 }
247 
249 {
250  base::PlannerPtr planner;
251  if (!goal)
252  throw Exception("Unable to allocate default planner for unspecified goal definition");
253 
254  base::SpaceInformationPtr si(goal->getSpaceInformation());
255  const base::StateSpacePtr &space(si->getStateSpace());
256  control::SpaceInformationPtr siC(std::dynamic_pointer_cast<control::SpaceInformation, base::SpaceInformation>(si));
257  if (siC) // kinodynamic planning
258  {
259  // if we have a default projection
260  if (space->hasDefaultProjection())
261  planner = base::PlannerPtr(new control::KPIECE1(siC));
262  // otherwise use a single-tree planner
263  else
264  planner = base::PlannerPtr(new control::RRT(siC));
265  }
266  // if we can sample the goal region and interpolation between states is symmetric,
267  // use a bi-directional planner
268  else if (goal->hasType(base::GOAL_SAMPLEABLE_REGION) && space->hasSymmetricInterpolate())
269  {
270  // if we have a default projection
271  if (space->hasDefaultProjection())
272  planner = base::PlannerPtr(new geometric::LBKPIECE1(goal->getSpaceInformation()));
273  else
274  planner = base::PlannerPtr(new geometric::RRTConnect(goal->getSpaceInformation()));
275  }
276  // otherwise use a single-tree planner
277  else
278  {
279  // if we have a default projection
280  if (space->hasDefaultProjection())
281  planner = base::PlannerPtr(new geometric::KPIECE1(goal->getSpaceInformation()));
282  else
283  planner = base::PlannerPtr(new geometric::RRT(goal->getSpaceInformation()));
284  }
285 
286  if (!planner)
287  throw Exception("Unable to allocate default planner");
288 
289  return planner;
290 }
A shared pointer wrapper for ompl::base::StateSpace.
void print(std::ostream &out=std::cout) const
Print the computed configuration parameters.
Definition: SelfConfig.cpp:242
A shared pointer wrapper for ompl::base::Planner.
Kinematic Planning by Interior-Exterior Cell Exploration.
Definition: KPIECE1.h:74
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
double getAverageValidMotionLength()
Get the probability of a sampled state being valid (calls base::SpaceInformation::averageValidMotionL...
Definition: SelfConfig.cpp:218
RRT-Connect (RRTConnect)
Definition: RRTConnect.h:61
A shared pointer wrapper for ompl::base::ProjectionEvaluator.
Rapidly-exploring Random Trees.
Definition: RRT.h:65
A shared pointer wrapper for ompl::base::SpaceInformation.
SelfConfig(const base::SpaceInformationPtr &si, const std::string &context=std::string())
Construct an instance that can configure the space encapsulated by si. Any information printed to the...
Definition: SelfConfig.cpp:176
Kinodynamic Planning by Interior-Exterior Cell Exploration.
Definition: KPIECE1.h:77
A shared pointer wrapper for ompl::control::SpaceInformation.
Lazy Bi-directional KPIECE with one level of discretization.
Definition: LBKPIECE1.h:78
static base::PlannerPtr getDefaultPlanner(const base::GoalPtr &goal)
Given a goal specification, decide on a planner for that goal.
Definition: SelfConfig.cpp:248
The exception type for ompl.
Definition: Exception.h:47
#define OMPL_DEBUG(fmt,...)
Log a formatted debugging string.
Definition: Console.h:70
void configureProjectionEvaluator(base::ProjectionEvaluatorPtr &proj)
If proj is undefined, it is set to the default projection reported by base::StateSpace::getDefaultPro...
Definition: SelfConfig.cpp:236
double getProbabilityOfValidState()
Get the probability of a sampled state being valid (calls base::SpaceInformation::probabilityOfValidS...
Definition: SelfConfig.cpp:212
void configurePlannerRange(double &range)
Compute what a good length for motion segments is.
Definition: SelfConfig.cpp:230
Rapidly-exploring Random Tree.
Definition: RRT.h:66
static const unsigned int TEST_STATE_COUNT
When multiple states need to be generated as part of the computation of various information (usually ...
static const double MAX_MOTION_LENGTH_AS_SPACE_EXTENT_FRACTION
For planners: if default values are to be used for the maximum length of motions, this constant defin...
A shared pointer wrapper for ompl::base::Goal.
void configureValidStateSamplingAttempts(unsigned int &attempts)
Instances of base::ValidStateSampler need a number of attempts to be specified – the maximum number o...
Definition: SelfConfig.cpp:224
static const unsigned int MAX_VALID_SAMPLE_ATTEMPTS
When multiple attempts are needed to generate valid samples, this value defines the default number of...
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