OpenDEStateSpace.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/extensions/opende/OpenDEStateSpace.h"
38 #include "ompl/util/Console.h"
39 #include <limits>
40 #include <queue>
41 
43  double positionWeight, double linVelWeight, double angVelWeight, double orientationWeight) :
44  base::CompoundStateSpace(), env_(env)
45 {
46  setName("OpenDE" + getName());
48  for (unsigned int i = 0 ; i < env_->stateBodies_.size() ; ++i)
49  {
50  std::string body = ":B" + std::to_string(i);
51 
52  addSubspace(base::StateSpacePtr(new base::RealVectorStateSpace(3)), positionWeight); // position
53  components_.back()->setName(components_.back()->getName() + body + ":position");
54 
55  addSubspace(base::StateSpacePtr(new base::RealVectorStateSpace(3)), linVelWeight); // linear velocity
56  components_.back()->setName(components_.back()->getName() + body + ":linvel");
57 
58  addSubspace(base::StateSpacePtr(new base::RealVectorStateSpace(3)), angVelWeight); // angular velocity
59  components_.back()->setName(components_.back()->getName() + body + ":angvel");
60 
61  addSubspace(base::StateSpacePtr(new base::SO3StateSpace()), orientationWeight); // orientation
62  components_.back()->setName(components_.back()->getName() + body + ":orientation");
63  }
64  lock();
66 }
67 
69 {
70  // limit all velocities to 1 m/s, 1 rad/s, respectively
71  base::RealVectorBounds bounds1(3);
72  bounds1.setLow(-1);
73  bounds1.setHigh(1);
74  setLinearVelocityBounds(bounds1);
75  setAngularVelocityBounds(bounds1);
76 
77  // find the bounding box that contains all geoms included in the collision spaces
78  double mX, mY, mZ, MX, MY, MZ;
79  mX = mY = mZ = std::numeric_limits<double>::infinity();
80  MX = MY = MZ = -std::numeric_limits<double>::infinity();
81  bool found = false;
82 
83  std::queue<dSpaceID> spaces;
84  for (unsigned int i = 0 ; i < env_->collisionSpaces_.size() ; ++i)
85  spaces.push(env_->collisionSpaces_[i]);
86 
87  while (!spaces.empty())
88  {
89  dSpaceID space = spaces.front();
90  spaces.pop();
91 
92  int n = dSpaceGetNumGeoms(space);
93 
94  for (int j = 0 ; j < n ; ++j)
95  {
96  dGeomID geom = dSpaceGetGeom(space, j);
97  if (dGeomIsSpace(geom))
98  spaces.push((dSpaceID)geom);
99  else
100  {
101  bool valid = true;
102  dReal aabb[6];
103  dGeomGetAABB(geom, aabb);
104 
105  // things like planes are infinite; we want to ignore those
106  for (int k = 0 ; k < 6 ; ++k)
107  if (fabs(aabb[k]) >= std::numeric_limits<dReal>::max())
108  {
109  valid = false;
110  break;
111  }
112  if (valid)
113  {
114  found = true;
115  if (aabb[0] < mX) mX = aabb[0];
116  if (aabb[1] > MX) MX = aabb[1];
117  if (aabb[2] < mY) mY = aabb[2];
118  if (aabb[3] > MY) MY = aabb[3];
119  if (aabb[4] < mZ) mZ = aabb[4];
120  if (aabb[5] > MZ) MZ = aabb[5];
121  }
122  }
123  }
124  }
125 
126  if (found)
127  {
128  double dx = MX - mX;
129  double dy = MY - mY;
130  double dz = MZ - mZ;
131  double dM = std::max(dx, std::max(dy, dz));
132 
133  // add 10% in each dimension + 1% of the max dimension
134  dx = dx / 10.0 + dM / 100.0;
135  dy = dy / 10.0 + dM / 100.0;
136  dz = dz / 10.0 + dM / 100.0;
137 
138  bounds1.low[0] = mX - dx;
139  bounds1.high[0] = MX + dx;
140  bounds1.low[1] = mY - dy;
141  bounds1.high[1] = MY + dy;
142  bounds1.low[2] = mZ - dz;
143  bounds1.high[2] = MZ + dz;
144 
145  setVolumeBounds(bounds1);
146  }
147 }
148 
150 {
151  CompoundStateSpace::copyState(destination, source);
152  destination->as<StateType>()->collision = source->as<StateType>()->collision;
153 }
154 
155 namespace ompl
156 {
158  struct CallbackParam
159  {
160  const control::OpenDEEnvironment *env;
161  bool collision;
162  };
163 
164  static void nearCallback(void *data, dGeomID o1, dGeomID o2)
165  {
166  // if a collision has not already been detected
167  if (reinterpret_cast<CallbackParam*>(data)->collision == false)
168  {
169  dBodyID b1 = dGeomGetBody(o1);
170  dBodyID b2 = dGeomGetBody(o2);
171  if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) return;
172 
173  dContact contact[1]; // one contact is sufficient
174  int numc = dCollide(o1, o2, 1, &contact[0].geom, sizeof(dContact));
175 
176  // check if there is really a collision
177  if (numc)
178  {
179  // check if the collision is allowed
180  bool valid = reinterpret_cast<CallbackParam*>(data)->env->isValidCollision(o1, o2, contact[0]);
181  reinterpret_cast<CallbackParam*>(data)->collision = !valid;
182  if (reinterpret_cast<CallbackParam*>(data)->env->verboseContacts_)
183  {
184  OMPL_DEBUG("%s contact between %s and %s", (valid ? "Valid" : "Invalid"),
185  reinterpret_cast<CallbackParam*>(data)->env->getGeomName(o1).c_str(),
186  reinterpret_cast<CallbackParam*>(data)->env->getGeomName(o2).c_str());
187  }
188  }
189  }
190  }
192 }
193 
195 {
196  if (state->as<StateType>()->collision & (1 << STATE_COLLISION_KNOWN_BIT))
197  return state->as<StateType>()->collision & (1 << STATE_COLLISION_VALUE_BIT);
198  env_->mutex_.lock();
199  writeState(state);
200  CallbackParam cp = { env_.get(), false };
201  for (unsigned int i = 0 ; cp.collision == false && i < env_->collisionSpaces_.size() ; ++i)
202  dSpaceCollide(env_->collisionSpaces_[i], &cp, &nearCallback);
203  env_->mutex_.unlock();
204  if (cp.collision)
205  state->as<StateType>()->collision &= (1 << STATE_COLLISION_VALUE_BIT);
206  state->as<StateType>()->collision &= (1 << STATE_COLLISION_KNOWN_BIT);
207  return cp.collision;
208 }
209 
211 {
212  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
213  if (i % 4 != 3)
214  if (!components_[i]->satisfiesBounds(state->components[i]))
215  return false;
216  return true;
217 }
218 
220 {
221  for (unsigned int i = 0 ; i < env_->stateBodies_.size() ; ++i)
222  components_[i * 4]->as<base::RealVectorStateSpace>()->setBounds(bounds);
223 }
224 
226 {
227  for (unsigned int i = 0 ; i < env_->stateBodies_.size() ; ++i)
228  components_[i * 4 + 1]->as<base::RealVectorStateSpace>()->setBounds(bounds);
229 }
230 
232 {
233  for (unsigned int i = 0 ; i < env_->stateBodies_.size() ; ++i)
234  components_[i * 4 + 2]->as<base::RealVectorStateSpace>()->setBounds(bounds);
235 }
236 
238 {
239  StateType *state = new StateType();
240  allocStateComponents(state);
241  return state;
242 }
243 
245 {
246  CompoundStateSpace::freeState(state);
247 }
248 
249 // this function should most likely not be used with OpenDE propagations, but just in case it is called, we need to make sure the collision information
250 // is cleared from the resulting state
251 void ompl::control::OpenDEStateSpace::interpolate(const base::State *from, const base::State *to, const double t, base::State *state) const
252 {
253  CompoundStateSpace::interpolate(from, to, t, state);
254  state->as<StateType>()->collision = 0;
255 }
256 
258 namespace ompl
259 {
260  namespace control
261  {
262  // we need to make sure any collision information is cleared when states are sampled (just in case this ever happens)
263  class WrapperForOpenDESampler : public ompl::base::StateSampler
264  {
265  public:
266  WrapperForOpenDESampler(const base::StateSpace *space, const base::StateSamplerPtr &wrapped) : base::StateSampler(space), wrapped_(wrapped)
267  {
268  }
269 
270  virtual void sampleUniform(ompl::base::State *state)
271  {
272  wrapped_->sampleUniform(state);
273  state->as<OpenDEStateSpace::StateType>()->collision = 0;
274  }
275 
276  virtual void sampleUniformNear(base::State *state, const base::State *near, const double distance)
277  {
278  wrapped_->sampleUniformNear(state, near, distance);
279  state->as<OpenDEStateSpace::StateType>()->collision = 0;
280  }
281 
282  virtual void sampleGaussian(base::State *state, const base::State *mean, const double stdDev)
283  {
284  wrapped_->sampleGaussian(state, mean, stdDev);
285  state->as<OpenDEStateSpace::StateType>()->collision = 0;
286  }
287  private:
288  base::StateSamplerPtr wrapped_;
289  };
290  }
291 }
293 
295 {
297  return base::StateSamplerPtr(new WrapperForOpenDESampler(this, sampler));
298 }
299 
301 {
303  if (dynamic_cast<WrapperForOpenDESampler*>(sampler.get()))
304  return sampler;
305  else
306  return base::StateSamplerPtr(new WrapperForOpenDESampler(this, sampler));
307 }
308 
310 {
311  StateType *s = state->as<StateType>();
312  for (int i = (int)env_->stateBodies_.size() - 1 ; i >= 0 ; --i)
313  {
314  unsigned int _i4 = i * 4;
315 
316  const dReal *pos = dBodyGetPosition(env_->stateBodies_[i]);
317  const dReal *vel = dBodyGetLinearVel(env_->stateBodies_[i]);
318  const dReal *ang = dBodyGetAngularVel(env_->stateBodies_[i]);
319  double *s_pos = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
320  double *s_vel = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
321  double *s_ang = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
322 
323  for (int j = 0; j < 3; ++j)
324  {
325  s_pos[j] = pos[j];
326  s_vel[j] = vel[j];
327  s_ang[j] = ang[j];
328  }
329 
330  const dReal *rot = dBodyGetQuaternion(env_->stateBodies_[i]);
332 
333  s_rot.w = rot[0];
334  s_rot.x = rot[1];
335  s_rot.y = rot[2];
336  s_rot.z = rot[3];
337  }
338  s->collision = 0;
339 }
340 
342 {
343  const StateType *s = state->as<StateType>();
344  for (int i = (int)env_->stateBodies_.size() - 1 ; i >= 0 ; --i)
345  {
346  unsigned int _i4 = i * 4;
347 
348  double *s_pos = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
349  dBodySetPosition(env_->stateBodies_[i], s_pos[0], s_pos[1], s_pos[2]);
350 
351  double *s_vel = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
352  dBodySetLinearVel(env_->stateBodies_[i], s_vel[0], s_vel[1], s_vel[2]);
353 
354  double *s_ang = s->as<base::RealVectorStateSpace::StateType>(_i4)->values; ++_i4;
355  dBodySetAngularVel(env_->stateBodies_[i], s_ang[0], s_ang[1], s_ang[2]);
356 
358  dQuaternion q;
359  q[0] = s_rot.w;
360  q[1] = s_rot.x;
361  q[2] = s_rot.y;
362  q[3] = s_rot.z;
363  dBodySetQuaternion(env_->stateBodies_[i], q);
364  }
365 }
Index of bit in StateType::collision indicating whether it is known if a state is in collision or not...
void setName(const std::string &name)
Set the name of the state space.
Definition: StateSpace.cpp:201
virtual StateSamplerPtr allocStateSampler() const
Allocate an instance of the state sampler for this space. This sampler will be allocated with the sam...
Definition: StateSpace.cpp:790
int type_
A type assigned for this state space.
Definition: StateSpace.h:508
void setVolumeBounds(const base::RealVectorBounds &bounds)
Set the bounds for each of the position subspaces.
std::vector< double > low
Lower bound.
virtual StateSamplerPtr allocDefaultStateSampler() const
Allocate an instance of the default uniform state sampler for this space.
A shared pointer wrapper for ompl::base::StateSpace.
virtual void readState(base::State *state) const
Read the parameters of the OpenDE bodies and store them in state.
A shared pointer wrapper for ompl::base::StateSampler.
void lock()
Lock this state space. This means no further spaces can be added as components. This function can be ...
Index of bit in StateType::collision indicating whether a state is in collision or not...
virtual void sampleUniform(State *state)=0
Sample a state.
void setAngularVelocityBounds(const base::RealVectorBounds &bounds)
Set the bounds for each of the angular velocity subspaces.
A state space representing SO(3). The internal representation is done with quaternions. The distance between states is the angle between quaternions and interpolation is done with slerp.
Definition: SO3StateSpace.h:84
CompoundState StateType
Define the type of state allocated by this state space.
Definition: StateSpace.h:554
virtual void writeState(const base::State *state) const
Set the parameters of the OpenDE bodies to be the ones read from state. The code will technically wor...
OpenDE State. This is a compound state that allows accessing the properties of the bodies the state s...
void allocStateComponents(CompoundState *state) const
Allocate the state components. Called by allocState(). Usually called by derived state spaces...
virtual base::State * allocState() const
Allocate a state that can store a point in the described space.
unsigned int componentCount_
The number of components.
Definition: StateSpace.h:715
bool satisfiesBoundsExceptRotation(const StateType *state) const
This is a convenience function provided for optimization purposes. It checks whether a state satisfie...
This class contains the OpenDE constructs OMPL needs to know about when planning. ...
virtual bool evaluateCollision(const base::State *source) const
Fill the OpenDEStateSpace::STATE_COLLISION_VALUE_BIT of StateType::collision member of a state...
double w
scalar component of quaternion
void setLow(double value)
Set the lower bound in each dimension to a specific value.
virtual base::StateSamplerPtr allocStateSampler() const
Allocate an instance of the state sampler for this space. This sampler will be allocated with the sam...
Main namespace. Contains everything in this library.
Definition: Cost.h:42
void setHigh(double value)
Set the upper bound in each dimension to a specific value.
void setDefaultBounds()
By default, the volume bounds enclosing the geometry of the environment are computed to include all o...
The definition of a state in SO(3) represented as a unit quaternion.
Definition: SO3StateSpace.h:94
OpenDEStateSpace(const OpenDEEnvironmentPtr &env, double positionWeight=1.0, double linVelWeight=0.5, double angVelWeight=0.5, double orientationWeight=1.0)
Construct a state space representing OpenDE states.
std::vector< double > high
Upper bound.
virtual void copyState(base::State *destination, const base::State *source) const
Copy a state to another. The memory of source and destination should NOT overlap. ...
A state space representing Rn. The distance function is the L2 norm.
Representation of a space in which planning can be performed. Topology specific sampling, interpolation and distance are defined.
Definition: StateSpace.h:72
Definition of an abstract state.
Definition: State.h:50
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 base::StateSamplerPtr allocDefaultStateSampler() const
Allocate an instance of the default uniform state sampler for this space.
virtual void freeState(base::State *state) const
Free the memory of the allocated state.
void addSubspace(const StateSpacePtr &component, double weight)
Adds a new state space as part of the compound state space. For computing distances within the compou...
Definition: StateSpace.cpp:860
#define OMPL_DEBUG(fmt,...)
Log a formatted debugging string.
Definition: Console.h:70
virtual void interpolate(const base::State *from, const base::State *to, const double t, base::State *state) const
Computes the state that lies at time t in [0, 1] on the segment that connects from state to to state...
The lower and upper bounds for an Rn space.
State ** components
The components that make up a compound state.
Definition: State.h:142
Number of state space types; To add new types, use values that are larger than the count...
const std::string & getName() const
Get the name of the state space.
Definition: StateSpace.cpp:196
double z
Z component of quaternion vector.
Abstract definition of a state space sampler.
Definition: StateSampler.h:65
double y
Y component of quaternion vector.
const T * as() const
Cast this instance to a desired type.
Definition: State.h:74
void setLinearVelocityBounds(const base::RealVectorBounds &bounds)
Set the bounds for each of the linear velocity subspaces.
const T * as(const unsigned int index) const
Cast a component of this instance to a desired type.
Definition: State.h:109
int collision
Flag containing information about state validity.
std::vector< StateSpacePtr > components_
The state spaces that make up the compound state space.
Definition: StateSpace.h:712
double x
X component of quaternion vector.
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...
A shared pointer wrapper for ompl::control::OpenDEEnvironment.
OpenDEEnvironmentPtr env_
Representation of the OpenDE parameters OMPL needs to plan.