time_indexed_rrt_connect.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
31 #include <ompl/geometric/planners/rrt/RRTConnect.h>
32 #include <ompl/util/RandomNumbers.h>
33 
35 
36 namespace exotica
37 {
38 OMPLTimeIndexedRNStateSpace::OMPLTimeIndexedRNStateSpace(TimeIndexedSamplingProblemPtr &prob, TimeIndexedRRTConnectSolverInitializer init) : ompl::base::CompoundStateSpace(), prob_(prob)
39 {
40  setName("OMPLTimeIndexedRNStateSpace");
41  unsigned int dim = prob->N;
42  addSubspace(ompl::base::StateSpacePtr(new ompl::base::RealVectorStateSpace(dim)), 1.0);
43  ompl::base::RealVectorBounds bounds(dim);
44  for (unsigned int i = 0; i < dim; ++i)
45  {
46  bounds.setHigh(i, prob->GetBounds()[i + dim]);
47  bounds.setLow(i, prob->GetBounds()[i]);
48  }
49  getSubspace(0)->as<ompl::base::RealVectorStateSpace>()->setBounds(bounds);
50  addSubspace(ompl::base::StateSpacePtr(new ompl::base::TimeStateSpace), 1.0);
51  getSubspace(1)->as<ompl::base::TimeStateSpace>()->setBounds(prob_->GetStartTime(), prob_->GetGoalTime());
52  lock();
53 }
54 
55 ompl::base::StateSamplerPtr OMPLTimeIndexedRNStateSpace::allocDefaultStateSampler() const
56 {
57  return CompoundStateSpace::allocDefaultStateSampler();
58 }
59 void OMPLTimeIndexedRNStateSpace::ExoticaToOMPLState(const Eigen::VectorXd &q, const double &t, ompl::base::State *state) const
60 {
62  memcpy(ss->getRNSpace().values, q.data(), sizeof(double) * q.rows());
63  ss->getTime().position = t;
64 }
65 void OMPLTimeIndexedRNStateSpace::OMPLToExoticaState(const ompl::base::State *state, Eigen::VectorXd &q, double &t) const
66 {
68  if (q.rows() != prob_->N) q.resize(prob_->N);
69  memcpy(q.data(), ss->getRNSpace().values, sizeof(double) * prob_->N);
70  t = ss->getTime().position;
71 }
72 void OMPLTimeIndexedRNStateSpace::StateDebug(const Eigen::VectorXd &q) const
73 {
74 }
75 
76 OMPLTimeIndexedStateValidityChecker::OMPLTimeIndexedStateValidityChecker(const ompl::base::SpaceInformationPtr &si, const TimeIndexedSamplingProblemPtr &prob) : ompl::base::StateValidityChecker(si), prob_(prob)
77 {
78 }
79 
80 bool OMPLTimeIndexedStateValidityChecker::isValid(const ompl::base::State *state) const
81 {
82  double tmp;
83  return isValid(state, tmp);
84 }
85 
86 bool OMPLTimeIndexedStateValidityChecker::isValid(const ompl::base::State *state, double &dist) const
87 {
88  Eigen::VectorXd q(prob_->N);
89  double t;
90 #if ROS_VERSION_MINIMUM(1, 12, 0) // if ROS version >= ROS_KINETIC
91  std::static_pointer_cast<OMPLTimeIndexedRNStateSpace>(si_->getStateSpace())->OMPLToExoticaState(state, q, t);
92 #else
93  boost::static_pointer_cast<OMPLTimeIndexedRNStateSpace>(si_->getStateSpace())->OMPLToExoticaState(state, q, t);
94 #endif
95 
96  if (!prob_->IsValid(q, t))
97  {
98  dist = -1;
99  return false;
100  }
101  return true;
102 }
103 
104 // The solver
105 void TimeIndexedRRTConnectSolver::Instantiate(const TimeIndexedRRTConnectSolverInitializer &init)
106 {
107  this->parameters_ = init;
108  algorithm_ = "Exotica_TimeIndexedRRTConnect";
109  planner_allocator_ = boost::bind(&allocatePlanner<OMPLTimeIndexedRRTConnect>, _1, _2);
110 
111  if (this->parameters_.RandomSeed > -1)
112  {
113  HIGHLIGHT_NAMED(algorithm_, "Setting random seed to " << this->parameters_.RandomSeed);
114  ompl::RNG::setSeed(static_cast<long unsigned int>(this->parameters_.RandomSeed));
115  }
116 }
117 
119 
120 {
122  prob_ = std::static_pointer_cast<TimeIndexedSamplingProblem>(pointer);
123  state_space_.reset(new OMPLTimeIndexedRNStateSpace(prob_, this->parameters_));
124  ompl_simple_setup_.reset(new ompl::geometric::SimpleSetup(state_space_));
125  ompl_simple_setup_->setStateValidityChecker(ompl::base::StateValidityCheckerPtr(new OMPLTimeIndexedStateValidityChecker(ompl_simple_setup_->getSpaceInformation(), prob_)));
126  ompl_simple_setup_->setPlannerAllocator(boost::bind(planner_allocator_, _1, "Exotica_" + algorithm_));
127  ompl_simple_setup_->getSpaceInformation()->setStateValidityCheckingResolution(this->parameters_.ValidityCheckResolution);
128 
129  ompl_simple_setup_->getSpaceInformation()->setup();
130  ompl_simple_setup_->setup();
131  if (ompl_simple_setup_->getPlanner()->params().hasParam("Range")) ompl_simple_setup_->getPlanner()->params().setParam("Range", this->parameters_.Range);
132 }
133 
135 {
136  // clear previously computed solutions
137  ompl_simple_setup_->getProblemDefinition()->clearSolutionPaths();
138  const ompl::base::PlannerPtr planner = ompl_simple_setup_->getPlanner();
139  if (planner) planner->clear();
140  ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->resetMotionCounter();
141  ompl_simple_setup_->getPlanner()->setProblemDefinition(ompl_simple_setup_->getProblemDefinition());
142 }
143 
145 {
146  ompl_simple_setup_->clearStartStates();
147  int v = ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->getValidMotionCount();
148  int iv = ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->getInvalidMotionCount();
149  CONSOLE_BRIDGE_logDebug("There were %d valid motions and %d invalid motions.", v, iv);
150 
151  if (ompl_simple_setup_->getProblemDefinition()->hasApproximateSolution())
152  CONSOLE_BRIDGE_logWarn("Computed solution is approximate");
153  ptc_.reset();
154 }
155 
156 void TimeIndexedRRTConnectSolver::SetGoalState(const Eigen::VectorXd &qT, const double t, const double eps)
157 {
158  ompl::base::ScopedState<> gs(state_space_);
159  state_space_->as<OMPLTimeIndexedRNStateSpace>()->ExoticaToOMPLState(qT, t, gs.get());
160  if (!ompl_simple_setup_->getStateValidityChecker()->isValid(gs.get()))
161  {
162  ThrowNamed("Goal state is not valid!");
163  }
164 
165  if (!ompl_simple_setup_->getSpaceInformation()->satisfiesBounds(gs.get()))
166  {
167  state_space_->as<OMPLTimeIndexedRNStateSpace>()->StateDebug(qT);
168 
169  // Debug state and bounds
170  std::string out_of_bounds_joint_ids = "";
171  for (int i = 0; i < qT.rows(); ++i)
172  if (qT(i) < prob_->GetBounds()[i] || qT(i) > prob_->GetBounds()[i + qT.rows()]) out_of_bounds_joint_ids += "[j" + std::to_string(i) + "=" + std::to_string(qT(i)) + ", ll=" + std::to_string(prob_->GetBounds()[i]) + ", ul=" + std::to_string(prob_->GetBounds()[i + qT.rows()]) + "]\n";
173 
174  ThrowNamed("Invalid goal state [Invalid joint bounds for joint indices: \n"
175  << out_of_bounds_joint_ids << "]");
176  }
177  ompl_simple_setup_->setGoalState(gs, eps);
178 }
179 
180 void TimeIndexedRRTConnectSolver::GetPath(Eigen::MatrixXd &traj, ompl::base::PlannerTerminationCondition &ptc)
181 {
182  ompl::geometric::PathSimplifierPtr psf_ = ompl_simple_setup_->getPathSimplifier();
183  const ompl::base::SpaceInformationPtr &si = ompl_simple_setup_->getSpaceInformation();
184 
185  ompl::geometric::PathGeometric pg = ompl_simple_setup_->getSolutionPath();
186  if (this->parameters_.Smooth)
187  {
188  bool tryMore = false;
189  if (ptc == false) tryMore = psf_->reduceVertices(pg);
190  if (ptc == false) psf_->collapseCloseVertices(pg);
191  int times = 0;
192  while (times < 10 && tryMore && ptc == false)
193  {
194  tryMore = psf_->reduceVertices(pg);
195  ++times;
196  }
197  if (si->getStateSpace()->isMetricSpace())
198  {
199  if (ptc == false)
200  tryMore = psf_->shortcutPath(pg);
201  else
202  tryMore = false;
203  while (times < 10 && tryMore && ptc == false)
204  {
205  tryMore = psf_->shortcutPath(pg);
206  ++times;
207  }
208  }
209  }
210  std::vector<ompl::base::State *> &states = pg.getStates();
211  unsigned int length = 0;
212 
213  if (this->parameters_.TrajectoryPointsPerSecond <= 0)
214  {
215  const int n1 = states.size() - 1;
216  for (int i = 0; i < n1; ++i)
217  length += si->getStateSpace()->validSegmentCount(states[i], states[i + 1]);
218  }
219  else
220  {
221  double tstart, tgoal;
222  Eigen::VectorXd qs, qg;
223  state_space_->as<OMPLTimeIndexedRNStateSpace>()->OMPLToExoticaState(pg.getState(0), qs, tstart);
224  state_space_->as<OMPLTimeIndexedRNStateSpace>()->OMPLToExoticaState(pg.getState(states.size() - 1), qg, tgoal);
225  length = static_cast<int>(std::ceil((tgoal - tstart) * this->parameters_.TrajectoryPointsPerSecond));
226  }
227  pg.interpolate(length);
228 
229  traj.resize(pg.getStateCount(), this->parameters_.AddTimeIntoSolution ? prob_->GetSpaceDim() + 1 : prob_->GetSpaceDim());
230  Eigen::VectorXd tmp(prob_->GetSpaceDim());
231  Eigen::VectorXd ts(pg.getStateCount());
232  for (int i = 0; i < (int)pg.getStateCount(); ++i)
233  {
234  state_space_->as<OMPLTimeIndexedRNStateSpace>()->OMPLToExoticaState(pg.getState(i), tmp, ts(i));
235  traj.row(i).tail(prob_->GetSpaceDim()) = tmp;
236  }
237  if (this->parameters_.AddTimeIntoSolution) traj.col(0) = ts;
238 }
239 
240 void TimeIndexedRRTConnectSolver::Solve(Eigen::MatrixXd &solution)
241 {
242  Timer timer;
243 
244  // Reset bounds on time space
245  ompl::base::TimeStateSpace *time_space = ompl_simple_setup_->getStateSpace()->as<ompl::base::CompoundStateSpace>()->getSubspace(1)->as<ompl::base::TimeStateSpace>();
246  time_space->setBounds(prob_->GetStartTime(), prob_->GetGoalTime());
247 
248  // Set goal state
249  SetGoalState(prob_->GetGoalState(), prob_->GetGoalTime());
250 
251  // Set start state
252  Eigen::VectorXd q0 = prob_->ApplyStartState();
253  ompl::base::ScopedState<> ompl_start_state(state_space_);
254  state_space_->as<OMPLTimeIndexedRNStateSpace>()->ExoticaToOMPLState(q0, prob_->GetStartTime(), ompl_start_state.get());
255  ompl_simple_setup_->setStartState(ompl_start_state);
256 
257  PreSolve();
258  ompl::time::point start = ompl::time::now();
259  if (!ptc_)
260  ptc_.reset(new ompl::base::PlannerTerminationCondition(ompl::base::timedPlannerTerminationCondition(this->parameters_.Timeout - ompl::time::seconds(ompl::time::now() - start))));
261  if (ompl_simple_setup_->solve(*ptc_) == ompl::base::PlannerStatus::EXACT_SOLUTION && ompl_simple_setup_->haveSolutionPath())
262  {
263  GetPath(solution, *ptc_);
264  }
265  PostSolve();
266 
267  planning_time_ = timer.GetDuration();
268 }
269 
270 void TimeIndexedRRTConnectSolver::SetPlannerTerminationCondition(const std::shared_ptr<ompl::base::PlannerTerminationCondition> &ptc)
271 {
272  ptc_ = ptc;
273 }
274 
275 OMPLTimeIndexedRRTConnect::OMPLTimeIndexedRRTConnect(const base::SpaceInformationPtr &si) : base::Planner(si, "OMPLTimeIndexedRRTConnect")
276 {
277  specs_.recognizedGoal = base::GOAL_SAMPLEABLE_REGION;
278  specs_.directed = true;
279 
280  maxDistance_ = 0.0;
281 
282  Planner::declareParam<double>("range", this, &OMPLTimeIndexedRRTConnect::setRange, &OMPLTimeIndexedRRTConnect::getRange, "0.:1.:10000.");
283  connectionPoint_ = std::make_pair<base::State *, base::State *>(nullptr, nullptr);
284 }
285 
287 {
288  freeMemory();
289 }
290 
292 {
293  Planner::setup();
294  tools::SelfConfig sc(si_, getName());
295  sc.configurePlannerRange(maxDistance_);
296 
297 #if ROS_VERSION_MINIMUM(1, 12, 0) // if ROS version >= ROS_KINETIC
298  if (!tStart_) tStart_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
299  if (!tGoal_) tGoal_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
300 #else
301  if (!tStart_)
302  tStart_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(si_->getStateSpace()));
303  if (!tGoal_)
304  tGoal_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(si_->getStateSpace()));
305 #endif
306  tStart_->setDistanceFunction(boost::bind(&OMPLTimeIndexedRRTConnect::reverseTimeDistance, this, _1, _2));
307  tGoal_->setDistanceFunction(boost::bind(&OMPLTimeIndexedRRTConnect::forwardTimeDistance, this, _1, _2));
308 }
309 
311 {
312  std::vector<Motion *> motions;
313 
314  if (tStart_)
315  {
316  tStart_->list(motions);
317  for (unsigned int i = 0; i < motions.size(); ++i)
318  {
319  if (motions[i]->state) si_->freeState(motions[i]->state);
320  delete motions[i];
321  }
322  }
323 
324  if (tGoal_)
325  {
326  tGoal_->list(motions);
327  for (unsigned int i = 0; i < motions.size(); ++i)
328  {
329  if (motions[i]->state) si_->freeState(motions[i]->state);
330  delete motions[i];
331  }
332  }
333 }
334 
336 {
337  Planner::clear();
338  sampler_.reset();
339  freeMemory();
340  if (tStart_) tStart_->clear();
341  if (tGoal_) tGoal_->clear();
342  connectionPoint_ = std::make_pair<base::State *, base::State *>(nullptr, nullptr);
343 }
344 
346 {
347  // find closest state in the tree
348  Motion *nmotion = tree->nearest(rmotion);
349 
350  bool changed = false;
351  if (!correctTime(nmotion, rmotion, !tgi.start, changed)) return TRAPPED;
352 
353  // assume we can reach the state we go towards
354  bool reach = !changed;
355 
356  // find state to add
357  base::State *dstate = rmotion->state;
358  double d = si_->distance(nmotion->state, rmotion->state);
359  if (d > maxDistance_)
360  {
361  si_->getStateSpace()->interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
362  dstate = tgi.xstate;
363  reach = false;
364  }
365  // if we are in the start tree, we just check the motion like we normally do;
366  // if we are in the goal tree, we need to check the motion in reverse, but checkMotion() assumes the first state it receives as argument is valid,
367  // so we check that one first
368  bool validMotion = tgi.start ? si_->checkMotion(nmotion->state, dstate) : si_->getStateValidityChecker()->isValid(dstate) && si_->checkMotion(dstate, nmotion->state);
369 
370  if (validMotion)
371  {
372  // create a motion
373  Motion *motion = new Motion(si_);
374  si_->copyState(motion->state, dstate);
375  motion->parent = nmotion;
376  motion->root = nmotion->root;
377  tgi.xmotion = motion;
378 
379  tree->add(motion);
380  if (reach)
381  {
382  return REACHED;
383  }
384  else
385  {
386  return ADVANCED;
387  }
388  }
389  else
390  return TRAPPED;
391 }
392 
393 ompl::base::PlannerStatus OMPLTimeIndexedRRTConnect::solve(const base::PlannerTerminationCondition &ptc)
394 {
395  checkValidity();
396  base::GoalSampleableRegion *goal = dynamic_cast<base::GoalSampleableRegion *>(pdef_->getGoal().get());
397 
398  if (!goal)
399  {
400  OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
401  return base::PlannerStatus::UNRECOGNIZED_GOAL_TYPE;
402  }
403  // std::cout << "getStartStateCount() in OMPLTimeIndexedRRTConnect: " << pdef_->getStartStateCount() << std::endl;
404  // const base::State *check_st = pdef_->getStartState(0);
405  // std::cout << "isValid: in OMPLTimeIndexedRRTConnect: " << si_->isValid(check_st) << std::endl;
406 
407  while (const base::State *st = pis_.nextStart())
408  {
409  Motion *motion = new Motion(si_);
410  si_->copyState(motion->state, st);
411  motion->root = motion->state;
412  tStart_->add(motion);
413  }
414 
415  if (tStart_->size() == 0)
416  {
417  OMPL_ERROR("%s: Motion planning start tree could not be initialized!", getName().c_str());
418  return base::PlannerStatus::INVALID_START;
419  }
420 
421  if (!goal->couldSample())
422  {
423  OMPL_ERROR("%s: Insufficient states in sampleable goal region", getName().c_str());
424  return base::PlannerStatus::INVALID_GOAL;
425  }
426 
427  if (!sampler_) sampler_ = si_->allocStateSampler();
428 
429  OMPL_INFORM("%s: Starting planning with %d states already in datastructure", getName().c_str(), (int)(tStart_->size() + tGoal_->size()));
430 
431  TreeGrowingInfo tgi;
432  tgi.xstate = si_->allocState();
433 
434  Motion *rmotion = new Motion(si_);
435  base::State *rstate = rmotion->state;
436  bool startTree = true;
437  bool solved = false;
438 
439  while (ptc == false)
440  {
441  TreeData &tree = startTree ? tStart_ : tGoal_;
442  tgi.start = startTree;
443  startTree = !startTree;
444  TreeData &otherTree = startTree ? tStart_ : tGoal_;
445 
446  if (tGoal_->size() == 0 || pis_.getSampledGoalsCount() < tGoal_->size() / 2)
447  {
448  const base::State *st = tGoal_->size() == 0 ? pis_.nextGoal(ptc) : pis_.nextGoal();
449  if (st)
450  {
451  Motion *motion = new Motion(si_);
452  si_->copyState(motion->state, st);
453  motion->root = motion->state;
454  tGoal_->add(motion);
455  }
456 
457  if (tGoal_->size() == 0)
458  {
459  OMPL_ERROR("%s: Unable to sample any valid states for goal tree", getName().c_str());
460  break;
461  }
462  }
463 
464  // sample random state
465  sampler_->sampleUniform(rstate);
466  reverse_check_ = false;
467  GrowState gs = growTree(tree, tgi, rmotion);
468 
469  if (gs != TRAPPED)
470  {
471  // remember which motion was just added
472  Motion *addedMotion = tgi.xmotion;
473 
474  // attempt to connect trees
475 
476  // if reached, it means we used rstate directly, no need top copy again
477  if (gs != REACHED) si_->copyState(rstate, tgi.xstate);
478 
479  GrowState gsc = ADVANCED;
480  tgi.start = startTree;
481 
482  reverse_check_ = true;
483  while (ptc == false && gsc == ADVANCED)
484  {
485  gsc = growTree(otherTree, tgi, rmotion);
486  }
487 
488  Motion *startMotion = startTree ? tgi.xmotion : addedMotion;
489  Motion *goalMotion = startTree ? addedMotion : tgi.xmotion;
490 
491  // if we connected the trees in a valid way (start and goal pair is valid)
492  if (gsc == REACHED && goal->isStartGoalPairValid(startMotion->root, goalMotion->root))
493  {
494  // it must be the case that either the start tree or the goal tree has made some progress
495  // so one of the parents is not nullptr. We go one step 'back' to avoid having a duplicate state
496  // on the solution path
497  if (startMotion->parent)
498  startMotion = startMotion->parent;
499  else
500  goalMotion = goalMotion->parent;
501 
502  connectionPoint_ = std::make_pair(startMotion->state, goalMotion->state);
503 
504  // construct the solution path
505  Motion *solution = startMotion;
506  std::vector<Motion *> mpath1;
507  while (solution != nullptr)
508  {
509  mpath1.push_back(solution);
510  solution = solution->parent;
511  }
512 
513  solution = goalMotion;
514  std::vector<Motion *> mpath2;
515  while (solution != nullptr)
516  {
517  mpath2.push_back(solution);
518  solution = solution->parent;
519  }
520 
521  ompl::geometric::PathGeometric *path = new ompl::geometric::PathGeometric(si_);
522  path->getStates().reserve(mpath1.size() + mpath2.size());
523  for (int i = mpath1.size() - 1; i >= 0; --i)
524  path->append(mpath1[i]->state);
525  for (unsigned int i = 0; i < mpath2.size(); ++i)
526  path->append(mpath2[i]->state);
527 
528  pdef_->addSolutionPath(base::PathPtr(path), false, 0.0, getName());
529  solved = true;
530  break;
531  }
532  }
533  }
534 
535  si_->freeState(tgi.xstate);
536  si_->freeState(rstate);
537  delete rmotion;
538 
539  OMPL_INFORM("%s: Created %u states (%u start + %u goal)", getName().c_str(), tStart_->size() + tGoal_->size(), tStart_->size(), tGoal_->size());
540  return solved ? base::PlannerStatus::EXACT_SOLUTION : base::PlannerStatus::TIMEOUT;
541 }
542 
543 void OMPLTimeIndexedRRTConnect::getPlannerData(base::PlannerData &data) const
544 {
545  Planner::getPlannerData(data);
546 
547  std::vector<Motion *> motions;
548  if (tStart_) tStart_->list(motions);
549 
550  for (unsigned int i = 0; i < motions.size(); ++i)
551  {
552  if (motions[i]->parent == nullptr)
553  data.addStartVertex(base::PlannerDataVertex(motions[i]->state, 1));
554  else
555  {
556  data.addEdge(base::PlannerDataVertex(motions[i]->parent->state, 1), base::PlannerDataVertex(motions[i]->state, 1));
557  }
558  }
559 
560  motions.clear();
561  if (tGoal_) tGoal_->list(motions);
562 
563  for (unsigned int i = 0; i < motions.size(); ++i)
564  {
565  if (motions[i]->parent == nullptr)
566  data.addGoalVertex(base::PlannerDataVertex(motions[i]->state, 2));
567  else
568  {
569  // The edges in the goal tree are reversed to be consistent with start tree
570  data.addEdge(base::PlannerDataVertex(motions[i]->state, 2), base::PlannerDataVertex(motions[i]->parent->state, 2));
571  }
572  }
573 
574  // Add the edge connecting the two trees
575  data.addEdge(data.vertexIndex(connectionPoint_.first), data.vertexIndex(connectionPoint_.second));
576 }
577 } // namespace exotica
#define CONSOLE_BRIDGE_logWarn(fmt,...)
d
void ExoticaToOMPLState(const Eigen::VectorXd &q, const double &t, ompl::base::State *state) const
void setRange(double distance)
Set the range the planner is supposed to use. This parameter greatly influences the runtime of the al...
void Solve(Eigen::MatrixXd &solution) override
std::string getName(void *handle)
OMPLTimeIndexedStateValidityChecker(const ompl::base::SpaceInformationPtr &si, const TimeIndexedSamplingProblemPtr &prob)
base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc) override
const ompl::base::TimeStateSpace::StateType & getTime() const
void GetPath(Eigen::MatrixXd &traj, ompl::base::PlannerTerminationCondition &ptc)
#define CONSOLE_BRIDGE_logDebug(fmt,...)
virtual void SpecifyProblem(PlanningProblemPtr pointer)
progress has been made towards the randomly sampled state
bool correctTime(const Motion *a, Motion *b, bool reverse, bool &changed) const
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
void Instantiate(const TimeIndexedRRTConnectSolverInitializer &init) override
std::pair< base::State *, base::State * > connectionPoint_
The pair of states in each tree connected during planning. Used for PlannerData computation.
OMPLTimeIndexedRRTConnect(const base::SpaceInformationPtr &si)
Information attached to growing a tree of motions (used internally)
GrowState
The state of the tree after an attempt to extend it.
void SetGoalState(const Eigen::VectorXd &qT, const double t, const double eps=0)
#define ThrowNamed(m)
bool isValid(const ompl::base::State *state) const override
double getRange() const
Get the range the planner is using.
void SpecifyProblem(PlanningProblemPtr pointer) override
ompl::base::StateSamplerPtr allocDefaultStateSampler() const override
double maxDistance_
The maximum length of a motion to be added to a tree.
base::StateSamplerPtr sampler_
State sampler.
void OMPLToExoticaState(const ompl::base::State *state, Eigen::VectorXd &q, double &t) const
void getPlannerData(base::PlannerData &data) const override
#define HIGHLIGHT_NAMED(name, x)
double reverseTimeDistance(const Motion *a, const Motion *b) const
std::shared_ptr< exotica::TimeIndexedSamplingProblem > TimeIndexedSamplingProblemPtr
void SetPlannerTerminationCondition(const std::shared_ptr< ompl::base::PlannerTerminationCondition > &ptc)
double GetDuration() const
std::shared_ptr< PlanningProblem > PlanningProblemPtr
the randomly sampled state was reached
const ompl::base::RealVectorStateSpace::StateType & getRNSpace() const
void freeMemory()
Free the memory allocated by this planner.
double forwardTimeDistance(const Motion *a, const Motion *b) const
std::shared_ptr< NearestNeighbors< Motion * > > TreeData
A nearest-neighbor datastructure representing a tree of motions.
GrowState growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion)
Grow a tree towards a random state.
void StateDebug(const Eigen::VectorXd &q) const


exotica_time_indexed_rrt_connect_solver
Author(s): Yiming Yang
autogenerated on Sat Apr 10 2021 02:36:59