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 }
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 ...
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...
virtual base::State * allocState() const
Allocate a state that can store a point in the described space.
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...
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 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.
A shared pointer wrapper for ompl::control::OpenDEEnvironment.
OpenDEEnvironmentPtr env_
Representation of the OpenDE parameters OMPL needs to plan.