SpaceInformation.cpp
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2010, 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/control/SpaceInformation.h"
38 #include "ompl/control/SimpleDirectedControlSampler.h"
39 #include "ompl/control/SteeredControlSampler.h"
40 #include "ompl/util/Exception.h"
41 #include <cassert>
42 #include <utility>
43 #include <limits>
44 
46  const base::StateSpacePtr &stateSpace, ControlSpacePtr controlSpace)
47  : base::SpaceInformation(stateSpace), controlSpace_(std::move(controlSpace))
48 {
49  declareParams();
50 }
51 
53 {
54  params_.declareParam<unsigned int>("min_control_duration",
55  [this](unsigned int n) { setMinControlDuration(n); },
56  [this] { return getMinControlDuration(); });
57  params_.declareParam<unsigned int>("max_control_duration",
58  [this](unsigned int n) { setMaxControlDuration(n); },
59  [this] { return getMaxControlDuration(); });
60  params_.declareParam<double>("propagation_step_size",
61  [this](double s) { setPropagationStepSize(s); },
62  [this] { return getPropagationStepSize(); });
63 }
64 
66 {
68  declareParams(); // calling base::SpaceInformation::setup() clears the params
69  if (!statePropagator_)
70  throw Exception("State propagator not defined");
71  if (minSteps_ > maxSteps_)
72  throw Exception("The minimum number of steps cannot be larger than the maximum number of steps");
73  if (minSteps_ == 0 && maxSteps_ == 0)
74  {
75  minSteps_ = 1;
76  maxSteps_ = 10;
77  OMPL_WARN("Assuming propagation will always have between %d and %d steps", minSteps_, maxSteps_);
78  }
79  if (minSteps_ < 1)
80  throw Exception("The minimum number of steps must be at least 1");
81 
82  if (stepSize_ < std::numeric_limits<double>::epsilon())
83  {
84  stepSize_ = getStateValidityCheckingResolution() * getMaximumExtent();
85  if (stepSize_ < std::numeric_limits<double>::epsilon())
86  throw Exception("The propagation step size must be larger than 0");
87  OMPL_WARN("The propagation step size is assumed to be %f", stepSize_);
88  }
89 
90  controlSpace_->setup();
91  if (controlSpace_->getDimension() <= 0)
92  throw Exception("The dimension of the control space we plan in must be > 0");
93 }
94 
96 {
97  if (dcsa_)
98  return dcsa_(this);
99  if (statePropagator_->canSteer())
100  return std::make_shared<SteeredControlSampler>(this);
101  else
102  return std::make_shared<SimpleDirectedControlSampler>(this);
103 }
104 
106 {
107  dcsa_ = dcsa;
108  setup_ = false;
109 }
110 
112 {
114  setup_ = false;
115 }
116 
118 {
119  class FnStatePropagator : public StatePropagator
120  {
121  public:
122  FnStatePropagator(SpaceInformation *si, StatePropagatorFn fn) : StatePropagator(si), fn_(std::move(fn))
123  {
124  }
125 
126  void propagate(const base::State *state, const Control *control, const double duration,
127  base::State *result) const override
128  {
129  fn_(state, control, duration, result);
130  }
131 
132  protected:
133  StatePropagatorFn fn_;
134  };
135 
136  setStatePropagator(std::make_shared<FnStatePropagator>(this, fn));
137 }
138 
140 {
141  statePropagator_ = sp;
142 }
143 
145 {
146  if (statePropagator_)
147  return statePropagator_->canPropagateBackward();
148  return false;
149 }
150 
151 void ompl::control::SpaceInformation::propagate(const base::State *state, const Control *control, int steps,
152  base::State *result) const
153 {
154  if (steps == 0)
155  {
156  if (result != state)
157  copyState(result, state);
158  }
159  else
160  {
161  double signedStepSize = steps > 0 ? stepSize_ : -stepSize_;
162  steps = abs(steps);
163 
164  statePropagator_->propagate(state, control, signedStepSize, result);
165  for (int i = 1; i < steps; ++i)
166  statePropagator_->propagate(result, control, signedStepSize, result);
167  }
168 }
169 
171  int steps, base::State *result) const
172 {
173  if (steps == 0)
174  {
175  if (result != state)
176  copyState(result, state);
177  return 0;
178  }
179 
180  double signedStepSize = steps > 0 ? stepSize_ : -stepSize_;
181  steps = abs(steps);
182 
183  // perform the first step of propagation
184  statePropagator_->propagate(state, control, signedStepSize, result);
185 
186  // if we found a valid state after one step, we can go on
187  if (isValid(result))
188  {
189  base::State *temp1 = result;
190  base::State *temp2 = allocState();
191  base::State *toDelete = temp2;
192  unsigned int r = steps;
193 
194  // for the remaining number of steps
195  for (int i = 1; i < steps; ++i)
196  {
197  statePropagator_->propagate(temp1, control, signedStepSize, temp2);
198  if (isValid(temp2))
199  std::swap(temp1, temp2);
200  else
201  {
202  // the last valid state is temp1;
203  r = i;
204  break;
205  }
206  }
207 
208  // if we finished the for-loop without finding an invalid state, the last valid state is temp1
209  // make sure result contains that information
210  if (result != temp1)
211  copyState(result, temp1);
212 
213  // free the temporary memory
214  freeState(toDelete);
215 
216  return r;
217  }
218  // if the first propagation step produced an invalid step, return 0 steps
219  // the last valid state is the starting one (assumed to be valid)
220  if (result != state)
221  copyState(result, state);
222  return 0;
223 }
224 
225 void ompl::control::SpaceInformation::propagate(const base::State *state, const Control *control, int steps,
226  std::vector<base::State *> &result, bool alloc) const
227 {
228  double signedStepSize = steps > 0 ? stepSize_ : -stepSize_;
229  steps = abs(steps);
230 
231  if (alloc)
232  {
233  result.resize(steps);
234  for (auto &i : result)
235  i = allocState();
236  }
237  else
238  {
239  if (result.empty())
240  return;
241  steps = std::min(steps, (int)result.size());
242  }
243 
244  int st = 0;
245 
246  if (st < steps)
247  {
248  statePropagator_->propagate(state, control, signedStepSize, result[st]);
249  ++st;
250 
251  while (st < steps)
252  {
253  statePropagator_->propagate(result[st - 1], control, signedStepSize, result[st]);
254  ++st;
255  }
256  }
257 }
258 
260  int steps, std::vector<base::State *> &result,
261  bool alloc) const
262 {
263  double signedStepSize = steps > 0 ? stepSize_ : -stepSize_;
264  steps = abs(steps);
265 
266  if (alloc)
267  result.resize(steps);
268  else
269  {
270  if (result.empty())
271  return 0;
272  steps = std::min(steps, (int)result.size());
273  }
274 
275  int st = 0;
276 
277  if (st < steps)
278  {
279  if (alloc)
280  result[st] = allocState();
281  statePropagator_->propagate(state, control, signedStepSize, result[st]);
282 
283  if (isValid(result[st]))
284  {
285  ++st;
286  while (st < steps)
287  {
288  if (alloc)
289  result[st] = allocState();
290  statePropagator_->propagate(result[st - 1], control, signedStepSize, result[st]);
291 
292  if (!isValid(result[st]))
293  {
294  if (alloc)
295  {
296  freeState(result[st]);
297  result.resize(st);
298  }
299  break;
300  }
301  ++st;
302  }
303  }
304  else
305  {
306  if (alloc)
307  {
308  freeState(result[st]);
309  result.resize(st);
310  }
311  }
312  }
313 
314  return st;
315 }
316 
318 {
320  out << " - control space:" << std::endl;
321  controlSpace_->printSettings(out);
322  out << " - can propagate backward: " << (canPropagateBackward() ? "yes" : "no") << std::endl;
323  out << " - propagation step size: " << stepSize_ << std::endl;
324  out << " - propagation duration: [" << minSteps_ << ", " << maxSteps_ << "]" << std::endl;
325 }
Definition of an abstract control.
Definition: Control.h:111
void setStatePropagator(const StatePropagatorFn &fn)
Set the function that performs state propagation.
SpaceInformation(const base::StateSpacePtr &stateSpace, ControlSpacePtr controlSpace)
Constructor. Sets the instance of the state and control spaces to plan with.
A shared pointer wrapper for ompl::control::ControlSpace.
DirectedControlSamplerPtr allocDirectedControlSampler() const
Allocate an instance of the DirectedControlSampler to use. This will be the default (SimpleDirectedCo...
Definition of an abstract state.
Definition: State.h:113
Model the effect of controls on system states.
void setDirectedControlSamplerAllocator(const DirectedControlSamplerAllocator &dcsa)
Set the allocator to use for the DirectedControlSampler.
std::function< DirectedControlSamplerPtr(const SpaceInformation *)> DirectedControlSamplerAllocator
Definition of a function that can allocate a directed control sampler.
std::function< void(const base::State *, const Control *, const double, base::State *)> StatePropagatorFn
A function that achieves state propagation.
void printSettings(std::ostream &out=std::cout) const override
Print information about the current instance of the state space.
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
Definition: Console.h:66
Space information containing necessary information for planning with controls. setup() needs to be ca...
virtual void printSettings(std::ostream &out=std::cout) const
Print information about the current instance of the state space.
A shared pointer wrapper for ompl::control::DirectedControlSampler.
void propagate(const base::State *state, const Control *control, int steps, base::State *result) const
Propagate the model of the system forward, starting a a given state, with a given control,...
A shared pointer wrapper for ompl::control::StatePropagator.
void clearDirectedSamplerAllocator()
Reset the DirectedControlSampler to be the default one.
virtual void setup()
Perform additional setup tasks (run once, before use). If state validity checking resolution has not ...
The exception type for ompl.
Definition: Exception.h:78
unsigned int propagateWhileValid(const base::State *state, const Control *control, int steps, base::State *result) const
Propagate the model of the system forward, starting at a given state, with a given control,...
bool canPropagateBackward() const
Some systems can only propagate forward in time (i.e., the steps argument for the propagate() functio...
void setup() override
Perform additional setup tasks (run once, before use)