StateSpace.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 #include "ompl/base/StateSpace.h"
36 #include "ompl/util/Exception.h"
37 #include "ompl/tools/config/MagicConstants.h"
38 #include "ompl/base/spaces/RealVectorStateSpace.h"
39 #include <mutex>
40 #include <boost/scoped_ptr.hpp>
41 #include <functional>
42 #include <numeric>
43 #include <limits>
44 #include <queue>
45 #include <cmath>
46 #include <list>
47 #include <set>
48 
50 
52 namespace ompl
53 {
54  namespace base
55  {
56  namespace
57  {
58  struct AllocatedSpaces
59  {
60  AllocatedSpaces() : counter_(0)
61  {
62  }
63  std::list<StateSpace*> list_;
64  std::mutex lock_;
65  unsigned int counter_;
66  };
67 
68  static boost::scoped_ptr<AllocatedSpaces> g_allocatedSpaces;
69  static std::once_flag g_once;
70 
71  void initAllocatedSpaces()
72  {
73  g_allocatedSpaces.reset(new AllocatedSpaces);
74  }
75 
76  AllocatedSpaces& getAllocatedSpaces()
77  {
78  std::call_once(g_once, &initAllocatedSpaces);
79  return *g_allocatedSpaces;
80  }
81  } // namespace
82  }
83 }
85 
87 {
88  AllocatedSpaces &as = getAllocatedSpaces();
89  std::lock_guard<std::mutex> smLock(as.lock_);
90 
91  // autocompute a unique name
92  name_ = "Space" + std::to_string(as.counter_++);
93 
95  longestValidSegmentFraction_ = 0.01; // 1%
97 
99 
100  maxExtent_ = std::numeric_limits<double>::infinity();
101 
102  params_.declareParam<double>("longest_valid_segment_fraction",
103  std::bind(&StateSpace::setLongestValidSegmentFraction, this, std::placeholders::_1),
105 
106  params_.declareParam<unsigned int>("valid_segment_count_factor",
107  std::bind(&StateSpace::setValidSegmentCountFactor, this, std::placeholders::_1),
108  std::bind(&StateSpace::getValidSegmentCountFactor, this));
109  as.list_.push_back(this);
110 }
111 
112 ompl::base::StateSpace::~StateSpace()
113 {
114  AllocatedSpaces &as = getAllocatedSpaces();
115  std::lock_guard<std::mutex> smLock(as.lock_);
116  as.list_.remove(this);
117 }
118 
120 namespace ompl
121 {
122  namespace base
123  {
124  static void computeStateSpaceSignatureHelper(const StateSpace *space, std::vector<int> &signature)
125  {
126  signature.push_back(space->getType());
127  signature.push_back(space->getDimension());
128 
129  if (space->isCompound())
130  {
131  unsigned int c = space->as<CompoundStateSpace>()->getSubspaceCount();
132  for (unsigned int i = 0 ; i < c ; ++i)
133  computeStateSpaceSignatureHelper(space->as<CompoundStateSpace>()->getSubspace(i).get(), signature);
134  }
135  }
136 
137  void computeLocationsHelper(const StateSpace *s,
138  std::map<std::string, StateSpace::SubstateLocation> &substateMap,
139  std::vector<StateSpace::ValueLocation> &locationsArray,
140  std::map<std::string, StateSpace::ValueLocation> &locationsMap, StateSpace::ValueLocation loc)
141  {
142  loc.stateLocation.space = s;
143  substateMap[s->getName()] = loc.stateLocation;
144  State *test = s->allocState();
145  if (s->getValueAddressAtIndex(test, 0) != nullptr)
146  {
147  loc.index = 0;
148  locationsMap[s->getName()] = loc;
149  // if the space is compound, we will find this value again in the first subspace
150  if (!s->isCompound())
151  {
152  if (s->getType() == base::STATE_SPACE_REAL_VECTOR)
153  {
154  const std::string &name = s->as<base::RealVectorStateSpace>()->getDimensionName(0);
155  if (!name.empty())
156  locationsMap[name] = loc;
157  }
158  locationsArray.push_back(loc);
159  while (s->getValueAddressAtIndex(test, ++loc.index) != nullptr)
160  {
161  if (s->getType() == base::STATE_SPACE_REAL_VECTOR)
162  {
163  const std::string &name = s->as<base::RealVectorStateSpace>()->getDimensionName(loc.index);
164  if (!name.empty())
165  locationsMap[name] = loc;
166  }
167  locationsArray.push_back(loc);
168  }
169  }
170  }
171  s->freeState(test);
172 
173  if (s->isCompound())
174  for (unsigned int i = 0 ; i < s->as<base::CompoundStateSpace>()->getSubspaceCount() ; ++i)
175  {
176  loc.stateLocation.chain.push_back(i);
177  computeLocationsHelper(s->as<base::CompoundStateSpace>()->getSubspace(i).get(), substateMap, locationsArray, locationsMap, loc);
178  loc.stateLocation.chain.pop_back();
179  }
180  }
181 
182  void computeLocationsHelper(const StateSpace *s,
183  std::map<std::string, StateSpace::SubstateLocation> &substateMap,
184  std::vector<StateSpace::ValueLocation> &locationsArray,
185  std::map<std::string, StateSpace::ValueLocation> &locationsMap)
186  {
187  substateMap.clear();
188  locationsArray.clear();
189  locationsMap.clear();
190  computeLocationsHelper(s, substateMap, locationsArray, locationsMap, StateSpace::ValueLocation());
191  }
192  }
193 }
195 
196 const std::string& ompl::base::StateSpace::getName() const
197 {
198  return name_;
199 }
200 
201 void ompl::base::StateSpace::setName(const std::string &name)
202 {
203  name_ = name;
204 
205  // we don't want to call this function during the state space construction because calls to virtual functions are made,
206  // so we check if any values were previously inserted as value locations;
207  // if none were, then we either have none (so no need to call this function again)
208  // or setup() was not yet called
209  if (!valueLocationsInOrder_.empty())
210  computeLocationsHelper(this, substateLocationsByName_, valueLocationsInOrder_, valueLocationsByName_);
211 }
212 
214 {
215  computeLocationsHelper(this, substateLocationsByName_, valueLocationsInOrder_, valueLocationsByName_);
216 }
217 
218 void ompl::base::StateSpace::computeSignature(std::vector<int> &signature) const
219 {
220  signature.clear();
221  computeStateSpaceSignatureHelper(this, signature);
222  signature.insert(signature.begin(), signature.size());
223 }
224 
226 {
227  State* copy = allocState();
228  copyState(copy, source);
229  return copy;
230 }
231 
233 {
234 }
235 
237 {
238  maxExtent_ = getMaximumExtent();
239  longestValidSegment_ = maxExtent_ * longestValidSegmentFraction_;
240 
241  if (longestValidSegment_ < std::numeric_limits<double>::epsilon())
242  {
243  std::stringstream error;
244  error << "The longest valid segment for state space " + getName() + " must be positive." << std::endl;
245  error << "Space settings:" << std::endl;
246  printSettings(error);
247  throw Exception(error.str());
248  }
249 
250  computeLocationsHelper(this, substateLocationsByName_, valueLocationsInOrder_, valueLocationsByName_);
251 
252  // make sure we don't overwrite projections that have been configured by the user
253  std::map<std::string, ProjectionEvaluatorPtr> oldProjections = projections_;
254  registerProjections();
255  for (std::map<std::string, ProjectionEvaluatorPtr>::iterator it = oldProjections.begin() ; it != oldProjections.end() ; ++it)
256  if (it->second->userConfigured())
257  {
258  std::map<std::string, ProjectionEvaluatorPtr>::iterator o = projections_.find(it->first);
259  if (o != projections_.end())
260  if (!o->second->userConfigured())
261  projections_[it->first] = it->second;
262  }
263 
264  // remove previously set parameters for projections
265  std::vector<std::string> pnames;
266  params_.getParamNames(pnames);
267  for (std::vector<std::string>::const_iterator it = pnames.begin() ; it != pnames.end() ; ++it)
268  if (it->substr(0, 11) == "projection.")
269  params_.remove(*it);
270 
271  // setup projections and add their parameters
272  for (std::map<std::string, ProjectionEvaluatorPtr>::const_iterator it = projections_.begin() ; it != projections_.end() ; ++it)
273  {
274  it->second->setup();
275  if (it->first == DEFAULT_PROJECTION_NAME)
276  params_.include(it->second->params(), "projection");
277  else
278  params_.include(it->second->params(), "projection." + it->first);
279  }
280 }
281 
282 const std::map<std::string, ompl::base::StateSpace::SubstateLocation>& ompl::base::StateSpace::getSubstateLocationsByName() const
283 {
284  return substateLocationsByName_;
285 }
286 
288 {
289  std::size_t index = 0;
290  while (loc.chain.size() > index)
291  state = state->as<CompoundState>()->components[loc.chain[index++]];
292  return state;
293 }
294 
296 {
297  std::size_t index = 0;
298  while (loc.chain.size() > index)
299  state = state->as<CompoundState>()->components[loc.chain[index++]];
300  return state;
301 }
302 
303 double* ompl::base::StateSpace::getValueAddressAtIndex(State* /*state*/, const unsigned int /*index*/) const
304 {
305  return nullptr;
306 }
307 
308 const double* ompl::base::StateSpace::getValueAddressAtIndex(const State *state, const unsigned int index) const
309 {
310  double *val = getValueAddressAtIndex(const_cast<State*>(state), index); // this const-cast does not hurt, since the state is not modified
311  return val;
312 }
313 
314 const std::vector<ompl::base::StateSpace::ValueLocation>& ompl::base::StateSpace::getValueLocations() const
315 {
316  return valueLocationsInOrder_;
317 }
318 
319 const std::map<std::string, ompl::base::StateSpace::ValueLocation>& ompl::base::StateSpace::getValueLocationsByName() const
320 {
321  return valueLocationsByName_;
322 }
323 
324 void ompl::base::StateSpace::copyToReals(std::vector<double> &reals, const State *source) const
325 {
326  reals.resize(valueLocationsInOrder_.size());
327  for (std::size_t i = 0 ; i < valueLocationsInOrder_.size() ; ++i)
328  reals[i] = *getValueAddressAtLocation(source, valueLocationsInOrder_[i]);
329 }
330 
331 void ompl::base::StateSpace::copyFromReals(State *destination, const std::vector<double> &reals) const
332 {
333  assert(reals.size() == valueLocationsInOrder_.size());
334  for (std::size_t i = 0 ; i < reals.size() ; ++i)
335  *getValueAddressAtLocation(destination, valueLocationsInOrder_[i]) = reals[i];
336 }
337 
339 {
340  std::size_t index = 0;
341  while (loc.stateLocation.chain.size() > index)
342  state = state->as<CompoundState>()->components[loc.stateLocation.chain[index++]];
343  return loc.stateLocation.space->getValueAddressAtIndex(state, loc.index);
344 }
345 
346 const double* ompl::base::StateSpace::getValueAddressAtLocation(const State *state, const ValueLocation &loc) const
347 {
348  std::size_t index = 0;
349  while (loc.stateLocation.chain.size() > index)
350  state = state->as<CompoundState>()->components[loc.stateLocation.chain[index++]];
351  return loc.stateLocation.space->getValueAddressAtIndex(state, loc.index);
352 }
353 
354 double* ompl::base::StateSpace::getValueAddressAtName(State *state, const std::string &name) const
355 {
356  std::map<std::string, ValueLocation>::const_iterator it = valueLocationsByName_.find(name);
357  return (it != valueLocationsByName_.end()) ? getValueAddressAtLocation(state, it->second) : nullptr;
358 }
359 
360 const double* ompl::base::StateSpace::getValueAddressAtName(const State *state, const std::string &name) const
361 {
362  std::map<std::string, ValueLocation>::const_iterator it = valueLocationsByName_.find(name);
363  return (it != valueLocationsByName_.end()) ? getValueAddressAtLocation(state, it->second) : nullptr;
364 }
365 
367 {
368  return 0;
369 }
370 
371 void ompl::base::StateSpace::serialize(void* /*serialization*/, const State* /*state*/) const
372 {
373 }
374 
375 void ompl::base::StateSpace::deserialize(State* /*state*/, const void* /*serialization*/) const
376 {
377 }
378 
379 void ompl::base::StateSpace::printState(const State *state, std::ostream &out) const
380 {
381  out << "State instance [" << state << ']' << std::endl;
382 }
383 
384 void ompl::base::StateSpace::printSettings(std::ostream &out) const
385 {
386  out << "StateSpace '" << getName() << "' instance: " << this << std::endl;
387  printProjections(out);
388 }
389 
390 void ompl::base::StateSpace::printProjections(std::ostream &out) const
391 {
392  if (projections_.empty())
393  out << "No registered projections" << std::endl;
394  else
395  {
396  out << "Registered projections:" << std::endl;
397  for (std::map<std::string, ProjectionEvaluatorPtr>::const_iterator it = projections_.begin() ; it != projections_.end() ; ++it)
398  {
399  out << " - ";
400  if (it->first == DEFAULT_PROJECTION_NAME)
401  out << "<default>";
402  else
403  out << it->first;
404  out << std::endl;
405  it->second->printSettings(out);
406  }
407  }
408 }
409 
411 namespace ompl
412 {
413  namespace base
414  {
415  static bool StateSpaceIncludes(const StateSpace *self, const StateSpace *other)
416  {
417  std::queue<const StateSpace*> q;
418  q.push(self);
419  while (!q.empty())
420  {
421  const StateSpace *m = q.front();
422  q.pop();
423  if (m->getName() == other->getName())
424  return true;
425  if (m->isCompound())
426  {
427  unsigned int c = m->as<CompoundStateSpace>()->getSubspaceCount();
428  for (unsigned int i = 0 ; i < c ; ++i)
429  q.push(m->as<CompoundStateSpace>()->getSubspace(i).get());
430  }
431  }
432  return false;
433  }
434 
435  static bool StateSpaceCovers(const StateSpace *self, const StateSpace *other)
436  {
437  if (StateSpaceIncludes(self, other))
438  return true;
439  else
440  if (other->isCompound())
441  {
442  unsigned int c = other->as<CompoundStateSpace>()->getSubspaceCount();
443  for (unsigned int i = 0 ; i < c ; ++i)
444  if (!StateSpaceCovers(self, other->as<CompoundStateSpace>()->getSubspace(i).get()))
445  return false;
446  return true;
447  }
448  return false;
449  }
450 
451  struct CompareSubstateLocation
452  {
453  bool operator()(const StateSpace::SubstateLocation &a, const StateSpace::SubstateLocation &b) const
454  {
455  if (a.space->getDimension() != b.space->getDimension())
456  return a.space->getDimension() > b.space->getDimension();
457  return a.space->getName() > b.space->getName();
458  }
459  };
460 
461  }
462 }
463 
465 
467 {
468  return StateSpaceCovers(this, other.get());
469 }
470 
472 {
473  return StateSpaceIncludes(this, other.get());
474 }
475 
477 {
478  return StateSpaceCovers(this, other);
479 }
480 
482 {
483  return StateSpaceIncludes(this, other);
484 }
485 
486 void ompl::base::StateSpace::getCommonSubspaces(const StateSpacePtr &other, std::vector<std::string> &subspaces) const
487 {
488  getCommonSubspaces(other.get(), subspaces);
489 }
490 
491 void ompl::base::StateSpace::getCommonSubspaces(const StateSpace *other, std::vector<std::string> &subspaces) const
492 {
493  std::set<StateSpace::SubstateLocation, CompareSubstateLocation> intersection;
494  const std::map<std::string, StateSpace::SubstateLocation> &S = other->getSubstateLocationsByName();
495  for (std::map<std::string, StateSpace::SubstateLocation>::const_iterator it = substateLocationsByName_.begin() ; it != substateLocationsByName_.end() ; ++it)
496  {
497  if (S.find(it->first) != S.end())
498  intersection.insert(it->second);
499  }
500 
501  bool found = true;
502  while (found)
503  {
504  found = false;
505  for (std::set<StateSpace::SubstateLocation, CompareSubstateLocation>::iterator it = intersection.begin() ; it != intersection.end() ; ++it)
506  for (std::set<StateSpace::SubstateLocation, CompareSubstateLocation>::iterator jt = intersection.begin() ; jt != intersection.end() ; ++jt)
507  if (it != jt)
508  if (StateSpaceCovers(it->space, jt->space))
509  {
510  intersection.erase(jt);
511  found = true;
512  break;
513  }
514  }
515  subspaces.clear();
516  for (std::set<StateSpace::SubstateLocation, CompareSubstateLocation>::iterator it = intersection.begin() ; it != intersection.end() ; ++it)
517  subspaces.push_back(it->space->getName());
518 }
519 
520 void ompl::base::StateSpace::List(std::ostream &out)
521 {
522  AllocatedSpaces &as = getAllocatedSpaces();
523  std::lock_guard<std::mutex> smLock(as.lock_);
524  for (std::list<StateSpace*>::iterator it = as.list_.begin() ; it != as.list_.end(); ++it)
525  out << "@ " << *it << ": " << (*it)->getName() << std::endl;
526 }
527 
528 void ompl::base::StateSpace::list(std::ostream &out) const
529 {
530  std::queue<const StateSpace*> q;
531  q.push(this);
532  while (!q.empty())
533  {
534  const StateSpace *m = q.front();
535  q.pop();
536  out << "@ " << m << ": " << m->getName() << std::endl;
537  if (m->isCompound())
538  {
539  unsigned int c = m->as<CompoundStateSpace>()->getSubspaceCount();
540  for (unsigned int i = 0 ; i < c ; ++i)
541  q.push(m->as<CompoundStateSpace>()->getSubspace(i).get());
542  }
543  }
544 }
545 
546 void ompl::base::StateSpace::diagram(std::ostream &out) const
547 {
548  out << "digraph StateSpace {" << std::endl;
549  out << '"' << getName() << '"' << std::endl;
550 
551  std::queue<const StateSpace*> q;
552  q.push(this);
553  while (!q.empty())
554  {
555  const StateSpace *m = q.front();
556  q.pop();
557  if (m->isCompound())
558  {
559  unsigned int c = m->as<CompoundStateSpace>()->getSubspaceCount();
560  for (unsigned int i = 0 ; i < c ; ++i)
561  {
562  const StateSpace *s = m->as<CompoundStateSpace>()->getSubspace(i).get();
563  q.push(s);
564  out << '"' << m->getName() << "\" -> \"" << s->getName() << "\" [label=\"" <<
565  std::to_string(m->as<CompoundStateSpace>()->getSubspaceWeight(i)) << "\"];" << std::endl;
566  }
567  }
568  }
569 
570  out << '}' << std::endl;
571 }
572 
573 void ompl::base::StateSpace::Diagram(std::ostream &out)
574 {
575  AllocatedSpaces &as = getAllocatedSpaces();
576  std::lock_guard<std::mutex> smLock(as.lock_);
577  out << "digraph StateSpaces {" << std::endl;
578  for (std::list<StateSpace*>::iterator it = as.list_.begin() ; it != as.list_.end(); ++it)
579  {
580  out << '"' << (*it)->getName() << '"' << std::endl;
581  for (std::list<StateSpace*>::iterator jt = as.list_.begin() ; jt != as.list_.end(); ++jt)
582  if (it != jt)
583  {
584  if ((*it)->isCompound() && (*it)->as<CompoundStateSpace>()->hasSubspace((*jt)->getName()))
585  out << '"' << (*it)->getName() << "\" -> \"" << (*jt)->getName() << "\" [label=\"" <<
586  std::to_string((*it)->as<CompoundStateSpace>()->getSubspaceWeight((*jt)->getName())) <<
587  "\"];" << std::endl;
588  else
589  if (!StateSpaceIncludes(*it, *jt) && StateSpaceCovers(*it, *jt))
590  out << '"' << (*it)->getName() << "\" -> \"" << (*jt)->getName() << "\" [style=dashed];" << std::endl;
591  }
592  }
593  out << '}' << std::endl;
594 }
595 
597 {
598  unsigned int flags = isMetricSpace() ? ~0 : ~(STATESPACE_DISTANCE_SYMMETRIC | STATESPACE_TRIANGLE_INEQUALITY);
599  sanityChecks(std::numeric_limits<double>::epsilon(), std::numeric_limits<float>::epsilon(), flags);
600 }
601 
602 void ompl::base::StateSpace::sanityChecks(double zero, double eps, unsigned int flags) const
603 {
604  {
605  double maxExt = getMaximumExtent();
606 
607  State *s1 = allocState();
608  State *s2 = allocState();
609  StateSamplerPtr ss = allocStateSampler();
610  char *serialization = nullptr;
611  if ((flags & STATESPACE_SERIALIZATION) && getSerializationLength() > 0)
612  serialization = new char[getSerializationLength()];
613  for (unsigned int i = 0 ; i < magic::TEST_STATE_COUNT ; ++i)
614  {
615  ss->sampleUniform(s1);
616  if (distance(s1, s1) > eps)
617  throw Exception("Distance from a state to itself should be 0");
618  if (!equalStates(s1, s1))
619  throw Exception("A state should be equal to itself");
620  if ((flags & STATESPACE_RESPECT_BOUNDS) && !satisfiesBounds(s1))
621  throw Exception("Sampled states should be within bounds");
622  copyState(s2, s1);
623  if (!equalStates(s1, s2))
624  throw Exception("Copy of a state is not the same as the original state. copyState() may not work correctly.");
625  if (flags & STATESPACE_ENFORCE_BOUNDS_NO_OP)
626  {
627  enforceBounds(s1);
628  if (!equalStates(s1, s2))
629  throw Exception("enforceBounds() seems to modify states that are in fact within bounds.");
630  }
631  if (flags & STATESPACE_SERIALIZATION)
632  {
633  ss->sampleUniform(s2);
634  serialize(serialization, s1);
635  deserialize(s2, serialization);
636  if (!equalStates(s1, s2))
637  throw Exception("Serialization/deserialization operations do not seem to work as expected.");
638  }
639  ss->sampleUniform(s2);
640  if (!equalStates(s1, s2))
641  {
642  double d12 = distance(s1, s2);
643  if ((flags & STATESPACE_DISTANCE_DIFFERENT_STATES) && d12 < zero)
644  throw Exception("Distance between different states should be above 0");
645  double d21 = distance(s2, s1);
646  if ((flags & STATESPACE_DISTANCE_SYMMETRIC) && fabs(d12 - d21) > eps)
647  throw Exception("The distance function should be symmetric (A->B=" +
648  std::to_string(d12) + ", B->A=" +
649  std::to_string(d21) + ", difference is " +
650  std::to_string(fabs(d12 - d21)) + ")");
651  if (flags & STATESPACE_DISTANCE_BOUND)
652  if (d12 > maxExt + zero)
653  throw Exception("The distance function should not report values larger than the maximum extent ("+
654  std::to_string(d12) + " > " + std::to_string(maxExt) + ")");
655  }
656  }
657  if (serialization)
658  delete[] serialization;
659  freeState(s1);
660  freeState(s2);
661  }
662 
663 
664  // Test that interpolation works as expected and also test triangle inequality
665  if (!isDiscrete() && !isHybrid())
666  {
667  State *s1 = allocState();
668  State *s2 = allocState();
669  State *s3 = allocState();
670  StateSamplerPtr ss = allocStateSampler();
671 
672  for (unsigned int i = 0 ; i < magic::TEST_STATE_COUNT ; ++i)
673  {
674  ss->sampleUniform(s1);
675  ss->sampleUniform(s2);
676  ss->sampleUniform(s3);
677 
678  interpolate(s1, s2, 0.0, s3);
679  if ((flags & STATESPACE_INTERPOLATION) && distance(s1, s3) > eps)
680  throw Exception("Interpolation from a state at time 0 should be not change the original state");
681 
682  interpolate(s1, s2, 1.0, s3);
683  if ((flags & STATESPACE_INTERPOLATION) && distance(s2, s3) > eps)
684  throw Exception("Interpolation to a state at time 1 should be the same as the final state");
685 
686  interpolate(s1, s2, 0.5, s3);
687  double diff = distance(s1, s3) + distance(s3, s2) - distance(s1, s2);
688  if ((flags & STATESPACE_TRIANGLE_INEQUALITY) && fabs(diff) > eps)
689  throw Exception("Interpolation to midpoint state does not lead to distances that satisfy the triangle inequality (" +
690  std::to_string(diff) + " difference)");
691 
692  interpolate(s3, s2, 0.5, s3);
693  interpolate(s1, s2, 0.75, s2);
694 
695  if ((flags & STATESPACE_INTERPOLATION) && distance(s2, s3) > eps)
696  throw Exception("Continued interpolation does not work as expected. Please also check that interpolate() works with overlapping memory for its state arguments");
697  }
698  freeState(s1);
699  freeState(s2);
700  freeState(s3);
701  }
702 }
703 
705 {
706  return hasProjection(DEFAULT_PROJECTION_NAME);
707 }
708 
709 bool ompl::base::StateSpace::hasProjection(const std::string &name) const
710 {
711  return projections_.find(name) != projections_.end();
712 }
713 
715 {
716  if (hasDefaultProjection())
717  return getProjection(DEFAULT_PROJECTION_NAME);
718  else
719  {
720  OMPL_ERROR("No default projection is set. Perhaps setup() needs to be called");
721  return ProjectionEvaluatorPtr();
722  }
723 }
724 
726 {
727  std::map<std::string, ProjectionEvaluatorPtr>::const_iterator it = projections_.find(name);
728  if (it != projections_.end())
729  return it->second;
730  else
731  {
732  OMPL_ERROR("Projection '%s' is not defined", name.c_str());
733  return ProjectionEvaluatorPtr();
734  }
735 }
736 
737 const std::map<std::string, ompl::base::ProjectionEvaluatorPtr>& ompl::base::StateSpace::getRegisteredProjections() const
738 {
739  return projections_;
740 }
741 
743 {
744  registerProjection(DEFAULT_PROJECTION_NAME, projection);
745 }
746 
747 void ompl::base::StateSpace::registerProjection(const std::string &name, const ProjectionEvaluatorPtr &projection)
748 {
749  if (projection)
750  projections_[name] = projection;
751  else
752  OMPL_ERROR("Attempting to register invalid projection under name '%s'. Ignoring.", name.c_str());
753 }
754 
756 {
757  return false;
758 }
759 
761 {
762  return false;
763 }
764 
766 {
767  return false;
768 }
769 
771 {
772  return true;
773 }
774 
776 {
777  return true;
778 }
779 
781 {
782  ssa_ = ssa;
783 }
784 
786 {
787  ssa_ = StateSamplerAllocator();
788 }
789 
791 {
792  if (ssa_)
793  return ssa_(this);
794  else
795  return allocDefaultStateSampler();
796 }
797 
799 {
800  return allocSubspaceStateSampler(subspace.get());
801 }
802 
804 {
805  if (subspace->getName() == getName())
806  return allocStateSampler();
807  return StateSamplerPtr(new SubspaceStateSampler(this, subspace, 1.0));
808 }
809 
811 {
812  if (factor < 1)
813  throw Exception("The multiplicative factor for the valid segment count between two states must be strictly positive");
814  longestValidSegmentCountFactor_ = factor;
815 }
816 
818 {
819  if (segmentFraction < std::numeric_limits<double>::epsilon() || segmentFraction > 1.0 - std::numeric_limits<double>::epsilon())
820  throw Exception("The fraction of the extent must be larger than 0 and less than 1");
821  longestValidSegmentFraction_ = segmentFraction;
822 }
823 
825 {
826  return longestValidSegmentCountFactor_;
827 }
828 
830 {
831  return longestValidSegmentFraction_;
832 }
833 
835 {
836  return longestValidSegment_;
837 }
838 
839 unsigned int ompl::base::StateSpace::validSegmentCount(const State *state1, const State *state2) const
840 {
841  return longestValidSegmentCountFactor_ * (unsigned int)ceil(distance(state1, state2) / longestValidSegment_);
842 }
843 
844 ompl::base::CompoundStateSpace::CompoundStateSpace() : StateSpace(), componentCount_(0), weightSum_(0.0), locked_(false)
845 {
846  setName("Compound" + getName());
847 }
848 
849 ompl::base::CompoundStateSpace::CompoundStateSpace(const std::vector<StateSpacePtr> &components,
850  const std::vector<double> &weights) :
851  StateSpace(), componentCount_(0), weightSum_(0.0), locked_(false)
852 {
853  if (components.size() != weights.size())
854  throw Exception("Number of component spaces and weights are not the same");
855  setName("Compound" + getName());
856  for (unsigned int i = 0 ; i < components.size() ; ++i)
857  addSubspace(components[i], weights[i]);
858 }
859 
860 void ompl::base::CompoundStateSpace::addSubspace(const StateSpacePtr &component, double weight)
861 {
862  if (locked_)
863  throw Exception("This state space is locked. No further components can be added");
864  if (weight < 0.0)
865  throw Exception("Subspace weight cannot be negative");
866  components_.push_back(component);
867  weights_.push_back(weight);
868  weightSum_ += weight;
869  componentCount_ = components_.size();
870 }
871 
873 {
874  return true;
875 }
876 
878 {
879  bool c = false;
880  bool d = false;
881  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
882  {
883  if (components_[i]->isHybrid())
884  return true;
885  if (components_[i]->isDiscrete())
886  d = true;
887  else
888  c = true;
889  }
890  return c && d;
891 }
892 
894 {
895  return componentCount_;
896 }
897 
899 {
900  if (componentCount_ > index)
901  return components_[index];
902  else
903  throw Exception("Subspace index does not exist");
904 }
905 
906 bool ompl::base::CompoundStateSpace::hasSubspace(const std::string &name) const
907 {
908  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
909  if (components_[i]->getName() == name)
910  return true;
911  return false;
912 }
913 
914 unsigned int ompl::base::CompoundStateSpace::getSubspaceIndex(const std::string& name) const
915 {
916  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
917  if (components_[i]->getName() == name)
918  return i;
919  throw Exception("Subspace " + name + " does not exist");
920 }
921 
923 {
924  return components_[getSubspaceIndex(name)];
925 }
926 
927 double ompl::base::CompoundStateSpace::getSubspaceWeight(const unsigned int index) const
928 {
929  if (componentCount_ > index)
930  return weights_[index];
931  else
932  throw Exception("Subspace index does not exist");
933 }
934 
935 double ompl::base::CompoundStateSpace::getSubspaceWeight(const std::string &name) const
936 {
937  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
938  if (components_[i]->getName() == name)
939  return weights_[i];
940  throw Exception("Subspace " + name + " does not exist");
941 }
942 
943 void ompl::base::CompoundStateSpace::setSubspaceWeight(const unsigned int index, double weight)
944 {
945  if (weight < 0.0)
946  throw Exception("Subspace weight cannot be negative");
947  if (componentCount_ > index)
948  {
949  weightSum_ += weight - weights_[index];
950  weights_[index] = weight;
951  }
952  else
953  throw Exception("Subspace index does not exist");
954 }
955 
956 void ompl::base::CompoundStateSpace::setSubspaceWeight(const std::string &name, double weight)
957 {
958  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
959  if (components_[i]->getName() == name)
960  {
961  setSubspaceWeight(i, weight);
962  return;
963  }
964  throw Exception("Subspace " + name + " does not exist");
965 }
966 
967 const std::vector<ompl::base::StateSpacePtr>& ompl::base::CompoundStateSpace::getSubspaces() const
968 {
969  return components_;
970 }
971 
972 const std::vector<double>& ompl::base::CompoundStateSpace::getSubspaceWeights() const
973 {
974  return weights_;
975 }
976 
978 {
979  unsigned int dim = 0;
980  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
981  dim += components_[i]->getDimension();
982  return dim;
983 }
984 
986 {
987  double e = 0.0;
988  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
989  if (weights_[i] >= std::numeric_limits<double>::epsilon()) // avoid possible multiplication of 0 times infinity
990  e += weights_[i] * components_[i]->getMaximumExtent();
991  return e;
992 }
993 
995 {
996  double m = 1.0;
997  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
998  if (weights_[i] >= std::numeric_limits<double>::epsilon()) // avoid possible multiplication of 0 times infinity
999  m *= weights_[i] * components_[i]->getMeasure();
1000  return m;
1001 }
1002 
1004 {
1005  CompoundState *cstate = static_cast<CompoundState*>(state);
1006  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1007  components_[i]->enforceBounds(cstate->components[i]);
1008 }
1009 
1011 {
1012  const CompoundState *cstate = static_cast<const CompoundState*>(state);
1013  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1014  if (!components_[i]->satisfiesBounds(cstate->components[i]))
1015  return false;
1016  return true;
1017 }
1018 
1019 void ompl::base::CompoundStateSpace::copyState(State *destination, const State *source) const
1020 {
1021  CompoundState *cdest = static_cast<CompoundState*>(destination);
1022  const CompoundState *csrc = static_cast<const CompoundState*>(source);
1023  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1024  components_[i]->copyState(cdest->components[i], csrc->components[i]);
1025 }
1026 
1028 {
1029  unsigned int l = 0;
1030  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1031  l += components_[i]->getSerializationLength();
1032  return l;
1033 }
1034 
1035 void ompl::base::CompoundStateSpace::serialize(void *serialization, const State *state) const
1036 {
1037  const CompoundState *cstate = static_cast<const CompoundState*>(state);
1038  unsigned int l = 0;
1039  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1040  {
1041  components_[i]->serialize(reinterpret_cast<char*>(serialization) + l, cstate->components[i]);
1042  l += components_[i]->getSerializationLength();
1043  }
1044 }
1045 
1046 void ompl::base::CompoundStateSpace::deserialize(State *state, const void *serialization) const
1047 {
1048  CompoundState *cstate = static_cast<CompoundState*>(state);
1049  unsigned int l = 0;
1050  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1051  {
1052  components_[i]->deserialize(cstate->components[i], reinterpret_cast<const char*>(serialization) + l);
1053  l += components_[i]->getSerializationLength();
1054  }
1055 }
1056 
1057 double ompl::base::CompoundStateSpace::distance(const State *state1, const State *state2) const
1058 {
1059  const CompoundState *cstate1 = static_cast<const CompoundState*>(state1);
1060  const CompoundState *cstate2 = static_cast<const CompoundState*>(state2);
1061  double dist = 0.0;
1062  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1063  dist += weights_[i] * components_[i]->distance(cstate1->components[i], cstate2->components[i]);
1064  return dist;
1065 }
1066 
1068 {
1070  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1071  components_[i]->setLongestValidSegmentFraction(segmentFraction);
1072 }
1073 
1074 unsigned int ompl::base::CompoundStateSpace::validSegmentCount(const State *state1, const State *state2) const
1075 {
1076  const CompoundState *cstate1 = static_cast<const CompoundState*>(state1);
1077  const CompoundState *cstate2 = static_cast<const CompoundState*>(state2);
1078  unsigned int sc = 0;
1079  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1080  {
1081  unsigned int sci = components_[i]->validSegmentCount(cstate1->components[i], cstate2->components[i]);
1082  if (sci > sc)
1083  sc = sci;
1084  }
1085  return sc;
1086 }
1087 
1088 bool ompl::base::CompoundStateSpace::equalStates(const State *state1, const State *state2) const
1089 {
1090  const CompoundState *cstate1 = static_cast<const CompoundState*>(state1);
1091  const CompoundState *cstate2 = static_cast<const CompoundState*>(state2);
1092  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1093  if (!components_[i]->equalStates(cstate1->components[i], cstate2->components[i]))
1094  return false;
1095  return true;
1096 }
1097 
1098 void ompl::base::CompoundStateSpace::interpolate(const State *from, const State *to, const double t, State *state) const
1099 {
1100  const CompoundState *cfrom = static_cast<const CompoundState*>(from);
1101  const CompoundState *cto = static_cast<const CompoundState*>(to);
1102  CompoundState *cstate = static_cast<CompoundState*>(state);
1103  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1104  components_[i]->interpolate(cfrom->components[i], cto->components[i], t, cstate->components[i]);
1105 }
1106 
1108 {
1110  if (weightSum_ < std::numeric_limits<double>::epsilon())
1111  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1112  ss->addSampler(components_[i]->allocStateSampler(), 1.0);
1113  else
1114  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1115  ss->addSampler(components_[i]->allocStateSampler(), weights_[i] / weightSum_);
1116  return StateSamplerPtr(ss);
1117 }
1118 
1120 {
1121  if (subspace->getName() == getName())
1122  return allocStateSampler();
1123  if (hasSubspace(subspace->getName()))
1124  return StateSamplerPtr(new SubspaceStateSampler(this, subspace, getSubspaceWeight(subspace->getName()) / weightSum_));
1125  return StateSpace::allocSubspaceStateSampler(subspace);
1126 }
1127 
1129 {
1130  CompoundState *state = new CompoundState();
1131  allocStateComponents(state);
1132  return static_cast<State*>(state);
1133 }
1134 
1136 {
1137  state->components = new State*[componentCount_];
1138  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1139  state->components[i] = components_[i]->allocState();
1140 }
1141 
1143 {
1144  CompoundState *cstate = static_cast<CompoundState*>(state);
1145  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1146  components_[i]->freeState(cstate->components[i]);
1147  delete[] cstate->components;
1148  delete cstate;
1149 }
1150 
1152 {
1153  locked_ = true;
1154 }
1155 
1157 {
1158  return locked_;
1159 }
1160 
1161 double* ompl::base::CompoundStateSpace::getValueAddressAtIndex(State *state, const unsigned int index) const
1162 {
1163  CompoundState *cstate = static_cast<CompoundState*>(state);
1164  unsigned int idx = 0;
1165 
1166  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1167  for (unsigned int j = 0 ; j <= index ; ++j)
1168  {
1169  double *va = components_[i]->getValueAddressAtIndex(cstate->components[i], j);
1170  if (va)
1171  {
1172  if (idx == index)
1173  return va;
1174  else
1175  idx++;
1176  }
1177  else
1178  break;
1179  }
1180  return nullptr;
1181 }
1182 
1183 void ompl::base::CompoundStateSpace::printState(const State *state, std::ostream &out) const
1184 {
1185  out << "Compound state [" << std::endl;
1186  const CompoundState *cstate = static_cast<const CompoundState*>(state);
1187  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1188  components_[i]->printState(cstate->components[i], out);
1189  out << "]" << std::endl;
1190 }
1191 
1193 {
1194  out << "Compound state space '" << getName() << "' of dimension " << getDimension() << (isLocked() ? " (locked)" : "") << " [" << std::endl;
1195  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1196  {
1197  components_[i]->printSettings(out);
1198  out << " of weight " << weights_[i] << std::endl;
1199  }
1200  out << "]" << std::endl;
1201  printProjections(out);
1202 }
1203 
1205 {
1206  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1207  components_[i]->setup();
1208 
1210 }
1211 
1213 {
1215  for (unsigned int i = 0 ; i < componentCount_ ; ++i)
1216  components_[i]->computeLocations();
1217 }
1218 
1219 namespace ompl
1220 {
1221  namespace base
1222  {
1223 
1224  AdvancedStateCopyOperation copyStateData(const StateSpacePtr &destS, State *dest, const StateSpacePtr &sourceS, const State *source)
1225  {
1226  return copyStateData(destS.get(), dest, sourceS.get(), source);
1227  }
1228 
1229  AdvancedStateCopyOperation copyStateData(const StateSpace *destS, State *dest, const StateSpace *sourceS, const State *source)
1230  {
1231  // if states correspond to the same space, simply do copy
1232  if (destS->getName() == sourceS->getName())
1233  {
1234  if (dest != source)
1235  destS->copyState(dest, source);
1236  return ALL_DATA_COPIED;
1237  }
1238 
1240 
1241  // if "to" state is compound
1242  if (destS->isCompound())
1243  {
1244  const CompoundStateSpace *compoundDestS = destS->as<CompoundStateSpace>();
1245  CompoundState *compoundDest = dest->as<CompoundState>();
1246 
1247  // if there is a subspace in "to" that corresponds to "from", set the data and return
1248  for (unsigned int i = 0 ; i < compoundDestS->getSubspaceCount() ; ++i)
1249  if (compoundDestS->getSubspace(i)->getName() == sourceS->getName())
1250  {
1251  if (compoundDest->components[i] != source)
1252  compoundDestS->getSubspace(i)->copyState(compoundDest->components[i], source);
1253  return ALL_DATA_COPIED;
1254  }
1255 
1256  // it could be there are further levels of compound spaces where the data can be set
1257  // so we call this function recursively
1258  for (unsigned int i = 0 ; i < compoundDestS->getSubspaceCount() ; ++i)
1259  {
1260  AdvancedStateCopyOperation res = copyStateData(compoundDestS->getSubspace(i).get(), compoundDest->components[i], sourceS, source);
1261 
1262  if (res != NO_DATA_COPIED)
1263  result = SOME_DATA_COPIED;
1264 
1265  // if all data was copied, we stop
1266  if (res == ALL_DATA_COPIED)
1267  return ALL_DATA_COPIED;
1268  }
1269  }
1270 
1271  // if we got to this point, it means that the data in "from" could not be copied as a chunk to "to"
1272  // it could be the case "from" is from a compound space as well, so we can copy parts of "from", as needed
1273  if (sourceS->isCompound())
1274  {
1275  const CompoundStateSpace *compoundSourceS = sourceS->as<CompoundStateSpace>();
1276  const CompoundState *compoundSource = source->as<CompoundState>();
1277 
1278  unsigned int copiedComponents = 0;
1279 
1280  // if there is a subspace in "to" that corresponds to "from", set the data and return
1281  for (unsigned int i = 0 ; i < compoundSourceS->getSubspaceCount() ; ++i)
1282  {
1283  AdvancedStateCopyOperation res = copyStateData(destS, dest, compoundSourceS->getSubspace(i).get(), compoundSource->components[i]);
1284  if (res == ALL_DATA_COPIED)
1285  copiedComponents++;
1286  if (res != NO_DATA_COPIED)
1287  result = SOME_DATA_COPIED;
1288  }
1289 
1290  // if each individual component got copied, then the entire data in "from" got copied
1291  if (copiedComponents == compoundSourceS->getSubspaceCount())
1292  result = ALL_DATA_COPIED;
1293  }
1294 
1295  return result;
1296  }
1297 
1299  const StateSpacePtr &sourceS, const State *source,
1300  const std::vector<std::string> &subspaces)
1301  {
1302  return copyStateData(destS.get(), dest, sourceS.get(), source, subspaces);
1303  }
1304 
1306  const StateSpace *sourceS, const State *source,
1307  const std::vector<std::string> &subspaces)
1308  {
1309  std::size_t copyCount = 0;
1310  const std::map<std::string, StateSpace::SubstateLocation> &destLoc = destS->getSubstateLocationsByName();
1311  const std::map<std::string, StateSpace::SubstateLocation> &sourceLoc = sourceS->getSubstateLocationsByName();
1312  for (std::size_t i = 0 ; i < subspaces.size() ; ++i)
1313  {
1314  std::map<std::string, StateSpace::SubstateLocation>::const_iterator dt = destLoc.find(subspaces[i]);
1315  if (dt != destLoc.end())
1316  {
1317  std::map<std::string, StateSpace::SubstateLocation>::const_iterator st = sourceLoc.find(subspaces[i]);
1318  if (st != sourceLoc.end())
1319  {
1320  dt->second.space->copyState(destS->getSubstateAtLocation(dest, dt->second), sourceS->getSubstateAtLocation(source, st->second));
1321  ++copyCount;
1322  }
1323  }
1324  }
1325  if (copyCount == subspaces.size())
1326  return ALL_DATA_COPIED;
1327  if (copyCount > 0)
1328  return SOME_DATA_COPIED;
1329  return NO_DATA_COPIED;
1330  }
1331 
1333  inline bool StateSpaceHasContent(const StateSpacePtr &m)
1334  {
1335  if (!m)
1336  return false;
1337  if (m->getDimension() == 0 && m->getType() == STATE_SPACE_UNKNOWN && m->isCompound())
1338  {
1339  const unsigned int nc = m->as<CompoundStateSpace>()->getSubspaceCount();
1340  for (unsigned int i = 0 ; i < nc ; ++i)
1341  if (StateSpaceHasContent(m->as<CompoundStateSpace>()->getSubspace(i)))
1342  return true;
1343  return false;
1344  }
1345  return true;
1346  }
1348 
1350  {
1351  if (!StateSpaceHasContent(a) && StateSpaceHasContent(b))
1352  return b;
1353 
1354  if (!StateSpaceHasContent(b) && StateSpaceHasContent(a))
1355  return a;
1356 
1357  std::vector<StateSpacePtr> components;
1358  std::vector<double> weights;
1359 
1360  bool change = false;
1361  if (a)
1362  {
1363  bool used = false;
1364  if (CompoundStateSpace *csm_a = dynamic_cast<CompoundStateSpace*>(a.get()))
1365  if (!csm_a->isLocked())
1366  {
1367  used = true;
1368  for (unsigned int i = 0 ; i < csm_a->getSubspaceCount() ; ++i)
1369  {
1370  components.push_back(csm_a->getSubspace(i));
1371  weights.push_back(csm_a->getSubspaceWeight(i));
1372  }
1373  }
1374 
1375  if (!used)
1376  {
1377  components.push_back(a);
1378  weights.push_back(1.0);
1379  }
1380  }
1381  if (b)
1382  {
1383  bool used = false;
1384  unsigned int size = components.size();
1385 
1386  if (CompoundStateSpace *csm_b = dynamic_cast<CompoundStateSpace*>(b.get()))
1387  if (!csm_b->isLocked())
1388  {
1389  used = true;
1390  for (unsigned int i = 0 ; i < csm_b->getSubspaceCount() ; ++i)
1391  {
1392  bool ok = true;
1393  for (unsigned int j = 0 ; j < size ; ++j)
1394  if (components[j]->getName() == csm_b->getSubspace(i)->getName())
1395  {
1396  ok = false;
1397  break;
1398  }
1399  if (ok)
1400  {
1401  components.push_back(csm_b->getSubspace(i));
1402  weights.push_back(csm_b->getSubspaceWeight(i));
1403  change = true;
1404  }
1405  }
1406  if (components.size() == csm_b->getSubspaceCount())
1407  return b;
1408  }
1409 
1410  if (!used)
1411  {
1412  bool ok = true;
1413  for (unsigned int j = 0 ; j < size ; ++j)
1414  if (components[j]->getName() == b->getName())
1415  {
1416  ok = false;
1417  break;
1418  }
1419  if (ok)
1420  {
1421  components.push_back(b);
1422  weights.push_back(1.0);
1423  change = true;
1424  }
1425  }
1426  }
1427 
1428  if (!change && a)
1429  return a;
1430 
1431  if (components.size() == 1)
1432  return components[0];
1433 
1434  return StateSpacePtr(new CompoundStateSpace(components, weights));
1435  }
1436 
1438  {
1439  std::vector<StateSpacePtr> components_a;
1440  std::vector<double> weights_a;
1441  std::vector<StateSpacePtr> components_b;
1442 
1443  if (a)
1444  {
1445  bool used = false;
1446  if (CompoundStateSpace *csm_a = dynamic_cast<CompoundStateSpace*>(a.get()))
1447  if (!csm_a->isLocked())
1448  {
1449  used = true;
1450  for (unsigned int i = 0 ; i < csm_a->getSubspaceCount() ; ++i)
1451  {
1452  components_a.push_back(csm_a->getSubspace(i));
1453  weights_a.push_back(csm_a->getSubspaceWeight(i));
1454  }
1455  }
1456 
1457  if (!used)
1458  {
1459  components_a.push_back(a);
1460  weights_a.push_back(1.0);
1461  }
1462  }
1463 
1464  if (b)
1465  {
1466  bool used = false;
1467  if (CompoundStateSpace *csm_b = dynamic_cast<CompoundStateSpace*>(b.get()))
1468  if (!csm_b->isLocked())
1469  {
1470  used = true;
1471  for (unsigned int i = 0 ; i < csm_b->getSubspaceCount() ; ++i)
1472  components_b.push_back(csm_b->getSubspace(i));
1473  }
1474  if (!used)
1475  components_b.push_back(b);
1476  }
1477 
1478  bool change = false;
1479  for (unsigned int i = 0 ; i < components_b.size() ; ++i)
1480  for (unsigned int j = 0 ; j < components_a.size() ; ++j)
1481  if (components_a[j]->getName() == components_b[i]->getName())
1482  {
1483  components_a.erase(components_a.begin() + j);
1484  weights_a.erase(weights_a.begin() + j);
1485  change = true;
1486  break;
1487  }
1488 
1489  if (!change && a)
1490  return a;
1491 
1492  if (components_a.size() == 1)
1493  return components_a[0];
1494 
1495  return StateSpacePtr(new CompoundStateSpace(components_a, weights_a));
1496  }
1497 
1498  StateSpacePtr operator-(const StateSpacePtr &a, const std::string &name)
1499  {
1500  std::vector<StateSpacePtr> components;
1501  std::vector<double> weights;
1502 
1503  bool change = false;
1504  if (a)
1505  {
1506  bool used = false;
1507  if (CompoundStateSpace *csm_a = dynamic_cast<CompoundStateSpace*>(a.get()))
1508  if (!csm_a->isLocked())
1509  {
1510  used = true;
1511  for (unsigned int i = 0 ; i < csm_a->getSubspaceCount() ; ++i)
1512  {
1513  if (csm_a->getSubspace(i)->getName() == name)
1514  {
1515  change = true;
1516  continue;
1517  }
1518  components.push_back(csm_a->getSubspace(i));
1519  weights.push_back(csm_a->getSubspaceWeight(i));
1520  }
1521  }
1522 
1523  if (!used)
1524  {
1525  if (a->getName() != name)
1526  {
1527  components.push_back(a);
1528  weights.push_back(1.0);
1529  }
1530  else
1531  change = true;
1532  }
1533  }
1534 
1535  if (!change && a)
1536  return a;
1537 
1538  if (components.size() == 1)
1539  return components[0];
1540 
1541  return StateSpacePtr(new CompoundStateSpace(components, weights));
1542  }
1543 
1545  {
1546  std::vector<StateSpacePtr> components_a;
1547  std::vector<double> weights_a;
1548  std::vector<StateSpacePtr> components_b;
1549  std::vector<double> weights_b;
1550 
1551  if (a)
1552  {
1553  bool used = false;
1554  if (CompoundStateSpace *csm_a = dynamic_cast<CompoundStateSpace*>(a.get()))
1555  if (!csm_a->isLocked())
1556  {
1557  used = true;
1558  for (unsigned int i = 0 ; i < csm_a->getSubspaceCount() ; ++i)
1559  {
1560  components_a.push_back(csm_a->getSubspace(i));
1561  weights_a.push_back(csm_a->getSubspaceWeight(i));
1562  }
1563  }
1564 
1565  if (!used)
1566  {
1567  components_a.push_back(a);
1568  weights_a.push_back(1.0);
1569  }
1570  }
1571 
1572  if (b)
1573  {
1574  bool used = false;
1575  if (CompoundStateSpace *csm_b = dynamic_cast<CompoundStateSpace*>(b.get()))
1576  if (!csm_b->isLocked())
1577  {
1578  used = true;
1579  for (unsigned int i = 0 ; i < csm_b->getSubspaceCount() ; ++i)
1580  {
1581  components_b.push_back(csm_b->getSubspace(i));
1582  weights_b.push_back(csm_b->getSubspaceWeight(i));
1583  }
1584  }
1585 
1586  if (!used)
1587  {
1588  components_b.push_back(b);
1589  weights_b.push_back(1.0);
1590  }
1591  }
1592 
1593  std::vector<StateSpacePtr> components;
1594  std::vector<double> weights;
1595 
1596  for (unsigned int i = 0 ; i < components_b.size() ; ++i)
1597  {
1598  for (unsigned int j = 0 ; j < components_a.size() ; ++j)
1599  if (components_a[j]->getName() == components_b[i]->getName())
1600  {
1601  components.push_back(components_b[i]);
1602  weights.push_back(std::max(weights_a[j], weights_b[i]));
1603  break;
1604  }
1605  }
1606 
1607  if (a && components.size() == components_a.size())
1608  return a;
1609 
1610  if (b && components.size() == components_b.size())
1611  return b;
1612 
1613  if (components.size() == 1)
1614  return components[0];
1615 
1616  return StateSpacePtr(new CompoundStateSpace(components, weights));
1617  }
1618  }
1619 }
State * getSubstateAtLocation(State *state, const SubstateLocation &loc) const
Get the substate of state that is pointed to by loc.
Definition: StateSpace.cpp:287
void setName(const std::string &name)
Set the name of the state space.
Definition: StateSpace.cpp:201
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.
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
virtual void deserialize(State *state, const void *serialization) const
Read the binary representation of a state from serialization and write it to state.
int type_
A type assigned for this state space.
Definition: StateSpace.h:508
ParamSet params_
The set of parameters for this space.
Definition: StateSpace.h:529
bool hasDefaultProjection() const
Check if a default projection is available.
Definition: StateSpace.cpp:704
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:839
virtual bool hasSymmetricInterpolate() const
Check if the interpolation function on this state space is symmetric, i.e. interpolate(from, to, t, state) = interpolate(to, from, 1-t, state). Default implementation returns true.
Definition: StateSpace.cpp:775
Definition of a compound state.
Definition: State.h:95
virtual void copyState(State *destination, const State *source) const
Copy a state to another. The memory of source and destination should NOT overlap. ...
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: StateSpace.cpp:303
virtual bool isHybrid() const
Check if this is a hybrid state space (i.e., both discrete and continuous components exist) ...
Definition: StateSpace.cpp:765
static const std::string DEFAULT_PROJECTION_NAME
The name used for the default projection.
Definition: StateSpace.h:505
std::size_t index
The index of the value to be accessed, within the substate location above.
Definition: StateSpace.h:128
virtual double getLongestValidSegmentFraction() const
When performing discrete validation of motions, the length of the longest segment that does not requi...
Definition: StateSpace.cpp:829
unsigned int getSubspaceIndex(const std::string &name) const
Get the index of a specific subspace from the compound state space.
Definition: StateSpace.cpp:914
virtual bool isCompound() const
Check if the state space is compound.
Definition: StateSpace.cpp:872
virtual unsigned int getSerializationLength() const
Get the number of chars in the serialization of a state in this space.
virtual StateSamplerPtr allocDefaultStateSampler() const
Allocate an instance of the default uniform state sampler for this space.
State * cloneState(const State *source) const
Clone a state.
Definition: StateSpace.cpp:225
bool includes(const StateSpacePtr &other) const
Return true if other is a space included (perhaps equal, perhaps a subspace) in this one...
Definition: StateSpace.cpp:471
static void Diagram(std::ostream &out)
Print a Graphviz digraph that represents the containment diagram for all the instantiated state space...
Definition: StateSpace.cpp:573
virtual void printProjections(std::ostream &out) const
Print the list of registered projections. This function is also called by printSettings() ...
Definition: StateSpace.cpp:390
A shared pointer wrapper for ompl::base::StateSpace.
const std::vector< ValueLocation > & getValueLocations() const
Get the locations of values of type double contained in a state from this space. The order of the val...
Definition: StateSpace.cpp:314
double getSubspaceWeight(const unsigned int index) const
Get the weight of a subspace from the compound state space (used in distance computation) ...
Definition: StateSpace.cpp:927
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 ...
bool isLocked() const
Return true if the state space is locked. A value of true means that no further spaces can be added a...
std::vector< std::size_t > chain
In a complex state space there may be multiple compound state spaces that make up an even larger comp...
Definition: StateSpace.h:115
Representation of the address of a value in a state. This structure stores the indexing information n...
Definition: StateSpace.h:122
No data was copied.
Definition: StateSpace.h:768
StateSpace()
Constructor. Assigns a unique name to the space.
Definition: StateSpace.cpp:86
AdvancedStateCopyOperation copyStateData(const StateSpacePtr &destS, State *dest, const StateSpacePtr &sourceS, const State *source)
Copy data from source (state from space sourceS) to dest (state from space destS) on a component by c...
virtual double getMeasure() const
Get a measure of the space (this can be thought of as a generalization of volume) ...
Definition: StateSpace.cpp:994
virtual StateSamplerPtr allocSubspaceStateSampler(const StateSpace *subspace) const
Allocate a sampler that actually samples only components that are part of subspace.
void diagram(std::ostream &out) const
Print a Graphviz digraph that represents the containment diagram for the state space.
Definition: StateSpace.cpp:546
void registerProjection(const std::string &name, const ProjectionEvaluatorPtr &projection)
Register a projection for this state space under a specified name.
Definition: StateSpace.cpp:747
virtual void computeLocations()
Compute the location information for various components of the state space. Either this function or s...
Definition: StateSpace.cpp:213
void copyFromReals(State *destination, const std::vector< double > &reals) const
Copy the values from reals to the state destination using getValueAddressAtLocation() ...
Definition: StateSpace.cpp:331
void computeSignature(std::vector< int > &signature) const
Compute an array of ints that uniquely identifies the structure of the state space. The first element of the signature is the number of integers that follow.
Definition: StateSpace.cpp:218
virtual void printSettings(std::ostream &out) const
Print the settings for this state space to a stream.
Definition: StateSpace.cpp:384
virtual void registerProjections()
Register the projections for this state space. Usually, this is at least the default projection...
Definition: StateSpace.cpp:232
virtual void setLongestValidSegmentFraction(double segmentFraction)
When performing discrete validation of motions, the length of the longest segment that does not requi...
void registerDefaultProjection(const ProjectionEvaluatorPtr &projection)
Register the default projection for this state space.
Definition: StateSpace.cpp:742
unsigned int longestValidSegmentCountFactor_
The factor to multiply the value returned by validSegmentCount(). Rarely used but useful for things l...
Definition: StateSpace.h:523
void allocStateComponents(CompoundState *state) const
Allocate the state components. Called by allocState(). Usually called by derived state spaces...
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...
std::function< StateSamplerPtr(const StateSpace *)> StateSamplerAllocator
Definition of a function that can allocate a state sampler.
Definition: StateSampler.h:200
const StateSpacePtr & getSubspace(const unsigned int index) const
Get a specific subspace from the compound state space.
Definition: StateSpace.cpp:898
T * as()
Cast this instance to a desired type.
Definition: StateSpace.h:89
All data was copied.
Definition: StateSpace.h:774
virtual void addSampler(const StateSamplerPtr &sampler, double weightImportance)
Add a sampler as part of the new compound sampler. This sampler is used to sample part of the compoun...
virtual void setLongestValidSegmentFraction(double segmentFraction)
When performing discrete validation of motions, the length of the longest segment that does not requi...
Definition: StateSpace.cpp:817
virtual State * allocState() const
Allocate a state that can store a point in the described space.
const std::vector< StateSpacePtr > & getSubspaces() const
Get the list of components.
Definition: StateSpace.cpp:967
virtual void computeLocations()
Compute the location information for various components of the state space. Either this function or s...
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...
A space to allow the composition of state spaces.
Definition: StateSpace.h:549
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
Representation of the address of a substate in a state. This structure stores the indexing informatio...
Definition: StateSpace.h:108
virtual double getMaximumExtent() const
Get the maximum value a call to distance() can return (or an upper bound). For unbounded state spaces...
Definition: StateSpace.cpp:985
const std::map< std::string, SubstateLocation > & getSubstateLocationsByName() const
Get the list of known substate locations (keys of the map corrspond to names of subspaces) ...
Definition: StateSpace.cpp:282
void setSubspaceWeight(const unsigned int index, double weight)
Set the weight of a subspace in the compound state space (used in distance computation) ...
Definition: StateSpace.cpp:943
virtual void printState(const State *state, std::ostream &out) const
Print a state to a stream.
A shared pointer wrapper for ompl::base::ProjectionEvaluator.
StateSpacePtr operator-(const StateSpacePtr &a, const StateSpacePtr &b)
Construct a compound state space that contains subspaces only from a. If a is compound, b (or the components from b, if b is compound) are removed and the remaining components are returned as a compound state space. If the compound space would end up containing solely one component, that component is returned instead.
Representation of a space in which planning can be performed. Topology specific sampling, interpolation and distance are defined.
Definition: StateSpace.h:72
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
unsigned int getValidSegmentCountFactor() const
Get the value used to multiply the return value of validSegmentCount().
Definition: StateSpace.cpp:824
virtual void printSettings(std::ostream &out) const
Print the settings for this state space to a stream.
virtual void freeState(State *state) const
Free the memory of the allocated state.
Definition of an abstract state.
Definition: State.h:50
virtual bool equalStates(const State *state1, const State *state2) const
Checks whether two states are equal.
virtual bool isDiscrete() const
Check if the set of states is discrete.
Definition: StateSpace.cpp:760
void setValidSegmentCountFactor(unsigned int factor)
Set factor to be the value to multiply the return value of validSegmentCount(). By default...
Definition: StateSpace.cpp:810
OptimizationObjectivePtr operator+(const OptimizationObjectivePtr &a, const OptimizationObjectivePtr &b)
Given two optimization objectives, returns a MultiOptimizationObjective that combines the two objecti...
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...
StateSamplerPtr allocSubspaceStateSampler(const StateSpacePtr &subspace) const
Allocate a sampler that actually samples only components that are part of subspace.
Definition: StateSpace.cpp:798
void setStateSamplerAllocator(const StateSamplerAllocator &ssa)
Set the sampler allocator to use.
Definition: StateSpace.cpp:780
bool covers(const StateSpacePtr &other) const
Return true if other is a space that is either included (perhaps equal, perhaps a subspace) in this o...
Definition: StateSpace.cpp:466
Some data was copied.
Definition: StateSpace.h:771
virtual double getMeasure() const =0
Get a measure of the space (this can be thought of as a generalization of volume) ...
virtual bool hasSymmetricDistance() const
Check if the distance function on this state space is symmetric, i.e. distance(s1,s2) = distance(s2,s1). Default implementation returns true.
Definition: StateSpace.cpp:770
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
The exception type for ompl.
Definition: Exception.h:47
double maxExtent_
The extent of this space at the time setup() was called.
Definition: StateSpace.h:514
void declareParam(const std::string &name, const typename SpecificParam< T >::SetterFn &setter, const typename SpecificParam< T >::GetterFn &getter=typename SpecificParam< T >::GetterFn())
This function declares a parameter name, and specifies the setter and getter functions.
Definition: GenericParam.h:239
const std::vector< double > & getSubspaceWeights() const
Get the list of component weights.
Definition: StateSpace.cpp:972
virtual bool isHybrid() const
Check if this is a hybrid state space (i.e., both discrete and continuous components exist) ...
Definition: StateSpace.cpp:877
bool hasSubspace(const std::string &name) const
Check if a specific subspace is contained in this state space.
Definition: StateSpace.cpp:906
void getCommonSubspaces(const StateSpacePtr &other, std::vector< std::string > &subspaces) const
Get the set of subspaces that this space and other have in common. The computed list of subspaces doe...
Definition: StateSpace.cpp:486
virtual void deserialize(State *state, const void *serialization) const
Read the binary representation of a state from serialization and write it to state.
Definition: StateSpace.cpp:375
ompl::base::RealVectorStateSpace
SubstateLocation stateLocation
Location of the substate that contains the pointed to value.
Definition: StateSpace.h:125
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...
double longestValidSegmentFraction_
The fraction of the longest valid segment.
Definition: StateSpace.h:517
const std::map< std::string, ProjectionEvaluatorPtr > & getRegisteredProjections() const
Get all the registered projections.
Definition: StateSpace.cpp:737
State ** components
The components that make up a compound state.
Definition: State.h:142
bool hasProjection(const std::string &name) const
Check if a projection with a specified name is available.
Definition: StateSpace.cpp:709
static void List(std::ostream &out)
Print the list of available state space instances.
Definition: StateSpace.cpp:520
virtual void serialize(void *serialization, const State *state) const
Write the binary representation of state to serialization.
Definition: StateSpace.cpp:371
virtual bool isCompound() const
Check if the state space is compound.
Definition: StateSpace.cpp:755
unsigned int getSubspaceCount() const
Get the number of state spaces that make up the compound state space.
Definition: StateSpace.cpp:893
double longestValidSegment_
The longest valid segment at the time setup() was called.
Definition: StateSpace.h:520
double getLongestValidSegmentLength() const
Get the longest valid segment at the time setup() was called.
Definition: StateSpace.cpp:834
Definition of a compound state sampler. This is useful to construct samplers for compound states...
Definition: StateSampler.h:114
const std::string & getName() const
Get the name of the state space.
Definition: StateSpace.cpp:196
CompoundStateSpace()
Construct an empty compound state space.
Definition: StateSpace.cpp:844
ProjectionEvaluatorPtr getDefaultProjection() const
Get the default projection.
Definition: StateSpace.cpp:714
static const unsigned int TEST_STATE_COUNT
When multiple states need to be generated as part of the computation of various information (usually ...
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-...
double * getValueAddressAtLocation(State *state, const ValueLocation &loc) const
Get a pointer to the double value in state that loc points to.
Definition: StateSpace.cpp:338
const std::map< std::string, ValueLocation > & getValueLocationsByName() const
Get the named locations of values of type double contained in a state from this space. The setup() function must have been previously called.
Definition: StateSpace.cpp:319
double * getValueAddressAtName(State *state, const std::string &name) const
Get a pointer to the double value in state that name points to.
Definition: StateSpace.cpp:354
virtual void copyState(State *destination, const State *source) const =0
Copy a state to another. The memory of source and destination should NOT overlap. ...
const T * as() const
Cast this instance to a desired type.
Definition: State.h:74
const StateSpace * space
The space that is reached if the chain above is followed on the state space.
Definition: StateSpace.h:118
AdvancedStateCopyOperation
The possible outputs for an advanced copy operation.
Definition: StateSpace.h:765
virtual void serialize(void *serialization, const State *state) const
Write the binary representation of state to serialization.
void copyToReals(std::vector< double > &reals, const State *source) const
Copy all the real values from a state source to the array reals using getValueAddressAtLocation() ...
Definition: StateSpace.cpp:324
Construct a sampler that samples only within a subspace of the space.
Definition: StateSampler.h:162
ProjectionEvaluatorPtr getProjection(const std::string &name) const
Get the projection registered under a specific name.
Definition: StateSpace.cpp:725
virtual void printState(const State *state, std::ostream &out) const
Print a state to a stream.
Definition: StateSpace.cpp:379
void clearStateSamplerAllocator()
Clear the state sampler allocator (reset to default)
Definition: StateSpace.cpp:785
virtual unsigned int getDimension() const
Get the dimension of the space (not the dimension of the surrounding ambient space) ...
Definition: StateSpace.cpp:977
virtual void sanityChecks() const
Convenience function that allows derived state spaces to choose which checks should pass (see SanityC...
Definition: StateSpace.cpp:596
virtual unsigned int getSerializationLength() const
Get the number of chars in the serialization of a state in this space.
Definition: StateSpace.cpp:366
OptimizationObjectivePtr operator*(double w, const OptimizationObjectivePtr &a)
Given a weighing factor and an optimization objective, returns a MultiOptimizationObjective containin...
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 list(std::ostream &out) const
Print the list of all contained state space instances.
Definition: StateSpace.cpp:528
Unset type; this is the default type.