VanaOwenStateSpace.cpp
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2024, Metron, 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 Metron, Inc. 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: Mark Moll */
36 
37 #include "ompl/base/spaces/VanaOwenStateSpace.h"
38 #include "ompl/base/SpaceInformation.h"
39 #include "ompl/tools/config/MagicConstants.h"
40 #include "ompl/util/Exception.h"
41 #include <queue>
42 #include <boost/math/tools/toms748_solve.hpp>
43 
44 using namespace ompl::base;
45 
46 namespace
47 {
48  constexpr double onepi = boost::math::constants::pi<double>();
49  constexpr double twopi = 2. * boost::math::constants::pi<double>();
50 
51  // tolerance for boost root finding algorithm
52  boost::math::tools::eps_tolerance<double> TOLERANCE(10);
53 
54  // max # iterations for doubling turning radius for initial solution path
55  constexpr unsigned int MAX_ITER = 64;
56 
57  void turn(const State *from, double turnRadius, double angle, State *state)
58  {
59  auto s0 = from->as<DubinsStateSpace::StateType>();
60  auto s1 = state->as<DubinsStateSpace::StateType>();
61  double theta = s0->getYaw(), phi = theta + angle, r = (angle > 0 ? turnRadius : -turnRadius);
62  s1->setXY(s0->getX() + r * (std::sin(phi) - std::sin(theta)),
63  s0->getY() + r * (-std::cos(phi) + std::cos(theta)));
64  s1->setYaw(phi);
65  }
66 
67 } // namespace
68 
69 VanaOwenStateSpace::VanaOwenStateSpace(double turningRadius, double maxPitch)
70  : VanaOwenStateSpace(turningRadius, {-maxPitch, maxPitch})
71 {
72 }
73 VanaOwenStateSpace::VanaOwenStateSpace(double turningRadius, std::pair<double, double> pitchRange)
74  : rho_(turningRadius), minPitch_(pitchRange.first), maxPitch_(pitchRange.second), dubinsSpace_(turningRadius)
75 {
76  setName("VanaOwen" + getName());
78  auto space = std::make_shared<RealVectorStateSpace>(4);
79  ompl::base::RealVectorBounds pitchBounds(4);
80  pitchBounds.setLow(3, minPitch_);
81  pitchBounds.setHigh(3, maxPitch_);
82  space->setBounds(pitchBounds);
83  addSubspace(space, 1.0);
84  addSubspace(std::make_shared<SO2StateSpace>(), 0.5);
85  lock();
86 }
87 
89 {
90  auto *state = new StateType();
91  allocStateComponents(state);
92  return state;
93 }
94 
96 {
97  class VanaOwenDefaultProjection : public ProjectionEvaluator
98  {
99  public:
100  VanaOwenDefaultProjection(const StateSpace *space) : ProjectionEvaluator(space)
101  {
102  }
103 
104  unsigned int getDimension() const override
105  {
106  return 3;
107  }
108 
109  void defaultCellSizes() override
110  {
111  cellSizes_.resize(3);
112  bounds_ = space_->as<VanaOwenStateSpace>()->getBounds();
113  bounds_.resize(3);
114  cellSizes_[0] = (bounds_.high[0] - bounds_.low[0]) / magic::PROJECTION_DIMENSION_SPLITS;
115  cellSizes_[1] = (bounds_.high[1] - bounds_.low[1]) / magic::PROJECTION_DIMENSION_SPLITS;
116  cellSizes_[2] = (bounds_.high[2] - bounds_.low[2]) / magic::PROJECTION_DIMENSION_SPLITS;
117  }
118 
119  void project(const State *state, Eigen::Ref<Eigen::VectorXd> projection) const override
120  {
121  projection = Eigen::Map<const Eigen::VectorXd>(
123  }
124  };
125 
126  registerDefaultProjection(std::make_shared<VanaOwenDefaultProjection>(this));
127 }
128 
129 DubinsStateSpace::StateType *VanaOwenStateSpace::get2DPose(double x, double y, double yaw) const
130 {
132  state->setXY(x, y);
133  state->setYaw(yaw);
134  return state;
135 }
136 
138 {
139  // in three cases the result is invalid:
140  // 1. path of type CCC (i.e., RLR or LRL)
141  // 2. pitch smaller than minPitch_
142  // 3. pitch greater than maxPitch_
143  if ((path.type_->at(1) != DubinsStateSpace::DUBINS_STRAIGHT) ||
144  (path.type_->at(0) == DubinsStateSpace::DUBINS_RIGHT && state->pitch() - path.length_[0] < minPitch_) ||
145  (path.type_->at(0) == DubinsStateSpace::DUBINS_LEFT && state->pitch() + path.length_[0] > maxPitch_))
146  {
147  return false;
148  }
149 
150  return true;
151 }
152 
153 bool VanaOwenStateSpace::decoupled(const StateType *from, const StateType *to, double radius, PathType &result,
154  std::array<DubinsStateSpace::StateType *, 3> &scratch) const
155 {
156  result.horizontalRadius_ = radius;
157  result.verticalRadius_ = 1. / std::sqrt(1. / (rho_ * rho_) - 1. / (radius * radius));
158  result.deltaZ_ = (*to)[2] - (*from)[2];
159  // note that we are exploiting properties of the memory layout of state types
160  result.pathXY_ = dubinsSpace_.dubins(from, to, radius);
161  result.phi_ = 0.;
162  result.numTurns_ = 0;
163 
164  // can't change altitude if vertical turning radius is infinite, but that's ok if we don't need a vertical turn
165  if (!std::isfinite(result.verticalRadius_))
166  {
167  if (std::abs(result.deltaZ_) < 1e-8 && std::abs(to->pitch() - from->pitch()) < 1e-8)
168  {
169  result.pathSZ_.type_ = &DubinsStateSpace::dubinsPathType[0]; // LSL type
170  result.pathSZ_.length_[0] = result.pathSZ_.length_[2] = 0.;
171  result.pathSZ_.length_[1] = result.deltaZ_;
172  return true;
173  }
174  else
175  return false;
176  }
177 
178  double len = radius * result.pathXY_.length();
179  auto startSZ = result.startSZ_, endSZ = scratch[0];
180 
181  startSZ->setXY(0., (*from)[2]);
182  startSZ->setYaw(from->pitch());
183  endSZ->setXY(len, (*to)[2]);
184  endSZ->setYaw(to->pitch());
185  result.pathSZ_ = dubinsSpace_.dubins(startSZ, endSZ, result.verticalRadius_);
186  if (isValid(result.pathSZ_, from))
187  {
188  // low altitude path
189  return true;
190  }
191 
192  double pitch = (result.deltaZ_ < 0) ? minPitch_ : maxPitch_, tanPitch = tan(pitch);
193  auto s1b = scratch[1], s2b = scratch[2];
194  double turnS, turnZ;
195  auto update = [&, this](double r, bool skipInit = false)
196  {
197  if (!skipInit)
198  {
199  result.horizontalRadius_ = r;
200  result.verticalRadius_ = 1. / std::sqrt(1. / (rho_ * rho_) - 1. / (r * r));
201  result.pathXY_ = dubinsSpace_.dubins(from, to, result.horizontalRadius_);
202  }
203  endSZ->setX((result.pathXY_.length() + twopi * result.numTurns_) * r);
204  turn(startSZ, result.verticalRadius_, pitch - from->pitch(), s1b);
205  assert(std::abs(s1b->getYaw() - pitch) < 1e-8);
206  dubinsSpace_.copyState(s2b, endSZ);
207  s2b->setYaw(s2b->getYaw() + onepi);
208  turn(s2b, result.verticalRadius_, pitch - to->pitch(), s2b);
209  assert(std::abs(s2b->getYaw() - pitch - onepi) < 1e-8);
210  turnS = (s1b->getX() - startSZ->getX()) + (endSZ->getX() - s2b->getX());
211  turnZ = (s1b->getY() - startSZ->getY()) + (endSZ->getY() - s2b->getY());
212  };
213  update(radius, true);
214 
215  double highAltitudeS = len + twopi * radius;
216  double highAltitudeZ = turnZ + (highAltitudeS - turnS) * tanPitch;
217  if (std::abs(result.deltaZ_) > std::abs(highAltitudeZ))
218  {
219  // high altitude path
220  result.numTurns_ = std::floor((std::abs((result.deltaZ_ - turnZ) / tanPitch) - len + turnS) / (twopi * radius));
221  auto radiusFun = [&, this](double r)
222  {
223  update(r);
224  result.pathSZ_ = dubinsSpace_.dubins(startSZ, endSZ, result.verticalRadius_);
225  return ((result.pathXY_.length() + twopi * result.numTurns_) * r - turnS) * tanPitch + turnZ -
226  result.deltaZ_;
227  };
228  std::uintmax_t iter = MAX_ITER;
229  try
230  {
231  auto root = boost::math::tools::toms748_solve(radiusFun, radius, 3. * radius, TOLERANCE, iter);
232  auto rval = radiusFun(.5 * (root.first + root.second));
233  if (iter >= MAX_ITER)
234  OMPL_WARN("Maximum number of iterations exceeded for high altitude Vana-Owen path");
235  return std::abs(rval) < 1e-4;
236  }
237  catch (std::domain_error& e)
238  {
239  return false;
240  }
241  }
242  else
243  {
244  // medium altitude path
245  auto zi = scratch[1];
246  auto phiFun = [&, this](double phi)
247  {
248  if (std::abs(phi)>twopi)
249  throw std::domain_error("phi too large");
250  turn(from, radius, phi, zi);
251  return (std::abs(phi) + dubinsSpace_.dubins(zi, to).length()) * radius * std::abs(tanPitch) - std::abs(result.deltaZ_);
252  };
253 
254  try
255  {
256  std::uintmax_t iter = MAX_ITER;
257  result.phi_ = 0.1;
258  auto root = boost::math::tools::bracket_and_solve_root(phiFun, result.phi_, 2., true, TOLERANCE, iter);
259  result.phi_ = .5 * (root.first + root.second);
260  if (std::abs(phiFun(result.phi_)) > .01)
261  throw std::domain_error("fail");
262  }
263  catch (...)
264  {
265  try {
266  std::uintmax_t iter = MAX_ITER;
267  result.phi_ = -.1;
268  auto root = boost::math::tools::bracket_and_solve_root(phiFun, result.phi_, 2., true, TOLERANCE, iter);
269  result.phi_ = .5 * (root.first + root.second);
270  }
271  catch (...)
272  {
273  //OMPL_ERROR("this shouldn't be happening!");
274  return false;
275  }
276  }
277  result.pathXY_ = dubinsSpace_.dubins(zi, to, radius);
278  endSZ->setX((result.pathXY_.length() + result.phi_) * radius);
279  result.pathSZ_ = dubinsSpace_.dubins(startSZ, endSZ, result.verticalRadius_);
280  return std::abs(phiFun(result.phi_)) < .01 && isValid(result.pathSZ_, from);
281  }
282  return true;
283 }
284 
285 std::optional<VanaOwenStateSpace::PathType> VanaOwenStateSpace::getPath(const State *state1, const State *state2) const
286 {
287  auto from = state1->as<StateType>(), to = state2->as<StateType>();
288  double radiusMultiplier = 1.5;
289  std::array<DubinsStateSpace::StateType *, 3> scratch;
290  PathType path;
291 
292  unsigned int iter = 0;
293  std::generate(scratch.begin(), scratch.end(),
294  [this]() { return dubinsSpace_.allocState()->as<DubinsStateSpace::StateType>(); });
295 
296  while (!decoupled(from, to, rho_ * radiusMultiplier, path, scratch) && iter++ < MAX_ITER)
297  {
298  radiusMultiplier *= 2.;
299  }
300  if (iter >= MAX_ITER)
301  {
302  OMPL_ERROR("Maximum number of iterations exceeded in VanaOwenStateSpace::PathType");
303  for (auto s : scratch)
305  return {};
306  }
307 
308  // Local optimalization between horizontal and vertical radii
309  double step = .1, radiusMultiplier2, minLength = path.length(), length;
310  PathType path2;
311  while (std::abs(step) > tolerance_)
312  {
313  radiusMultiplier2 = std::max(1., radiusMultiplier + step);
314  if (decoupled(from, to, rho_ * radiusMultiplier2, path2, scratch) && (length = path2.length()) < minLength)
315  {
316  radiusMultiplier = radiusMultiplier2;
317  path = path2;
318  minLength = length;
319  step *= 2.;
320  }
321  else
322  step *= -.1;
323  }
324 
325  for (auto s : scratch)
327  return path;
328 }
329 
330 double VanaOwenStateSpace::distance(const State *state1, const State *state2) const
331 {
332  if (auto path = getPath(state1, state2))
333  return path->length();
334  return getMaximumExtent();
335 }
336 
337 unsigned int VanaOwenStateSpace::validSegmentCount(const State *state1, const State *state2) const
338 {
339  return StateSpace::validSegmentCount(state1, state2);
340 }
341 
342 void VanaOwenStateSpace::interpolate(const State *from, const State *to, const double t, State *state) const
343 {
344  if (auto path = getPath(from, to))
345  interpolate(from, to, t, *path, state);
346  else
347  if (from != state)
348  copyState(state, from);
349 }
350 
351 void VanaOwenStateSpace::interpolate(const State *from, const State *to, const double t, PathType &path,
352  State *state) const
353 {
354  if (t >= 1.)
355  {
356  if (to != state)
357  copyState(state, to);
358  return;
359  }
360  if (t <= 0.)
361  {
362  if (from != state)
363  copyState(state, from);
364  return;
365  }
366 
367  auto intermediate = (from == state) ? dubinsSpace_.allocState() : state;
368  auto s = state->as<StateType>();
369  auto i = intermediate->as<DubinsStateSpace::StateType>();
370 
371  // This is exploiting internal properties of compound state spaces like DubinsStateSpace
372  // and VanaOwenStateSpace
373  dubinsSpace_.interpolate(path.startSZ_, path.pathSZ_, t, intermediate, path.verticalRadius_);
374  (*s)[2] = i->getY();
375  s->pitch() = i->getYaw();
376 
377  if (path.phi_ == 0.)
378  {
379  if (path.numTurns_ == 0)
380  {
381  // low altitude path
382  dubinsSpace_.interpolate(from, path.pathXY_, t, state, path.horizontalRadius_);
383  }
384  else
385  {
386  // high altitude path
387  auto lengthSpiral = twopi * path.horizontalRadius_ * path.numTurns_;
388  auto lengthPath = path.horizontalRadius_ * path.pathXY_.length();
389  auto length = lengthSpiral + lengthPath, dist = t * length;
390  if (dist > lengthSpiral)
391  dubinsSpace_.interpolate(from, path.pathXY_, (dist - lengthSpiral) / lengthPath, state,
392  path.horizontalRadius_);
393  else
394  turn(from, path.horizontalRadius_, dist / path.horizontalRadius_, state);
395  }
396  }
397  else
398  {
399  // medium altitude path
400  auto lengthTurn = std::abs(path.phi_) * path.horizontalRadius_;
401  auto lengthPath = path.horizontalRadius_ * path.pathXY_.length();
402  auto length = lengthTurn + lengthPath, dist = t * length;
403  if (dist > lengthTurn)
404  {
405  State *s = (state == to) ? dubinsSpace_.allocState() : state;
406  turn(from, path.horizontalRadius_, path.phi_, s);
407  dubinsSpace_.interpolate(s, path.pathXY_, (dist - lengthTurn) / lengthPath, state, path.horizontalRadius_);
408  if (state == to)
410  }
411  else
412  {
413  auto angle = dist / path.horizontalRadius_;
414  if (path.phi_ < 0)
415  angle = -angle;
416  turn(from, path.horizontalRadius_, angle, state);
417  }
418  }
419 
420  if (from == state)
421  dubinsSpace_.freeState(intermediate);
422  getSubspace(1)->enforceBounds(state->as<CompoundStateSpace::StateType>()->as<SO2StateSpace::StateType>(1));
423 }
424 
425 VanaOwenStateSpace::PathType::~PathType()
426 {
427  static const DubinsStateSpace dubinsStateSpace_;
428  dubinsStateSpace_.freeState(startSZ_);
429 }
430 
431 VanaOwenStateSpace::PathType::PathType()
432 {
433  static const DubinsStateSpace dubinsStateSpace_;
434  startSZ_ = dubinsStateSpace_.allocState()->as<DubinsStateSpace::StateType>();
435 }
436 
437 VanaOwenStateSpace::PathType::PathType(const VanaOwenStateSpace::PathType &path)
438  : pathXY_(path.pathXY_)
439  , pathSZ_(path.pathSZ_)
440  , horizontalRadius_(path.horizontalRadius_)
441  , verticalRadius_(path.verticalRadius_)
442  , deltaZ_(path.deltaZ_)
443  , phi_(path.phi_)
444  , numTurns_(path.numTurns_)
445 {
446  static const DubinsStateSpace dubinsStateSpace_;
447  startSZ_ = dubinsStateSpace_.allocState()->as<DubinsStateSpace::StateType>();
448  dubinsStateSpace_.copyState(startSZ_, path.startSZ_);
449 }
450 
451 VanaOwenStateSpace::PathType &VanaOwenStateSpace::PathType::operator=(const VanaOwenStateSpace::PathType &path)
452 {
453  static const DubinsStateSpace dubinsStateSpace_;
454  pathXY_ = path.pathXY_;
455  pathSZ_ = path.pathSZ_;
456  horizontalRadius_ = path.horizontalRadius_;
457  verticalRadius_ = path.verticalRadius_;
458  deltaZ_ = path.deltaZ_;
459  phi_ = path.phi_;
460  numTurns_ = path.numTurns_;
461  dubinsStateSpace_.copyState(startSZ_, path.startSZ_);
462  return *this;
463 }
464 
465 double VanaOwenStateSpace::PathType::length() const
466 {
467  return verticalRadius_ * pathSZ_.length();
468 }
469 
470 VanaOwenStateSpace::PathCategory VanaOwenStateSpace::PathType::category() const
471 {
472  if (phi_ == 0.)
473  {
474  if (numTurns_ == 0)
475  return PathCategory::LOW_ALTITUDE;
476  else
477  return PathCategory::HIGH_ALTITUDE;
478  }
479  else
480  {
481  if (numTurns_ == 0)
482  return PathCategory::MEDIUM_ALTITUDE;
483  else
484  return PathCategory::UNKNOWN;
485  }
486 }
487 
488 namespace ompl::base
489 {
490  std::ostream &operator<<(std::ostream &os, const VanaOwenStateSpace::PathType &path)
491  {
492  static const DubinsStateSpace dubinsStateSpace;
493 
494  os << "VanaOwenPath[ category = " << (char)path.category() << "\n\tlength = " << path.length()
495  << "\n\tXY = " << path.pathXY_ << "\n\tSZ = " << path.pathSZ_ << "\n\trh = " << path.horizontalRadius_
496  << "\n\trv = " << path.verticalRadius_ << "\n\tdeltaZ = " << path.deltaZ_ << "\n\tphi = " << path.phi_
497  << "\n\tnumTurns = " << path.numTurns_ << "\n\tstartSZ = ";
498  dubinsStateSpace.printState(path.startSZ_, os);
499  os << "]";
500  return os;
501  }
502 } // namespace ompl::base
Definition of a compound state.
Definition: State.h:150
std::optional< PathType > getPath(const State *state1, const State *state2) const
Compute a 3D Dubins path using the model and algorithm proposed by VanaOwen et al.
std::ostream & operator<<(std::ostream &stream, Cost c)
Output operator for Cost.
Definition: Cost.cpp:39
State * allocState() const override
Allocate a state that can store a point in the described space.
static const std::vector< std::vector< DubinsPathSegmentType > > dubinsPathType
Dubins path types.
Representation of a space in which planning can be performed. Topology specific sampling,...
Definition: StateSpace.h:134
void interpolate(const State *from, const State *to, double t, State *state) const override
Computes the state that lies at time t in [0, 1] on the segment that connects from state to to state....
const T * as(unsigned int index) const
Cast a component of this instance to a desired type.
Definition: State.h:159
An R^4 x SO(2) state space where distance is measured by the length of a type of Dubins airplane curv...
Definition of an abstract state.
Definition: State.h:113
const StateSpacePtr & getSubspace(unsigned int index) const
Get a specific subspace from the compound state space.
Definition: StateSpace.cpp:915
This namespace contains sampling based planning routines shared by both planning under geometric cons...
bool isValid(DubinsStateSpace::DubinsPath const &path, StateType const *state) const
Whether a path in SZ space satisfies Dubins path type and pitch constraints.
unsigned int validSegmentCount(const State *state1, const State *state2) const override
Count how many segments of the "longest valid length" fit on the motion from state1 to state2.
double * values
The value of the actual vector in Rn
unsigned int getDimension() const override
Get the dimension of the space (not the dimension of the surrounding ambient space)
Definition: StateSpace.cpp:994
bool decoupled(const StateType *state1, const StateType *state2, double radius, PathType &path, std::array< DubinsStateSpace::StateType *, 3 > &scratch) const
Helper function used by getPath.
const T * as() const
Cast this instance to a desired type.
Definition: State.h:162
void printState(const State *state, std::ostream &out) const override
Print a state to a stream.
const RealVectorBounds & getBounds() const
Get the bounds for this state space.
void registerDefaultProjection(const ProjectionEvaluatorPtr &projection)
Register the default projection for this state space.
Definition: StateSpace.cpp:752
double getMaximumExtent() const override
Get the maximum value a call to distance() can return (or an upper bound). For unbounded state spaces...
void copyState(State *destination, const State *source) const override
Copy a state to another. The memory of source and destination should NOT overlap.
Abstract definition for a class computing projections to Rn. Implicit integer grids are imposed on th...
An SE(2) state space where distance is measured by the length of Dubins curves.
const std::string & getName() const
Get the name of the state space.
Definition: StateSpace.cpp:196
double distance(const State *state1, const State *state2) const override
Computes distance between two states. This function satisfies the properties of a metric if isMetricS...
void registerProjections() override
Register the projections for this state space. Usually, this is at least the default projection....
The definition of a state in SO(2)
static const double PROJECTION_DIMENSION_SPLITS
When the cell sizes for a projection are automatically computed, this value defines the number of par...
void setName(const std::string &name)
Set the name of the state space.
Definition: StateSpace.cpp:201
int type_
A type assigned for this state space.
Definition: StateSpace.h:595
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
Definition: Console.h:66
void allocStateComponents(CompoundState *state) const
Allocate the state components. Called by allocState(). Usually called by derived state spaces.
ompl::base::CompoundState StateType
Define the type of state allocated by this state space.
Definition: StateSpace.h:641
Complete description of a Dubins path.
DubinsStateSpace::StateType * get2DPose(double x, double y, double yaw) const
Allocate a DubinsSpace state and initialize it.
DubinsPath dubins(const State *state1, const State *state2) const
Return a shortest Dubins path from SE(2) state state1 to SE(2) state state2.
A state in SE(2): (x, y, yaw)
@ STATE_SPACE_VANA_OWEN
ompl::base::VanaOwenStateSpace
void freeState(State *state) const override
Free the memory of the allocated state.
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
void interpolate(const State *from, const State *to, double t, State *state) const override
Computes the state that lies at time t in [0, 1] on the segment that connects from state to to state....
State * allocState() const override
Allocate a state that can store a point in the described space.
virtual unsigned int validSegmentCount(const State *state1, const State *state2) const
Count how many segments of the "longest valid length" fit on the motion from state1 to state2.
Definition: StateSpace.cpp:851
The lower and upper bounds for an Rn space.