RealVectorStateSpace.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/base/spaces/RealVectorStateSpace.h"
38 #include "ompl/base/spaces/RealVectorStateProjections.h"
39 #include "ompl/util/Exception.h"
40 #include <algorithm>
41 #include <cstring>
42 #include <limits>
43 #include <cmath>
44 
46 {
47  const unsigned int dim = space_->getDimension();
48  const RealVectorBounds &bounds = static_cast<const RealVectorStateSpace*>(space_)->getBounds();
49 
51  for (unsigned int i = 0 ; i < dim ; ++i)
52  rstate->values[i] = rng_.uniformReal(bounds.low[i], bounds.high[i]);
53 }
54 
55 void ompl::base::RealVectorStateSampler::sampleUniformNear(State *state, const State *near, const double distance)
56 {
57  const unsigned int dim = space_->getDimension();
58  const RealVectorBounds &bounds = static_cast<const RealVectorStateSpace*>(space_)->getBounds();
59 
61  const RealVectorStateSpace::StateType *rnear = static_cast<const RealVectorStateSpace::StateType*>(near);
62  for (unsigned int i = 0 ; i < dim ; ++i)
63  rstate->values[i] =
64  rng_.uniformReal(std::max(bounds.low[i], rnear->values[i] - distance),
65  std::min(bounds.high[i], rnear->values[i] + distance));
66 }
67 
68 void ompl::base::RealVectorStateSampler::sampleGaussian(State *state, const State *mean, const double stdDev)
69 {
70  const unsigned int dim = space_->getDimension();
71  const RealVectorBounds &bounds = static_cast<const RealVectorStateSpace*>(space_)->getBounds();
72 
74  const RealVectorStateSpace::StateType *rmean = static_cast<const RealVectorStateSpace::StateType*>(mean);
75  for (unsigned int i = 0 ; i < dim ; ++i)
76  {
77  double v = rng_.gaussian(rmean->values[i], stdDev);
78  if (v < bounds.low[i])
79  v = bounds.low[i];
80  else
81  if (v > bounds.high[i])
82  v = bounds.high[i];
83  rstate->values[i] = v;
84  }
85 }
86 
88 {
89  // compute a default random projection
90  if (dimension_ > 0)
91  {
92  if (dimension_ > 2)
93  {
94  int p = std::max(2, (int)ceil(log((double)dimension_)));
95  registerDefaultProjection(ProjectionEvaluatorPtr(new RealVectorRandomLinearProjectionEvaluator(this, p)));
96  }
97  else
98  registerDefaultProjection(ProjectionEvaluatorPtr(new RealVectorIdentityProjectionEvaluator(this)));
99  }
100 }
101 
103 {
104  bounds_.check();
106 }
107 
108 void ompl::base::RealVectorStateSpace::addDimension(const std::string &name, double minBound, double maxBound)
109 {
110  addDimension(minBound, maxBound);
111  setDimensionName(dimension_ - 1, name);
112 }
113 
114 void ompl::base::RealVectorStateSpace::addDimension(double minBound, double maxBound)
115 {
116  dimension_++;
117  stateBytes_ = dimension_ * sizeof(double);
118  bounds_.low.push_back(minBound);
119  bounds_.high.push_back(maxBound);
120  dimensionNames_.resize(dimension_, "");
121 }
122 
124 {
125  bounds.check();
126  if (bounds.low.size() != dimension_)
127  throw Exception("Bounds do not match dimension of state space: expected dimension " +
128  std::to_string(dimension_) + " but got dimension " +
129  std::to_string(bounds.low.size()));
130  bounds_ = bounds;
131 }
132 
133 void ompl::base::RealVectorStateSpace::setBounds(double low, double high)
134 {
135  RealVectorBounds bounds(dimension_);
136  bounds.setLow(low);
137  bounds.setHigh(high);
138  setBounds(bounds);
139 }
140 
142 {
143  return dimension_;
144 }
145 
146 const std::string& ompl::base::RealVectorStateSpace::getDimensionName(unsigned int index) const
147 {
148  if (index < dimensionNames_.size())
149  return dimensionNames_[index];
150  throw Exception("Index out of bounds");
151 }
152 
153 int ompl::base::RealVectorStateSpace::getDimensionIndex(const std::string &name) const
154 {
155  std::map<std::string, unsigned int>::const_iterator it = dimensionIndex_.find(name);
156  return it != dimensionIndex_.end() ? (int)it->second : -1;
157 }
158 
159 void ompl::base::RealVectorStateSpace::setDimensionName(unsigned int index, const std::string &name)
160 {
161  if (index < dimensionNames_.size())
162  {
163  dimensionNames_[index] = name;
164  dimensionIndex_[name] = index;
165  }
166  else
167  throw Exception("Cannot set dimension name. Index out of bounds");
168 }
169 
171 {
172  double e = 0.0;
173  for (unsigned int i = 0 ; i < dimension_ ; ++i)
174  {
175  double d = bounds_.high[i] - bounds_.low[i];
176  e += d*d;
177  }
178  return sqrt(e);
179 }
180 
182 {
183  double m = 1.0;
184  for (unsigned int i = 0 ; i < dimension_ ; ++i)
185  {
186  m *= bounds_.high[i] - bounds_.low[i];
187  }
188  return m;
189 }
190 
192 {
193  StateType *rstate = static_cast<StateType*>(state);
194  for (unsigned int i = 0 ; i < dimension_ ; ++i)
195  {
196  if (rstate->values[i] > bounds_.high[i])
197  rstate->values[i] = bounds_.high[i];
198  else
199  if (rstate->values[i] < bounds_.low[i])
200  rstate->values[i] = bounds_.low[i];
201  }
202 }
203 
205 {
206  const StateType *rstate = static_cast<const StateType*>(state);
207  for (unsigned int i = 0 ; i < dimension_ ; ++i)
208  if (rstate->values[i] - std::numeric_limits<double>::epsilon() > bounds_.high[i] ||
209  rstate->values[i] + std::numeric_limits<double>::epsilon() < bounds_.low[i])
210  return false;
211  return true;
212 }
213 
214 void ompl::base::RealVectorStateSpace::copyState(State *destination, const State *source) const
215 {
216  memcpy(static_cast<StateType*>(destination)->values,
217  static_cast<const StateType*>(source)->values, stateBytes_);
218 }
219 
221 {
222  return stateBytes_;
223 }
224 
225 void ompl::base::RealVectorStateSpace::serialize(void *serialization, const State *state) const
226 {
227  memcpy(serialization, state->as<StateType>()->values, stateBytes_);
228 }
229 
230 void ompl::base::RealVectorStateSpace::deserialize(State *state, const void *serialization) const
231 {
232  memcpy(state->as<StateType>()->values, serialization, stateBytes_);
233 }
234 
235 double ompl::base::RealVectorStateSpace::distance(const State *state1, const State *state2) const
236 {
237  double dist = 0.0;
238  const double *s1 = static_cast<const StateType*>(state1)->values;
239  const double *s2 = static_cast<const StateType*>(state2)->values;
240 
241  for (unsigned int i = 0 ; i < dimension_ ; ++i)
242  {
243  double diff = (*s1++) - (*s2++);
244  dist += diff * diff;
245  }
246  return sqrt(dist);
247 }
248 
249 bool ompl::base::RealVectorStateSpace::equalStates(const State *state1, const State *state2) const
250 {
251  const double *s1 = static_cast<const StateType*>(state1)->values;
252  const double *s2 = static_cast<const StateType*>(state2)->values;
253  for (unsigned int i = 0 ; i < dimension_ ; ++i)
254  {
255  double diff = (*s1++) - (*s2++);
256  if (fabs(diff) > std::numeric_limits<double>::epsilon() * 2.0)
257  return false;
258  }
259  return true;
260 }
261 
262 void ompl::base::RealVectorStateSpace::interpolate(const State *from, const State *to, const double t, State *state) const
263 {
264  const StateType *rfrom = static_cast<const StateType*>(from);
265  const StateType *rto = static_cast<const StateType*>(to);
266  const StateType *rstate = static_cast<StateType*>(state);
267  for (unsigned int i = 0 ; i < dimension_ ; ++i)
268  rstate->values[i] = rfrom->values[i] + (rto->values[i] - rfrom->values[i]) * t;
269 }
270 
272 {
273  return StateSamplerPtr(new RealVectorStateSampler(this));
274 }
275 
277 {
278  StateType *rstate = new StateType();
279  rstate->values = new double[dimension_];
280  return rstate;
281 }
282 
284 {
285  StateType *rstate = static_cast<StateType*>(state);
286  delete[] rstate->values;
287  delete rstate;
288 }
289 
290 double* ompl::base::RealVectorStateSpace::getValueAddressAtIndex(State *state, const unsigned int index) const
291 {
292  return index < dimension_ ? static_cast<StateType*>(state)->values + index : nullptr;
293 }
294 
295 void ompl::base::RealVectorStateSpace::printState(const State *state, std::ostream &out) const
296 {
297  out << "RealVectorState [";
298  if (state)
299  {
300  const StateType *rstate = static_cast<const StateType*>(state);
301  for (unsigned int i = 0 ; i < dimension_ ; ++i)
302  {
303  out << rstate->values[i];
304  if (i + 1 < dimension_)
305  out << ' ';
306  }
307  }
308  else
309  out << "nullptr" << std::endl;
310  out << ']' << std::endl;
311 }
312 
314 {
315  out << "Real vector state space '" << getName() << "' of dimension " << dimension_ << " with bounds: " << std::endl;
316  out << " - min: ";
317  for (unsigned int i = 0 ; i < dimension_ ; ++i)
318  out << bounds_.low[i] << " ";
319  out << std::endl;
320  out << " - max: ";
321  for (unsigned int i = 0 ; i < dimension_ ; ++i)
322  out << bounds_.high[i] << " ";
323  out << std::endl;
324 
325  bool printNames = false;
326  for (unsigned int i = 0 ; i < dimension_ ; ++i)
327  if (!dimensionNames_[i].empty())
328  printNames = true;
329  if (printNames)
330  {
331  out << " and dimension names: ";
332  for (unsigned int i = 0 ; i < dimension_ ; ++i)
333  out << "'" << dimensionNames_[i] << "' ";
334  out << std::endl;
335  }
336 }
int getDimensionIndex(const std::string &name) const
Get the index of a specific dimension, by name. Return -1 if name is not found.
const StateSpace * space_
The state space this sampler samples.
Definition: StateSampler.h:107
State sampler for the Rn state space.
virtual bool satisfiesBounds(const State *state) const
Check if a state is inside the bounding box. For unbounded spaces this function can always return tru...
void log(const char *file, int line, LogLevel level, const char *m,...)
Root level logging function. This should not be invoked directly, but rather used via a logging macro...
Definition: Console.cpp:120
std::vector< double > low
Lower bound.
virtual void copyState(State *destination, const State *source) const
Copy a state to another. The memory of source and destination should NOT overlap. ...
A shared pointer wrapper for ompl::base::StateSampler.
RNG rng_
An instance of a random number generator.
Definition: StateSampler.h:110
virtual unsigned int getDimension() const =0
Get the dimension of the space (not the dimension of the surrounding ambient space) ...
virtual double getMeasure() const
Get a measure of the space (this can be thought of as a generalization of volume) ...
virtual unsigned int getSerializationLength() const
Get the number of chars in the serialization of a state in this space.
const std::string & getDimensionName(unsigned int index) const
Each dimension can optionally have a name associated to it. If it does, this function returns that na...
virtual void sampleUniformNear(State *state, const State *near, const double distance)
Sample a state such that each component state[i] is uniformly sampled from [near[i]-distance, near[i]+distance]. If this interval exceeds the state space bounds, the interval is truncated.
virtual State * allocState() const
Allocate a state that can store a point in the described space.
virtual void deserialize(State *state, const void *serialization) const
Read the binary representation of a state from serialization and write it to state.
virtual void enforceBounds(State *state) const
Bring the state within the bounds of the state space. For unbounded spaces this function can be a no-...
virtual double getMaximumExtent() const
Get the maximum value a call to distance() can return (or an upper bound). For unbounded state spaces...
virtual void registerProjections()
Register the projections for this state space. Usually, this is at least the default projection...
virtual double * getValueAddressAtIndex(State *state, const unsigned int index) const
Many states contain a number of double values. This function provides a means to get the memory addre...
Definition for a class computing a random linear projections.
virtual void freeState(State *state) const
Free the memory of the allocated state.
void setLow(double value)
Set the lower bound in each dimension to a specific value.
virtual StateSamplerPtr allocDefaultStateSampler() const
Allocate an instance of the default uniform state sampler for this space.
void setHigh(double value)
Set the upper bound in each dimension to a specific value.
virtual void printSettings(std::ostream &out) const
Print the settings for this state space to a stream.
std::vector< double > high
Upper bound.
A shared pointer wrapper for ompl::base::ProjectionEvaluator.
double uniformReal(double lower_bound, double upper_bound)
Generate a random real within given bounds: [lower_bound, upper_bound)
Definition: RandomNumbers.h:75
A state space representing Rn. The distance function is the L2 norm.
virtual void setup()
Perform final setup steps. This function is automatically called by the SpaceInformation. If any default projections are to be registered, this call will set them and call their setup() functions. It is safe to call this function multiple times. At a subsequent call, projections that have been previously user configured are not re-instantiated, but their setup() method is still called.
Definition: StateSpace.cpp:236
Definition of an abstract state.
Definition: State.h:50
virtual void sampleGaussian(State *state, const State *mean, const double stdDev)
Sample a state such that each component state[i] has a Gaussian distribution with mean mean[i] and st...
void setDimensionName(unsigned int index, const std::string &name)
Set the name of a dimension.
void check() const
Check if the bounds are valid (same length for low and high, high[i] > low[i]). Throw an exception if...
virtual bool equalStates(const State *state1, const State *state2) const
Checks whether two states are equal.
The exception type for ompl.
Definition: Exception.h:47
The lower and upper bounds for an Rn space.
double * values
The value of the actual vector in Rn
virtual void printState(const State *state, std::ostream &out) const
Print a state to a stream.
virtual void serialize(void *serialization, const State *state) const
Write the binary representation of state to serialization.
void addDimension(double minBound=0.0, double maxBound=0.0)
Increase the dimensionality of the state space by 1. Optionally, bounds can be specified for this add...
virtual unsigned int getDimension() const
Get the dimension of the space (not the dimension of the surrounding ambient space) ...
const T * as() const
Cast this instance to a desired type.
Definition: State.h:74
virtual double distance(const State *state1, const State *state2) const
Computes distance between two states. This function satisfies the properties of a metric if isMetricS...
virtual void sampleUniform(State *state)
Sample a state.
virtual void interpolate(const State *from, const State *to, const double t, State *state) const
Computes the state that lies at time t in [0, 1] on the segment that connects from state to to state...
virtual void setup()
Perform final setup steps. This function is automatically called by the SpaceInformation. If any default projections are to be registered, this call will set them and call their setup() functions. It is safe to call this function multiple times. At a subsequent call, projections that have been previously user configured are not re-instantiated, but their setup() method is still called.
void setBounds(const RealVectorBounds &bounds)
Set the bounds of this state space. This defines the range of the space in which sampling is performe...