ODESolver.h
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: Ryan Luna */
36 
37 #ifndef OMPL_CONTROL_ODESOLVER_
38 #define OMPL_CONTROL_ODESOLVER_
39 
40 #include "ompl/control/Control.h"
41 #include "ompl/control/SpaceInformation.h"
42 #include "ompl/control/StatePropagator.h"
43 #include "ompl/util/Console.h"
44 #include "ompl/util/ClassForward.h"
45 
46 #include <boost/version.hpp>
47 #include <boost/numeric/odeint.hpp>
48 namespace odeint = boost::numeric::odeint;
49 #include <functional>
50 #include <cassert>
51 #include <vector>
52 
53 namespace ompl
54 {
55 
56  namespace control
57  {
58 
60  OMPL_CLASS_FORWARD(ODESolver);
62 
65 
70  class ODESolver
71  {
72  public:
74  typedef std::vector<double> StateType;
75 
78  typedef std::function<void(const StateType &, const Control*, StateType &)> ODE;
79 
82  typedef std::function<void(const base::State *state, const Control *control, const double duration, base::State *result)> PostPropagationEvent;
83 
86  ODESolver (const SpaceInformationPtr& si, const ODE& ode, double intStep) : si_(si), ode_(ode), intStep_(intStep)
87  {
88  }
89 
91  virtual ~ODESolver ()
92  {
93  }
94 
96  void setODE (const ODE &ode)
97  {
98  ode_ = ode;
99  }
100 
102  double getIntegrationStepSize () const
103  {
104  return intStep_;
105  }
106 
108  void setIntegrationStepSize (double intStep)
109  {
110  intStep_ = intStep;
111  }
112 
115  {
116  return si_;
117  }
118 
124  static StatePropagatorPtr getStatePropagator (ODESolverPtr solver,
125  const PostPropagationEvent &postEvent = nullptr)
126  {
127  class ODESolverStatePropagator : public StatePropagator
128  {
129  public:
130  ODESolverStatePropagator (ODESolverPtr solver, const PostPropagationEvent &pe) : StatePropagator (solver->si_), solver_(solver), postEvent_(pe)
131  {
132  if (!solver.get())
133  OMPL_ERROR("ODESolverPtr does not reference a valid ODESolver object");
134  }
135 
136  virtual void propagate (const base::State *state, const Control *control, const double duration, base::State *result) const
137  {
138  ODESolver::StateType reals;
139  si_->getStateSpace()->copyToReals(reals, state);
140  solver_->solve (reals, control, duration);
141  si_->getStateSpace()->copyFromReals(result, reals);
142 
143  if (postEvent_)
144  postEvent_ (state, control, duration, result);
145  }
146 
147  protected:
148  ODESolverPtr solver_;
150  };
151  return StatePropagatorPtr(dynamic_cast<StatePropagator*>(new ODESolverStatePropagator(solver, postEvent)));
152  }
153 
154  protected:
155 
157  virtual void solve (StateType &state, const Control *control, const double duration) const = 0;
158 
161 
164 
166  double intStep_;
167 
169  // Functor used by the boost::numeric::odeint stepper object
170  struct ODEFunctor
171  {
172  ODEFunctor (const ODE &o, const Control *ctrl) : ode(o), control(ctrl) {}
173 
174  // boost::numeric::odeint will callback to this method during integration to evaluate the system
175  void operator () (const StateType &current, StateType &output, double /*time*/)
176  {
177  ode (current, control, output);
178  }
179 
180  ODE ode;
181  const Control *control;
182  };
184  };
185 
192  template <class Solver = odeint::runge_kutta4<ODESolver::StateType> >
193  class ODEBasicSolver : public ODESolver
194  {
195  public:
196 
199  ODEBasicSolver (const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep = 1e-2) : ODESolver(si, ode, intStep)
200  {
201  }
202 
203  protected:
204 
206  virtual void solve (StateType &state, const Control *control, const double duration) const
207  {
208  Solver solver;
209  ODESolver::ODEFunctor odefunc (ode_, control);
210  odeint::integrate_const (solver, odefunc, state, 0.0, duration, intStep_);
211  }
212  };
213 
220  template <class Solver = odeint::runge_kutta_cash_karp54<ODESolver::StateType> >
221  class ODEErrorSolver : public ODESolver
222  {
223  public:
226  ODEErrorSolver (const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep = 1e-2) : ODESolver(si, ode, intStep)
227  {
228  }
229 
232  {
233  return error_;
234  }
235 
236  protected:
238  virtual void solve (StateType &state, const Control *control, const double duration) const
239  {
240  ODESolver::ODEFunctor odefunc (ode_, control);
241 
242  if (error_.size () != state.size ())
243  error_.assign (state.size (), 0.0);
244 
245  Solver solver;
246  solver.adjust_size (state);
247 
248  double time = 0.0;
249  while (time < duration + std::numeric_limits<float>::epsilon())
250  {
251  solver.do_step (odefunc, state, time, intStep_, error_);
252  time += intStep_;
253  }
254  }
255 
258  };
259 
266  template <class Solver = odeint::runge_kutta_cash_karp54<ODESolver::StateType> >
268  {
269  public:
272  ODEAdaptiveSolver (const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep = 1e-2) : ODESolver(si, ode, intStep), maxError_(1e-6), maxEpsilonError_(1e-7)
273  {
274  }
275 
277  double getMaximumError () const
278  {
279  return maxError_;
280  }
281 
283  void setMaximumError (double error)
284  {
285  maxError_ = error;
286  }
287 
289  double getMaximumEpsilonError () const
290  {
291  return maxEpsilonError_;
292  }
293 
295  void setMaximumEpsilonError (double error)
296  {
297  maxEpsilonError_ = error;
298  }
299 
300  protected:
301 
306  virtual void solve (StateType &state, const Control *control, const double duration) const
307  {
308  ODESolver::ODEFunctor odefunc (ode_, control);
309 
310 #if BOOST_VERSION < 105600
311  odeint::controlled_runge_kutta< Solver > solver (odeint::default_error_checker<double>(maxError_, maxEpsilonError_));
312 #else
313  typename boost::numeric::odeint::result_of::make_controlled< Solver >::type solver = make_controlled( 1.0e-6 , 1.0e-6 , Solver() );
314 #endif
315  odeint::integrate_adaptive (solver, odefunc, state, 0.0, duration, intStep_);
316  }
317 
319  double maxError_;
320 
323  };
324  }
325 }
326 
327 #endif
std::function< void(const base::State *state, const Control *control, const double duration, base::State *result)> PostPropagationEvent
Callback function to perform an event at the end of numerical integration. This functionality is opti...
Definition: ODESolver.h:82
Solver for ordinary differential equations of the type q' = f(q, u), where q is the current state of ...
Definition: ODESolver.h:221
ODEErrorSolver(const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep=1e-2)
Parameterized constructor. Takes a reference to the SpaceInformation, an ODE to solve, and the integration step size - default is 0.01.
Definition: ODESolver.h:226
std::function< void(const StateType &, const Control *, StateType &)> ODE
Callback function that defines the ODE. Accepts the current state, input control, and output state...
Definition: ODESolver.h:78
ODE ode_
Definition of the ODE to find solutions for.
Definition: ODESolver.h:163
double getMaximumEpsilonError() const
Retrieve the error tolerance during one step of numerical integration (local truncation error) ...
Definition: ODESolver.h:289
Definition of an abstract control.
Definition: Control.h:48
double getIntegrationStepSize() const
Return the size of a single numerical integration step.
Definition: ODESolver.h:102
ODEAdaptiveSolver(const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep=1e-2)
Parameterized constructor. Takes a reference to the SpaceInformation, an ODE to solve, and an optional integration step size - default is 0.01.
Definition: ODESolver.h:272
const SpaceInformationPtr & getSpaceInformation() const
Get the current instance of the space information.
Definition: ODESolver.h:114
void setODE(const ODE &ode)
Set the ODE to solve.
Definition: ODESolver.h:96
ODESolver::StateType getError()
Retrieves the error values from the most recent integration.
Definition: ODESolver.h:231
A shared pointer wrapper for ompl::control::ODESolver.
static StatePropagatorPtr getStatePropagator(ODESolverPtr solver, const PostPropagationEvent &postEvent=nullptr)
Retrieve a StatePropagator object that solves a system of ordinary differential equations defined by ...
Definition: ODESolver.h:124
Model the effect of controls on system states.
void setMaximumError(double error)
Set the total error allowed during numerical integration.
Definition: ODESolver.h:283
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
virtual void solve(StateType &state, const Control *control, const double duration) const
Solve the ODE using boost::numeric::odeint. Save the resulting error values into error_.
Definition: ODESolver.h:238
virtual void solve(StateType &state, const Control *control, const double duration) const =0
Solve the ODE given the initial state, and a control to apply for some duration.
std::vector< double > StateType
Portable data type for the state values.
Definition: ODESolver.h:74
Adaptive step size solver for ordinary differential equations of the type q' = f(q, u), where q is the current state of the system and u is a control applied to the system. The maximum integration error is bounded in this approach. Solver is the numerical integration method used to solve the equations, and must implement the error stepper concept from boost::numeric::odeint. The default is a fifth order Runge-Kutta Cash-Karp method with a fourth order error bound.
Definition: ODESolver.h:267
const SpaceInformationPtr si_
The SpaceInformation that this ODESolver operates in.
Definition: ODESolver.h:160
virtual void solve(StateType &state, const Control *control, const double duration) const
Solve the ODE using boost::numeric::odeint.
Definition: ODESolver.h:206
Definition of an abstract state.
Definition: State.h:50
void setIntegrationStepSize(double intStep)
Set the size of a single numerical integration step.
Definition: ODESolver.h:108
A shared pointer wrapper for ompl::control::SpaceInformation.
ODESolver::StateType error_
The error values calculated during numerical integration.
Definition: ODESolver.h:257
virtual ~ODESolver()
Destructor.
Definition: ODESolver.h:91
Basic solver for ordinary differential equations of the type q' = f(q, u), where q is the current sta...
Definition: ODESolver.h:193
void setMaximumEpsilonError(double error)
Set the error tolerance during one step of numerical integration (local truncation error) ...
Definition: ODESolver.h:295
double maxError_
The maximum error allowed when performing numerical integration.
Definition: ODESolver.h:319
Abstract base class for an object that can solve ordinary differential equations (ODE) of the type q'...
Definition: ODESolver.h:70
ODEBasicSolver(const SpaceInformationPtr &si, const ODESolver::ODE &ode, double intStep=1e-2)
Parameterized constructor. Takes a reference to the SpaceInformation, an ODE to solve, and an optional integration step size - default is 0.01.
Definition: ODESolver.h:199
double getMaximumError() const
Retrieve the total error allowed during numerical integration.
Definition: ODESolver.h:277
ODESolver(const SpaceInformationPtr &si, const ODE &ode, double intStep)
Parameterized constructor. Takes a reference to SpaceInformation, an ODE to solve, and the integration step size.
Definition: ODESolver.h:86
virtual void solve(StateType &state, const Control *control, const double duration) const
Solve the ordinary differential equation given the input state of the system, a control to apply to t...
Definition: ODESolver.h:306
double intStep_
The size of the numerical integration step. Should be small to minimize error.
Definition: ODESolver.h:166
double maxEpsilonError_
The maximum error allowed during one step of numerical integration.
Definition: ODESolver.h:322