OptimizationObjective.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
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 Willow Garage 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: Luis G. Torres, Ioan Sucan, Jonathan Gammell */
36 
37 #include "ompl/base/OptimizationObjective.h"
38 #include "ompl/tools/config/MagicConstants.h"
39 #include "ompl/base/goals/GoalRegion.h"
40 #include "ompl/base/samplers/informed/RejectionInfSampler.h"
41 #include <limits>
42 // For std::make_shared
43 #include <memory>
44 
45 ompl::base::OptimizationObjective::OptimizationObjective(const SpaceInformationPtr &si) :
46  si_(si),
47  threshold_(0.0)
48 {
49 }
50 
52 {
53  return description_;
54 }
55 
57 {
58  return isCostBetterThan(c, threshold_);
59 }
60 
62 {
63  return threshold_;
64 }
65 
67 {
68  threshold_ = c;
69 }
70 
72 {
73  return c1.value() < c2.value();
74 }
75 
77 {
78  // If c1 is not better than c2, and c2 is not better than c1, then they are equal
79  return !isCostBetterThan(c1,c2) && !isCostBetterThan(c2,c1);
80 }
81 
83 {
84  return isCostBetterThan(cost, infiniteCost());
85 }
86 
88 {
89  return isCostBetterThan(c1, c2) ? c1 : c2;
90 }
91 
93 {
94  return Cost(c1.value() + c2.value());
95 }
96 
98 {
99  return Cost(0.0);
100 }
101 
103 {
104  return Cost(std::numeric_limits<double>::infinity());
105 }
106 
108 {
109  return identityCost();
110 }
111 
113 {
114  return identityCost();
115 }
116 
118 {
119  return si_->getStateSpace()->hasSymmetricInterpolate();
120 }
121 
123 {
124  StateSamplerPtr ss = si_->allocStateSampler();
125  State *state = si_->allocState();
126  Cost totalCost(identityCost());
127 
128  for (unsigned int i = 0 ; i < numStates ; ++i)
129  {
130  ss->sampleUniform(state);
131  totalCost = combineCosts(totalCost, stateCost(state));
132  }
133 
134  si_->freeState(state);
135 
136  return Cost(totalCost.value() / (double)numStates);
137 }
138 
140 {
141  costToGoFn_ = costToGo;
142 }
143 
145 {
146  return static_cast<bool>(costToGoFn_);
147 }
148 
150 {
151  if (hasCostToGoHeuristic())
152  return costToGoFn_(state, goal);
153  else
154  return identityCost(); // assumes that identity < all costs
155 }
156 
158 {
159  return identityCost(); // assumes that identity < all costs
160 }
161 
163 {
164  return si_;
165 }
166 
167 ompl::base::InformedSamplerPtr ompl::base::OptimizationObjective::allocInformedStateSampler(const ProblemDefinitionPtr probDefn, unsigned int maxNumberCalls) const
168 {
169  OMPL_INFORM("%s: No direct informed sampling scheme is defined, defaulting to rejection sampling.", description_.c_str());
170  return std::make_shared<RejectionInfSampler>(probDefn, maxNumberCalls);
171 }
172 
173 void ompl::base::OptimizationObjective::print(std::ostream &out) const
174 {
175  out << "Optimization Objective: " << description_ << " @" << this << std::endl;
176  out << "Optimization Threshold: " << threshold_ << std::endl;
177 }
178 
180 {
181  const GoalRegion *goalRegion = goal->as<GoalRegion>();
182 
183  // Ensures that all states within the goal region's threshold to
184  // have a cost-to-go of exactly zero.
185  return Cost(std::max(goalRegion->distanceGoal(state) - goalRegion->getThreshold(),
186  0.0));
187 }
188 
189 ompl::base::MultiOptimizationObjective::MultiOptimizationObjective(const SpaceInformationPtr &si) :
190  OptimizationObjective(si),
191  locked_(false)
192 {
193 }
194 
195 ompl::base::MultiOptimizationObjective::Component::
196 Component(const OptimizationObjectivePtr& obj, double weight) :
197  objective(obj), weight(weight)
198 {
199 }
200 
202  double weight)
203 {
204  if (locked_)
205  {
206  throw Exception("This optimization objective is locked. No further objectives can be added.");
207  }
208  else
209  components_.push_back(Component(objective, weight));
210 }
211 
213 {
214  return components_.size();
215 }
216 
218 {
219  if (components_.size() > idx)
220  return components_[idx].objective;
221  else
222  throw Exception("Objective index does not exist.");
223 }
224 
226 {
227  if (components_.size() > idx)
228  return components_[idx].weight;
229  else
230  throw Exception("Objective index does not exist.");
231 }
232 
234  double weight)
235 {
236  if (components_.size() > idx)
237  components_[idx].weight = weight;
238  else
239  throw Exception("Objecitve index does not exist.");
240 }
241 
243 {
244  locked_ = true;
245 }
246 
248 {
249  return locked_;
250 }
251 
253 {
254  Cost c = identityCost();
255  for (std::vector<Component>::const_iterator comp = components_.begin();
256  comp != components_.end();
257  ++comp)
258  {
259  c = Cost(c.value() + comp->weight * (comp->objective->stateCost(s).value()));
260  }
261 
262  return c;
263 }
264 
266  const State *s2) const
267 {
268  Cost c = identityCost();
269  for (std::vector<Component>::const_iterator comp = components_.begin();
270  comp != components_.end();
271  ++comp)
272  {
273  c = Cost(c.value() + comp->weight * (comp->objective->motionCost(s1, s2).value()));
274  }
275 
276  return c;
277 }
278 
280  const OptimizationObjectivePtr &b)
281 {
282  std::vector<MultiOptimizationObjective::Component> components;
283 
284  if (a)
285  {
286  if (MultiOptimizationObjective *mult = dynamic_cast<MultiOptimizationObjective*>(a.get()))
287  {
288  for (std::size_t i = 0; i < mult->getObjectiveCount(); ++i)
289  {
290  components.push_back(MultiOptimizationObjective::
291  Component(mult->getObjective(i),
292  mult->getObjectiveWeight(i)));
293  }
294  }
295  else
296  components.push_back(MultiOptimizationObjective::Component(a, 1.0));
297  }
298 
299  if (b)
300  {
301  if (MultiOptimizationObjective *mult = dynamic_cast<MultiOptimizationObjective*>(b.get()))
302  {
303  for (std::size_t i = 0; i < mult->getObjectiveCount(); ++i)
304  {
305  components.push_back(MultiOptimizationObjective::Component(mult->getObjective(i),
306  mult->getObjectiveWeight(i)));
307  }
308  }
309  else
310  components.push_back(MultiOptimizationObjective::Component(b, 1.0));
311  }
312 
313  MultiOptimizationObjective *multObj = new MultiOptimizationObjective(a->getSpaceInformation());
314 
315  for (std::vector<MultiOptimizationObjective::Component>::const_iterator comp = components.begin();
316  comp != components.end();
317  ++comp)
318  {
319  multObj->addObjective(comp->objective, comp->weight);
320  }
321 
322  return OptimizationObjectivePtr(multObj);
323 }
324 
326  const OptimizationObjectivePtr &a)
327 {
328  std::vector<MultiOptimizationObjective::Component> components;
329 
330  if (a)
331  {
332  if (MultiOptimizationObjective *mult = dynamic_cast<MultiOptimizationObjective*>(a.get()))
333  {
334  for (std::size_t i = 0; i < mult->getObjectiveCount(); ++i)
335  {
336  components.push_back(MultiOptimizationObjective
337  ::Component(mult->getObjective(i),
338  weight * mult->getObjectiveWeight(i)));
339  }
340  }
341  else
342  components.push_back(MultiOptimizationObjective::Component(a, weight));
343  }
344 
345  MultiOptimizationObjective *multObj = new MultiOptimizationObjective(a->getSpaceInformation());
346 
347  for (std::vector<MultiOptimizationObjective::Component>::const_iterator comp = components.begin();
348  comp != components.end();
349  ++comp)
350  {
351  multObj->addObjective(comp->objective, comp->weight);
352  }
353 
354  return OptimizationObjectivePtr(multObj);
355 }
356 
358  double weight)
359 {
360  return weight * a;
361 }
virtual Cost initialCost(const State *s) const
Returns a cost value corresponding to starting at a state s. No optimal planners currently support th...
virtual void print(std::ostream &out) const
Print information about this optimization objective.
A shared pointer wrapper for ompl::base::ProblemDefinition.
This class allows for the definition of multiobjective optimal planning problems. Objectives are adde...
A shared pointer wrapper for ompl::base::StateSampler.
virtual bool isSymmetric() const
Check if this objective has a symmetric cost metric, i.e. motionCost(s1, s2) = motionCost(s2, s1). Default implementation returns whether the underlying state space has symmetric interpolation.
Abstract definition of goals.
Definition: Goal.h:62
virtual double distanceGoal(const State *st) const =0
Compute the distance to the goal (heuristic). This function is the one used in computing the distance...
Cost goalRegionCostToGo(const State *state, const Goal *goal)
For use when the cost-to-go of a state under the optimization objective is equivalent to the goal reg...
void addObjective(const OptimizationObjectivePtr &objective, double weight)
Adds a new objective for this multiobjective. A weight must also be specified for specifying importan...
virtual Cost averageStateCost(unsigned int numStates) const
Compute the average state cost of this objective by taking a sample of numStates states.
void setCostThreshold(Cost c)
Set the cost threshold for objective satisfaction. When a path is found with a cost better than the c...
const std::string & getDescription() const
Get the description of this optimization objective.
virtual Cost infiniteCost() const
Get a cost which is greater than all other costs in this OptimizationObjective; required for use in D...
const SpaceInformationPtr & getSpaceInformation() const
Returns this objective's SpaceInformation. Needed for operators in MultiOptimizationObjective.
void setCostToGoHeuristic(const CostToGoHeuristic &costToGo)
Set the cost-to-go heuristic function for this objective. The cost-to-go heuristic is a function whic...
virtual Cost motionCostHeuristic(const State *s1, const State *s2) const
Defines an admissible estimate on the optimal cost on the motion between states s1 and s2...
virtual Cost motionCost(const State *s1, const State *s2) const
Cost getCostThreshold() const
Returns the cost threshold currently being checked for objective satisfaction.
Cost costToGo(const State *state, const Goal *goal) const
Uses a cost-to-go heuristic to calculate an admissible estimate of the optimal cost from a given stat...
virtual bool isCostEquivalentTo(Cost c1, Cost c2) const
Compare whether cost c1 and cost c2 are equivalent. By default defined as !isCostBetterThan(c1, c2) && !isCostBetterThan(c2, c1), as if c1 is not better than c2, and c2 is not better than c1, then they are equal.
double value() const
The value of the cost.
Definition: Cost.h:54
virtual bool isCostBetterThan(Cost c1, Cost c2) const
Check whether the the cost c1 is considered better than the cost c2. By default, this returns true if...
A shared pointer wrapper for ompl::base::SpaceInformation.
T * as()
Cast this instance to a desired type.
Definition: Goal.h:79
virtual Cost betterCost(Cost c1, Cost c2) const
Return the minimum cost given c1 and c2. Uses isCostBetterThan.
Defines a pairing of an objective and its weight.
Definition of an abstract state.
Definition: State.h:50
OptimizationObjectivePtr operator+(const OptimizationObjectivePtr &a, const OptimizationObjectivePtr &b)
Given two optimization objectives, returns a MultiOptimizationObjective that combines the two objecti...
void setObjectiveWeight(unsigned int idx, double weight)
Sets the weighing factor of a specific objective.
double getObjectiveWeight(unsigned int idx) const
Returns the weighing factor of a specific objective.
The exception type for ompl.
Definition: Exception.h:47
bool isLocked() const
Returns whether this multiobjective has been locked from adding further objectives.
A shared pointer wrapper for ompl::base::OptimizationObjective.
std::size_t getObjectiveCount() const
Returns the number of objectives that make up this multiobjective.
Definition of a goal region.
Definition: GoalRegion.h:50
bool hasCostToGoHeuristic() const
Check if this objective has a cost-to-go heuristic function.
void lock()
This method "freezes" this multiobjective so that no more objectives can be added to it...
double getThreshold() const
Get the distance to the goal that is allowed for a state to be considered in the goal region...
Definition: GoalRegion.h:88
virtual bool isSatisfied(Cost c) const
Check if the the given cost c satisfies the specified cost objective, defined as better than the spec...
virtual Cost combineCosts(Cost c1, Cost c2) const
Get the cost that corresponds to combining the costs c1 and c2. Default implementation defines this c...
virtual InformedSamplerPtr allocInformedStateSampler(const ProblemDefinitionPtr probDefn, unsigned int maxNumberCalls) const
Allocate a heuristic-sampling state generator for this cost function, defaults to a basic rejection s...
virtual Cost terminalCost(const State *s) const
Returns a cost value corresponding to a path ending at a state s. No optimal planners currently suppo...
virtual bool isFinite(Cost cost) const
Returns whether the cost is finite or not.
virtual Cost stateCost(const State *s) const
virtual Cost identityCost() const
Get the identity cost value. The identity cost value is the cost c_i such that, for all costs c...
const OptimizationObjectivePtr & getObjective(unsigned int idx) const
Returns a specific objective from this multiobjective, where the individual objectives are in order o...
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition: Cost.h:47
OptimizationObjectivePtr operator*(double w, const OptimizationObjectivePtr &a)
Given a weighing factor and an optimization objective, returns a MultiOptimizationObjective containin...
std::function< Cost(const State *, const Goal *)> CostToGoHeuristic
The definition of a function which returns an admissible estimate of the optimal path cost from a giv...
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition: Console.h:68