Loading...
Searching...
No Matches
STRRTstar.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2021, Technische Universität Berlin (TU Berlin)
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 TU Berlin nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Francesco Grothe */
36
37#include "ompl/geometric/planners/rrt/STRRTstar.h"
38#include <ompl/util/Exception.h>
39#include <ompl/base/ScopedState.h>
40
41ompl::geometric::STRRTstar::STRRTstar(const ompl::base::SpaceInformationPtr &si)
42 : Planner(si, "SpaceTimeRRT"), sampler_(&(*si), startMotion_, goalMotions_, newBatchGoalMotions_, sampleOldBatch_)
43{
44 if (std::dynamic_pointer_cast<ompl::base::SpaceTimeStateSpace>(si->getStateSpace()) == nullptr)
45 {
46 OMPL_ERROR("%s: State Space needs to be of type SpaceTimeStateSpace.", getName().c_str());
47 throw ompl::Exception("Non-SpaceTimeStateSpace");
48 }
49 specs_.optimizingPaths = true;
50 specs_.canReportIntermediateSolutions = true;
51 Planner::declareParam<double>("range", this, &STRRTstar::setRange, &STRRTstar::getRange, "0.:1.:10000.");
52 distanceBetweenTrees_ = std::numeric_limits<double>::infinity();
53}
54
55ompl::geometric::STRRTstar::~STRRTstar()
56{
57 freeMemory();
58}
59
61{
62 Planner::setup();
65
66 if (!tStart_)
68 if (!tGoal_)
70 tStart_->setDistanceFunction([this](const Motion *a, const Motion *b) { return distanceFunction(a, b); });
71 tGoal_->setDistanceFunction([this](const Motion *a, const Motion *b) { return distanceFunction(a, b); });
72
73 if (si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->getTimeComponent()->isBounded())
74 {
76 si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->getTimeComponent()->getMaxTimeBound();
77 isTimeBounded_ = true;
78 }
79 else
80 {
81 upperTimeBound_ = std::numeric_limits<double>::infinity();
82 isTimeBounded_ = false;
83 }
85
86 si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->updateEpsilon();
87 // Calculate some constants:
89}
90
92{
93 std::vector<Motion *> motions;
94
95 if (tStart_)
96 {
97 tStart_->list(motions);
98 for (auto &motion : motions)
99 {
100 if (motion->state != nullptr)
101 si_->freeState(motion->state);
102 delete motion;
103 }
104 }
105
106 if (tGoal_)
107 {
108 tGoal_->list(motions);
109 for (auto &motion : motions)
110 {
111 if (motion->state != nullptr)
112 si_->freeState(motion->state);
113 delete motion;
114 }
115 }
116
117 if (tempState_)
118 si_->freeState(tempState_);
119}
120
122{
124 auto *goal = dynamic_cast<ompl::base::GoalSampleableRegion *>(pdef_->getGoal().get());
125
126 if (goal == nullptr)
127 {
128 OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
130 }
131
132 while (const ompl::base::State *st = pis_.nextStart())
133 {
134 auto *motion = new Motion(si_);
135 si_->copyState(motion->state, st);
136 motion->root = motion->state;
137 tStart_->add(motion);
138 startMotion_ = motion;
139 }
140
141 if (tStart_->size() == 0)
142 {
143 OMPL_ERROR("%s: Motion planning start tree could not be initialized!", getName().c_str());
145 }
146
147 if (!goal->couldSample())
148 {
149 OMPL_ERROR("%s: Insufficient states in sampleable goal region", getName().c_str());
151 }
152
153 OMPL_INFORM("%s: Starting planning with %d states already in datastructure", getName().c_str(),
154 (int)(tStart_->size() + tGoal_->size()));
155
156 TreeGrowingInfo tgi;
157 // Use ScopedState to ensure automatic cleanup even if exceptions are thrown
158 ompl::base::ScopedState<> xstateScoped(si_);
159 tgi.xstate = xstateScoped.get();
160
161 std::vector<Motion *> nbh;
162 const ompl::base::ReportIntermediateSolutionFn intermediateSolutionCallback =
163 pdef_->getIntermediateSolutionCallback();
164
165 Motion *approxsol = nullptr;
166 double approxdif = std::numeric_limits<double>::infinity();
167 auto *rmotion = new Motion(si_);
168 ompl::base::State *rstate = rmotion->state;
169 bool startTree = true;
170 bool solved = false;
171
172 // samples to fill the current batch
173 unsigned int batchSize = initialBatchSize_;
174
175 // number of samples in the current batch
176 int numBatchSamples = static_cast<int>(tStart_->size() + tGoal_->size()); // number of samples in the current batch
177
178 // number of goal samples in the new batch region
179 int newBatchGoalSamples = 0;
180
181 bool firstBatch = true;
182
183 // probability to sample the old batch region
184 double oldBatchSampleProb = 1.0;
185
186 // Time Bound factor for the old batch.
187 double oldBatchTimeBoundFactor = initialTimeBoundFactor_;
188
189 // Time Bound factor for the new batch.
190 double newBatchTimeBoundFactor = initialTimeBoundFactor_;
191
192 bool forceGoalSample = true;
193
194 OMPL_INFORM("%s: Starting planning with time bound factor %.2f", getName().c_str(), newBatchTimeBoundFactor);
195
196 while (!ptc)
197 {
199 TreeData &tree = startTree ? tStart_ : tGoal_;
200 tgi.start = startTree;
201 startTree = !startTree;
202 TreeData &otherTree = startTree ? tStart_ : tGoal_;
203
204 // batch is full
205 if (!isTimeBounded_ && (unsigned int)numBatchSamples >= batchSize)
206 {
207 if (firstBatch)
208 {
209 firstBatch = false;
210 oldBatchSampleProb = 0.5 * (1 / timeBoundFactorIncrease_);
211 }
212 increaseTimeBound(false, oldBatchTimeBoundFactor, newBatchTimeBoundFactor, startTree, batchSize,
213 numBatchSamples);
214 // transfer new batch goals to old batch
215 if (!newBatchGoalMotions_.empty())
216 {
218 newBatchGoalMotions_.clear();
219 }
220 continue;
221 }
222
223 // determine whether the old or new batch is sampled
224 sampleOldBatch_ =
225 (firstBatch || isTimeBounded_ || !sampleUniformForUnboundedTime_ || rng_.uniform01() <= oldBatchSampleProb);
226
227 // *** Begin Goal Sampling ***
228
229 ompl::base::State *goalState{nullptr};
230 if (sampleOldBatch_)
231 {
232 // sample until successful or time is up
233 if (goalMotions_.empty() && isTimeBounded_)
234 goalState = nextGoal(ptc, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
235 // sample for n tries, with n = batch size
236 else if (goalMotions_.empty() && !isTimeBounded_)
237 {
238 goalState = nextGoal(static_cast<int>(batchSize), oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
239 // the goal region is most likely blocked for this time period -> increase upper time bound
240 if (goalState == nullptr)
241 {
242 increaseTimeBound(true, oldBatchTimeBoundFactor, newBatchTimeBoundFactor, startTree, batchSize,
243 numBatchSamples);
244 continue;
245 }
246 }
247 // sample for a single try
248 else if (forceGoalSample ||
249 goalMotions_.size() < (tGoal_->size() - newBatchGoalSamples) / goalStateSampleRatio_)
250 {
251 goalState = nextGoal(1, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
252 forceGoalSample = false;
253 }
254 }
255 else
256 {
257 if (newBatchGoalMotions_.empty())
258 {
259 goalState = nextGoal(static_cast<int>(batchSize), oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
260 // the goal region is most likely blocked for this time period -> increase upper time bound
261 if (goalState == nullptr)
262 {
263 increaseTimeBound(false, oldBatchTimeBoundFactor, newBatchTimeBoundFactor, startTree, batchSize,
264 numBatchSamples);
265 continue;
266 }
267 }
268 else if (forceGoalSample ||
269 newBatchGoalMotions_.size() < (unsigned long)(newBatchGoalSamples / goalStateSampleRatio_))
270 {
271 goalState = nextGoal(1, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
272 forceGoalSample = false;
273 }
274 }
275
276 if (goalState != nullptr)
277 {
278 auto *motion = new Motion(si_);
279 si_->copyState(motion->state, goalState);
280 motion->root = motion->state;
281 tGoal_->add(motion);
282 if (sampleOldBatch_)
283 goalMotions_.push_back(motion);
284 else
285 {
286 newBatchGoalMotions_.push_back(motion);
287 newBatchGoalSamples++;
288 }
289
291 std::min(minimumTime_, si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->timeToCoverDistance(
292 startMotion_->state, goalState));
293 numBatchSamples++;
294 }
295
296 // *** End Goal Sampling ***
297
298 /* sample random state */
299 bool success = sampler_.sample(rstate);
300 if (!success)
301 {
302 forceGoalSample = true;
303 continue;
304 }
305
306 // EXTEND
307 GrowState gs = growTree(tree, tgi, rmotion, nbh, false);
308 if (gs != TRAPPED)
309 {
310 numBatchSamples++;
311 /* remember which motion was just added */
312 Motion *addedMotion = tgi.xmotion;
313 Motion *startMotion;
314 Motion *goalMotion;
315
316 /* rewire the goal tree */
317 bool newSolution = false;
318 if (!tgi.start && rewireState_ != OFF)
319 {
320 newSolution = rewireGoalTree(addedMotion);
321 if (newSolution)
322 {
323 // find connection point
324 std::queue<Motion *> queue;
325 queue.push(addedMotion);
326 while (!queue.empty())
327 {
328 if (queue.front()->connectionPoint != nullptr)
329 {
330 goalMotion = queue.front();
331 startMotion = queue.front()->connectionPoint;
332 break;
333 }
334 else
335 {
336 for (Motion *c : queue.front()->children)
337 queue.push(c);
338 }
339 queue.pop();
340 }
341 }
342 }
343
344 /* if reached, it means we used rstate directly, no need to copy again */
345 if (gs != REACHED)
346 si_->copyState(rstate, tgi.xstate);
347
348 tgi.start = startTree;
349
350 /* attempt to connect trees, if rewiring didn't find a new solution */
351 // CONNECT
352 if (!newSolution)
353 {
354 int totalSamples = static_cast<int>(tStart_->size() + tGoal_->size());
355 GrowState gsc = growTree(otherTree, tgi, rmotion, nbh, true);
356 if (gsc == REACHED)
357 {
358 newSolution = true;
359 startMotion = startTree ? tgi.xmotion : addedMotion;
360 goalMotion = startTree ? addedMotion : tgi.xmotion;
361 // it must be the case that either the start tree or the goal tree has made some progress
362 // so one of the parents is not nullptr. We go one step 'back' to avoid having a duplicate state
363 // on the solution path
364 if (startMotion->parent != nullptr)
365 startMotion = startMotion->parent;
366 else
367 goalMotion = goalMotion->parent;
368 }
369 numBatchSamples += static_cast<int>(tStart_->size() + tGoal_->size()) - totalSamples;
370 }
371
372 /* update distance between trees */
373 const double newDist = tree->getDistanceFunction()(addedMotion, otherTree->nearest(addedMotion));
374 if (newDist < distanceBetweenTrees_)
375 {
376 distanceBetweenTrees_ = newDist;
377 // OMPL_INFORM("Estimated distance to go: %f", distanceBetweenTrees_);
378 }
379
380 /* if we connected the trees in a valid way (start and goal pair is valid)*/
381 if (newSolution && goal->isStartGoalPairValid(startMotion->root, goalMotion->root))
382 {
383 constructSolution(startMotion, goalMotion, intermediateSolutionCallback, ptc);
384 solved = true;
385 if (ptc || upperTimeBound_ == minimumTime_)
386 break; // first solution is enough or optimal solution is found
387 // continue to look for solutions with the narrower time bound until the termination condition is met
388 }
389 else
390 {
391 // We didn't reach the goal, but if we were extending the start
392 // tree, then we can mark/improve the approximate path so far.
393 if (!startTree)
394 {
395 // We were working from the startTree.
396 double dist = 0.0;
397 goal->isSatisfied(tgi.xmotion->state, &dist);
398 if (dist < approxdif)
399 {
400 approxdif = dist;
401 approxsol = tgi.xmotion;
402 }
403 }
404 }
405 }
406 }
407
408 // No need to manually free tgi.xstate anymore - ScopedState handles it
409 si_->freeState(rstate);
410 delete rmotion;
411
412 OMPL_INFORM("%s: Created %u states (%u start + %u goal)", getName().c_str(), tStart_->size() + tGoal_->size(),
413 tStart_->size(), tGoal_->size());
414
415 if (approxsol && !solved)
416 {
417 /* construct the solution path */
418 std::vector<Motion *> mpath;
419 while (approxsol != nullptr)
420 {
421 mpath.push_back(approxsol);
422 approxsol = approxsol->parent;
423 }
424
425 auto path(std::make_shared<ompl::geometric::PathGeometric>(si_));
426 for (int i = mpath.size() - 1; i >= 0; --i)
427 path->append(mpath[i]->state);
428 pdef_->addSolutionPath(path, true, approxdif, getName());
430 }
431 if (solved)
432 {
433 // Add the solution path.
435 psol.setPlannerName(getName());
436
437 ompl::base::OptimizationObjectivePtr optimizationObjective =
438 std::make_shared<ompl::base::MinimizeArrivalTime>(si_);
439 psol.setOptimized(optimizationObjective, ompl::base::Cost(bestTime_), false);
440 pdef_->addSolutionPath(psol);
441 }
442
444}
445
448 std::vector<Motion *> &nbh, bool connect)
449{
450 // If connect, advance from single nearest neighbor until the random state is reached or trapped
451 if (connect)
452 {
453 GrowState gsc = ADVANCED;
454 while (gsc == ADVANCED)
455 {
456 // get nearest motion
457 Motion *nmotion = tree->nearest(rmotion);
458 gsc = growTreeSingle(tree, tgi, rmotion, nmotion);
459 }
460 return gsc;
461 }
462 if (rewireState_ == OFF)
463 {
464 Motion *nmotion = tree->nearest(rmotion);
465 return growTreeSingle(tree, tgi, rmotion, nmotion);
466 }
467 // get Neighborhood of random state
468 getNeighbors(tree, rmotion, nbh);
469 // in start tree sort by distance
470 if (tgi.start)
471 {
472 std::sort(nbh.begin(), nbh.end(), [this, &rmotion](Motion *a, Motion *b)
473 { return si_->distance(a->state, rmotion->state) < si_->distance(b->state, rmotion->state); });
474 }
475 // in goal tree sort by time of root node
476 else
477 {
478 std::sort(
479 nbh.begin(), nbh.end(),
480 [](Motion *a, Motion *b)
481 {
482 auto t1 =
483 a->root->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
484 auto t2 =
485 b->root->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
486 return t1 < t2;
487 });
488 }
489
490 // attempt to grow the tree for all neighbors in sorted order
491 GrowState gs = TRAPPED;
492 auto rt = rmotion->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
493 for (Motion *nmotion : nbh)
494 {
495 auto nt =
497 // trees grow only in one direction in time
498 if ((tgi.start && nt > rt) || (!tgi.start && nt < rt))
499 continue;
500 gs = growTreeSingle(tree, tgi, rmotion, nmotion);
501 if (gs != TRAPPED)
502 return gs;
503 }
504 // when radius_ is used for neighborhood calculation, the neighborhood might be empty
505 if (nbh.empty())
506 {
507 Motion *nmotion = tree->nearest(rmotion);
508 return growTreeSingle(tree, tgi, rmotion, nmotion);
509 }
510 // can't grow Tree
511 return gs;
512}
513
516 Motion *nmotion)
517{
518 /* assume we can reach the state we go towards */
519 bool reach = true;
520
521 /* find state to add */
522 ompl::base::State *dstate = rmotion->state;
523 double d = si_->distance(nmotion->state, rmotion->state);
524
525 if (d > maxDistance_)
526 {
527 si_->getStateSpace()->interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
528 /* Check if we have moved at all. Due to some stranger state spaces (e.g., the constrained state spaces),
529 * interpolate can fail and no progress is made. Without this check, the algorithm gets stuck in a loop as it
530 * thinks it is making progress, when none is actually occurring. */
531 if (si_->equalStates(nmotion->state, tgi.xstate))
532 return TRAPPED;
533 dstate = tgi.xstate;
534 reach = false;
535 }
536
537 bool validMotion = tgi.start ? si_->checkMotion(nmotion->state, dstate) :
538 si_->isValid(dstate) && si_->checkMotion(dstate, nmotion->state);
539
540 if (!validMotion)
541 return TRAPPED;
542
543 auto *motion = new Motion(si_);
544 si_->copyState(motion->state, dstate);
545 motion->parent = nmotion;
546 motion->root = nmotion->root;
547 motion->parent->children.push_back(motion);
548 tree->add(motion);
549 tgi.xmotion = motion;
550
551 return reach ? REACHED : ADVANCED;
552}
553
554void ompl::geometric::STRRTstar::increaseTimeBound(bool hasSameBounds, double &oldBatchTimeBoundFactor,
555 double &newBatchTimeBoundFactor, bool &startTree,
556 unsigned int &batchSize, int &numBatchSamples)
557{
558 oldBatchTimeBoundFactor =
559 hasSameBounds ? newBatchTimeBoundFactor * timeBoundFactorIncrease_ : newBatchTimeBoundFactor;
560 newBatchTimeBoundFactor *= timeBoundFactorIncrease_;
561 startTree = true;
562 if (sampleUniformForUnboundedTime_)
563 batchSize =
564 std::ceil(2.0 * (timeBoundFactorIncrease_ - 1.0) * static_cast<double>(tStart_->size() + tGoal_->size()));
565 numBatchSamples = 0;
566 OMPL_INFORM("%s: Increased time bound factor to %.2f", getName().c_str(), newBatchTimeBoundFactor);
567}
568
569void ompl::geometric::STRRTstar::constructSolution(
570 Motion *startMotion, Motion *goalMotion,
571 const ompl::base::ReportIntermediateSolutionFn &intermediateSolutionCallback,
573{
574 if (goalMotion->connectionPoint == nullptr)
575 {
576 goalMotion->connectionPoint = startMotion;
577 Motion *tMotion = goalMotion;
578 while (tMotion != nullptr)
579 {
580 tMotion->numConnections++;
581 tMotion = tMotion->parent;
582 }
583 }
584 // check whether the found solution is an improvement
585 auto newTime =
586 goalMotion->root->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
587 if (newTime >= upperTimeBound_)
588 return;
589
590 numSolutions_++;
591 isTimeBounded_ = true;
592 if (!newBatchGoalMotions_.empty())
593 {
594 goalMotions_.insert(goalMotions_.end(), newBatchGoalMotions_.begin(), newBatchGoalMotions_.end());
595 newBatchGoalMotions_.clear();
596 }
597
598 /* construct the solution path */
599 Motion *solution = startMotion;
600 std::vector<Motion *> mpath1;
601 while (solution != nullptr)
602 {
603 mpath1.push_back(solution);
604 solution = solution->parent;
605 }
606
607 solution = goalMotion;
608 std::vector<Motion *> mpath2;
609 while (solution != nullptr)
610 {
611 mpath2.push_back(solution);
612 solution = solution->parent;
613 }
614
615 std::vector<const ompl::base::State *> constPath;
616
617 auto path(std::make_shared<ompl::geometric::PathGeometric>(si_));
618 path->getStates().reserve(mpath1.size() + mpath2.size());
619 for (int i = mpath1.size() - 1; i >= 0; --i)
620 {
621 constPath.push_back(mpath1[i]->state);
622 path->append(mpath1[i]->state);
623 }
624 for (auto &i : mpath2)
625 {
626 constPath.push_back(i->state);
627 path->append(i->state);
628 }
629
630 bestSolution_ = path;
631 auto reachedGaol = path->getState(path->getStateCount() - 1);
632 bestTime_ = reachedGaol->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
633
634 if (intermediateSolutionCallback)
635 {
636 intermediateSolutionCallback(this, constPath, ompl::base::Cost(bestTime_));
637 }
638
639 // Update Time Limit
640 upperTimeBound_ = (bestTime_ - minimumTime_) * optimumApproxFactor_ + minimumTime_;
641
642 if (ptc)
643 return;
644 // Prune Start and Goal Trees
645 pruneStartTree();
646 Motion *newSolution = pruneGoalTree();
647
648 // loop as long as a new solution is found by rewiring the goal tree
649 if (newSolution != nullptr)
650 constructSolution(newSolution->connectionPoint, goalMotion, intermediateSolutionCallback, ptc);
651}
652
654{
655 std::queue<Motion *> queue;
656
657 tStart_->clear();
658 tStart_->add(startMotion_);
659 for (auto &c : startMotion_->children)
660 queue.push(c);
661 while (!queue.empty())
662 {
663 double t = queue.front()
664 ->state->as<ompl::base::CompoundState>()
666 ->position;
667 double timeToNearestGoal = std::numeric_limits<double>::infinity();
668 for (const auto &g : goalMotions_)
669 {
670 double deltaT = si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->timeToCoverDistance(
671 queue.front()->state, g->state);
672 if (deltaT < timeToNearestGoal)
673 timeToNearestGoal = deltaT;
674 }
675 // Motion is still valid, re-add to tree
676 if (t + timeToNearestGoal <= upperTimeBound_)
677 {
678 tStart_->add(queue.front());
679 for (auto &c : queue.front()->children)
680 queue.push(c);
681 }
682 // Motion is invalid due to the new time limit, delete motion
683 else
684 {
685 // Remove the motion from its parent
686 removeFromParent(queue.front());
687
688 // for deletion first construct list of all descendants
689 std::queue<Motion *> deletionQueue;
690 std::vector<Motion *> deletionList;
691
692 deletionQueue.push(queue.front());
693 while (!deletionQueue.empty())
694 {
695 for (auto &c : deletionQueue.front()->children)
696 deletionQueue.push(c);
697 deletionList.push_back(deletionQueue.front());
698 deletionQueue.pop();
699 }
700
701 // then free all descendants
702 for (auto &m : deletionList)
703 {
704 // Erase the actual motion
705 // First free the state
706 if (m->state)
707 si_->freeState(m->state);
708 // then delete the pointer
709 delete m;
710 }
711 }
712 // finally remove motion from the queue
713 queue.pop();
714 }
715}
716
718{
719 // it's possible to get multiple new solutions during the rewiring process. Store the best.
720 double bestSolutionTime = upperTimeBound_;
721 Motion *solutionMotion{nullptr};
722
723 tGoal_->clear();
724 std::vector<Motion *> validGoals;
725 std::vector<Motion *> invalidGoals;
726
727 // re-add goals with smallest time first
728 std::sort(
729 goalMotions_.begin(), goalMotions_.end(),
730 [](Motion *a, Motion *b)
731 {
732 return a->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position <
733 b->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
734 });
735 for (auto &m : goalMotions_)
736 {
737 double t = m->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
738 // add goal with all descendants to the tree
739 if (t <= upperTimeBound_)
740 {
741 tGoal_->add(m);
743 validGoals.push_back(m);
744 }
745 // try to rewire descendants to a valid goal
746 else
747 {
748 invalidGoals.push_back(m);
749 std::queue<Motion *> queue;
750 for (auto &c : m->children)
751 queue.push(c);
752 while (!queue.empty())
753 {
754 bool addedToTree = false;
755 if (tGoal_->size() != 0)
756 {
757 double costToGo = std::numeric_limits<double>::infinity();
758 double costSoFar = queue.front()
759 ->state->as<ompl::base::CompoundState>()
761 ->position;
762 for (auto &g : validGoals)
763 {
764 auto deltaT = si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->timeToCoverDistance(
765 queue.front()->state, g->state);
766 if (deltaT < costToGo)
767 costToGo = deltaT;
768 }
769 // try to rewire to the nearest neighbor
770
771 if (costSoFar + costToGo <= upperTimeBound_)
772 {
773 TreeGrowingInfo tgi{};
774 // Use ScopedState to ensure automatic cleanup even if exceptions are thrown
775 ompl::base::ScopedState<> xstateScoped(si_);
776 tgi.xstate = xstateScoped.get();
777 tgi.start = false;
778 std::vector<Motion *> nbh;
779 GrowState gsc = growTree(tGoal_, tgi, queue.front(), nbh, true);
780 // connection successful, add all descendants and check if a new solution was found.
781 if (gsc == REACHED)
782 {
783 // the motion was copied and added to the tree with a new parent
784 // adjust children and parent pointers
785 tgi.xmotion->children = queue.front()->children;
786 for (auto &c : tgi.xmotion->children)
787 {
788 c->parent = tgi.xmotion;
789 }
790 tgi.xmotion->connectionPoint = queue.front()->connectionPoint;
791 tgi.xmotion->numConnections = queue.front()->numConnections;
792 Motion *p = tgi.xmotion->parent;
793 while (p != nullptr)
794 {
795 p->numConnections += tgi.xmotion->numConnections;
796 p = p->parent;
797 }
798 addDescendants(tgi.xmotion, tGoal_);
799 // new solution found
800 if (tgi.xmotion->numConnections > 0 &&
801 tgi.xmotion->root->as<ompl::base::CompoundState>()
803 ->position < bestSolutionTime)
804 {
805 bestSolutionTime = tgi.xmotion->root->as<ompl::base::CompoundState>()
807 ->position;
808 solutionMotion = computeSolutionMotion(tgi.xmotion);
809 }
810 addedToTree = true;
811 }
812 }
813 }
814 // Free motion and state
815 if (!addedToTree)
816 {
817 // add children to queue, so they might be rewired
818 for (auto &c : queue.front()->children)
819 queue.push(c);
820 }
821 // Erase the actual motion
822 // First free the state
823 if (queue.front()->state)
824 si_->freeState(queue.front()->state);
825 // then delete the pointer
826 delete queue.front();
827
828 queue.pop();
829 }
830 }
831 }
832
833 removeInvalidGoals(invalidGoals);
834 return solutionMotion;
835}
836
838{
839 std::queue<Motion *> connectionQueue;
840 connectionQueue.push(motion);
841 while (!connectionQueue.empty())
842 {
843 if (connectionQueue.front()->connectionPoint != nullptr)
844 {
845 return connectionQueue.front();
846 }
847 else
848 {
849 for (Motion *c : connectionQueue.front()->children)
850 connectionQueue.push(c);
851 }
852 connectionQueue.pop();
853 }
854 // suppress compiler warning
855 return nullptr;
856}
857
858void ompl::geometric::STRRTstar::removeInvalidGoals(const std::vector<Motion *> &invalidGoals)
859{
860 for (auto &g : invalidGoals)
861 {
862 for (auto it = goalMotions_.begin(); it != goalMotions_.end(); ++it)
863 {
864 if (*it == g)
865 {
866 goalMotions_.erase(it);
867 break;
868 }
869 }
870 if (g->state)
871 si_->freeState(g->state);
872 delete g;
873 }
874}
875
877{
878 setup_ = false;
879 Planner::clear();
880 freeMemory();
881 if (tStart_)
882 tStart_->clear();
883 if (tGoal_)
884 tGoal_->clear();
885 distanceBetweenTrees_ = std::numeric_limits<double>::infinity();
886 bestSolution_ = nullptr;
887 bestTime_ = std::numeric_limits<double>::infinity();
888 minimumTime_ = std::numeric_limits<double>::infinity();
889 numIterations_ = 0;
890 numSolutions_ = 0;
891 startMotion_ = nullptr;
892 goalMotions_.clear();
893 newBatchGoalMotions_.clear();
894 tempState_ = nullptr;
895 sampleOldBatch_ = true;
897 isTimeBounded_ = initialTimeBound_ != std::numeric_limits<double>::infinity();
898}
899
901{
902 Planner::getPlannerData(data);
903
904 std::vector<Motion *> motions;
905 if (tStart_)
906 tStart_->list(motions);
907
908 for (auto &motion : motions)
909 {
910 if (motion->parent == nullptr)
911 data.addStartVertex(ompl::base::PlannerDataVertex(motion->state, 1));
912 else
913 {
914 data.addEdge(ompl::base::PlannerDataVertex(motion->parent->state, 1),
915 ompl::base::PlannerDataVertex(motion->state, 1));
916 }
917 }
918
919 motions.clear();
920 if (tGoal_)
921 tGoal_->list(motions);
922
923 for (auto &motion : motions)
924 {
925 if (motion->parent == nullptr)
926 data.addGoalVertex(ompl::base::PlannerDataVertex(motion->state, 2));
927 else
928 {
929 // The edges in the goal tree are reversed to be consistent with start tree
930 data.addEdge(ompl::base::PlannerDataVertex(motion->state, 2),
931 ompl::base::PlannerDataVertex(motion->parent->state, 2));
932 }
933 // add edges connecting the two trees
934 if (motion->connectionPoint != nullptr)
935 data.addEdge(data.vertexIndex(motion->connectionPoint->state), data.vertexIndex(motion->state));
936 }
937
938 // Add some info.
939 data.properties["approx goal distance REAL"] = ompl::toString(distanceBetweenTrees_);
940}
941
943{
944 for (auto it = m->parent->children.begin(); it != m->parent->children.end(); ++it)
945 {
946 if (*it == m)
947 {
948 m->parent->children.erase(it);
949 break;
950 }
951 }
952}
953
962{
963 std::queue<Motion *> queue;
964 for (auto &c : m->children)
965 queue.push(c);
966 while (!queue.empty())
967 {
968 for (auto &c : queue.front()->children)
969 queue.push(c);
970 queue.front()->root = m->root;
971 tree->add(queue.front());
972 queue.pop();
973 }
974}
975
977 std::vector<Motion *> &nbh) const
978{
979 auto card = static_cast<double>(tree->size() + 1u);
980 if (rewireState_ == RADIUS)
981 {
982 // r = min( r_rrt * (log(card(V))/card(V))^(1 / d + 1), distance)
983 // for the formula change of the RRTStar paper, see 'Revisiting the asymptotic optimality of RRT*'
984 double r = std::min(maxDistance_, r_rrt_ * std::pow(log(card) / card,
985 1.0 / 1.0 + static_cast<double>(si_->getStateDimension())));
986 tree->nearestR(motion, r, nbh);
987 }
988 else if (rewireState_ == KNEAREST)
989 {
990 // k = k_rrt * log(card(V))
991 unsigned int k = std::ceil(k_rrt_ * log(card));
992 tree->nearestK(motion, k, nbh);
993 }
994}
995
996bool ompl::geometric::STRRTstar::rewireGoalTree(Motion *addedMotion)
997{
998 bool solved = false;
999 std::vector<Motion *> nbh;
1000 getNeighbors(tGoal_, addedMotion, nbh);
1001 double nodeT =
1002 addedMotion->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
1003 double goalT =
1004 addedMotion->root->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
1005
1006 for (Motion *otherMotion : nbh)
1007 {
1008 double otherNodeT =
1009 otherMotion->state->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
1010 double otherGoalT =
1011 otherMotion->root->as<ompl::base::CompoundState>()->as<ompl::base::TimeStateSpace::StateType>(1)->position;
1012 // rewire, if goal time is improved and the otherMotion node can be connected to the added node
1013 if (otherNodeT < nodeT && goalT < otherGoalT && si_->checkMotion(otherMotion->state, addedMotion->state))
1014 {
1015 if (otherMotion->numConnections > 0)
1016 {
1017 Motion *p = otherMotion->parent;
1018 while (p != nullptr)
1019 {
1020 p->numConnections--;
1021 p = p->parent;
1022 }
1023 }
1024 removeFromParent(otherMotion);
1025 otherMotion->parent = addedMotion;
1026 otherMotion->root = addedMotion->root;
1027 addedMotion->children.push_back(otherMotion);
1028 // increase connection count of new ancestors
1029 if (otherMotion->numConnections > 0)
1030 {
1031 Motion *p = otherMotion->parent;
1032 while (p != nullptr)
1033 {
1034 p->numConnections++;
1035 p = p->parent;
1036 }
1037 if (otherMotion->root->as<ompl::base::CompoundState>()
1039 ->position < upperTimeBound_)
1040 {
1041 solved = true;
1042 }
1043 }
1044 }
1045 }
1046
1047 return solved;
1048}
1049
1051{
1052 const auto dim = static_cast<double>(si_->getStateDimension());
1053
1054 // r_rrt > (2*(1+1/d))^(1/d)*(measure/ballvolume)^(1/d)
1055 // prunedMeasure_ is set to si_->getSpaceMeasure();
1056 r_rrt_ = rewireFactor_ * std::pow(2 * (1.0 + 1.0 / dim) *
1057 (si_->getSpaceMeasure() / ompl::unitNBallMeasure(si_->getStateDimension())),
1058 1.0 / dim);
1059
1060 // k_rrg > e * (1 + 1 / d). K-nearest RRT*
1061 k_rrt_ = rewireFactor_ * boost::math::constants::e<double>() * (1.0 + 1.0 / dim);
1062}
1063
1064bool ompl::geometric::STRRTstar::sampleGoalTime(ompl::base::State *goal, double oldBatchTimeBoundFactor,
1065 double newBatchTimeBoundFactor)
1066{
1067 double ltb, utb;
1068 double startTime = si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->getStateTime(startMotion_->state);
1069 double minTimeToGoal =
1070 si_->getStateSpace()->as<ompl::base::SpaceTimeStateSpace>()->timeToCoverDistance(startMotion_->state, goal);
1071 double minTime = startTime + minTimeToGoal;
1072
1073 if (isTimeBounded_)
1074 {
1075 ltb = minTime;
1076 utb = upperTimeBound_;
1077 }
1078 else if (sampleOldBatch_)
1079 {
1080 ltb = minTime;
1081 utb = minTime * oldBatchTimeBoundFactor;
1082 }
1083 else
1084 {
1085 ltb = minTime * oldBatchTimeBoundFactor;
1086 utb = minTime * newBatchTimeBoundFactor;
1087 }
1088
1089 if (ltb > utb)
1090 return false; // goal can't be reached in time
1091
1092 double time = ltb == utb ? ltb : rng_.uniformReal(ltb, utb);
1094 return true;
1095}
1096
1097ompl::base::State *ompl::geometric::STRRTstar::nextGoal(int n, double oldBatchTimeBoundFactor,
1098 double newBatchTimeBoundFactor)
1099{
1101 return nextGoal(ptc, n, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
1102}
1103
1105 double oldBatchTimeBoundFactor, double newBatchTimeBoundFactor)
1106{
1107 return nextGoal(ptc, -1, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
1108}
1109
1111 double oldBatchTimeBoundFactor, double newBatchTimeBoundFactor)
1112{
1113 if (pdef_->getGoal() != nullptr)
1114 {
1116 pdef_->getGoal()->as<ompl::base::GoalSampleableRegion>() :
1117 nullptr;
1118
1119 if (goal != nullptr)
1120 {
1121 if (tempState_ == nullptr)
1122 tempState_ = si_->allocState();
1123 int tryCount = 0;
1124 do
1125 {
1126 goal->sampleGoal(tempState_); // sample space component
1127 // sample time component dependant on sampled space
1128 bool inTime = sampleGoalTime(tempState_, oldBatchTimeBoundFactor, newBatchTimeBoundFactor);
1129 bool bounds = inTime && si_->satisfiesBounds(tempState_);
1130 bool valid = bounds && si_->isValid(tempState_);
1131 if (valid)
1132 {
1133 return tempState_;
1134 }
1135 } while (!ptc.eval() && ++tryCount != n);
1136 }
1137 }
1138
1139 return nullptr;
1140}
1141
1143{
1144 maxDistance_ = distance;
1145}
1146
1148{
1149 return maxDistance_;
1150}
1151
1156
1158{
1159 if (optimumApproxFactor <= 0 || optimumApproxFactor > 1)
1160 {
1161 OMPL_ERROR("%s: The optimum approximation factor needs to be between 0 and 1.", getName().c_str());
1162 }
1163 optimumApproxFactor_ = optimumApproxFactor;
1164}
1165
1166std::string ompl::geometric::STRRTstar::getRewiringState() const
1167{
1168 std::vector<std::string> s{"Radius", "KNearest", "Off"};
1169 return s[rewireState_];
1170}
1171
1173{
1174 rewireState_ = OFF;
1175}
1176
1178{
1179 rewireState_ = RADIUS;
1180}
1181
1183{
1184 rewireState_ = KNEAREST;
1185}
1186
1187double ompl::geometric::STRRTstar::getRewireFactor() const
1188{
1189 return rewireFactor_;
1190}
1191
1192void ompl::geometric::STRRTstar::setRewireFactor(double v)
1193{
1194 if (v <= 1)
1195 {
1196 OMPL_ERROR("%s: Rewire Factor needs to be greater than 1.", getName().c_str());
1197 }
1198 rewireFactor_ = v;
1199}
1200
1202{
1203 return initialBatchSize_;
1204}
1205
1206void ompl::geometric::STRRTstar::setBatchSize(int v)
1207{
1208 if (v < 1)
1209 {
1210 OMPL_ERROR("%s: Batch Size needs to be at least 1.", getName().c_str());
1211 }
1212 initialBatchSize_ = v;
1213}
1214
1216{
1217 if (f <= 1.0)
1218 {
1219 OMPL_ERROR("%s: Time Bound Factor Increase needs to be higher than 1.", getName().c_str());
1220 }
1222}
1223
1225{
1226 if (f <= 1.0)
1227 {
1228 OMPL_ERROR("%s: Initial Time Bound Factor Increase needs to be higher than 1.", getName().c_str());
1229 }
1231}
1232
A nearest neighbors datastructure that uses linear search.
Definition of a compound state.
Definition State.h:87
const T * as(unsigned int index) const
Cast a component of this instance to a desired type.
Definition State.h:95
std::vector< Motion * > children
The set of motions descending from the current motion.
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition Cost.h:48
Abstract definition of a goal region that can be sampled.
virtual void sampleGoal(State *st) const =0
Sample a state in the goal region.
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition PlannerData.h:59
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique,...
unsigned int vertexIndex(const PlannerDataVertex &v) const
Return the index for the vertex associated with the given data. INVALID_INDEX is returned if this ver...
unsigned int addStartVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
unsigned int addGoalVertex(const PlannerDataVertex &v)
Adds the given vertex to the graph data, and marks it as a start vertex. The vertex index is returned...
virtual bool addEdge(unsigned int v1, unsigned int v2, const PlannerDataEdge &edge=PlannerDataEdge(), Cost weight=Cost(1.0))
Adds a directed edge between the given vertex indexes. An optional edge structure and weight can be s...
std::map< std::string, std::string > properties
Any extra properties (key-value pairs) the planner can set.
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
bool eval() const
The implementation of some termination condition. By default, this just calls fn_().
T * as()
Cast this instance to a desired type.
Definition Planner.h:230
PlannerInputStates pis_
Utility class to extract valid input states.
Definition Planner.h:407
PlannerSpecs specs_
The specifications of the planner (its capabilities).
Definition Planner.h:413
ProblemDefinitionPtr pdef_
The user set problem definition.
Definition Planner.h:404
const std::string & getName() const
Get the name of the planner.
Definition Planner.cpp:56
SpaceInformationPtr si_
The space information for which planning is done.
Definition Planner.h:401
virtual void checkValidity()
Check to see if the planner is in a working state (setup has been called, a goal was set,...
Definition Planner.cpp:106
bool setup_
Flag indicating whether setup() has been called.
Definition Planner.h:424
Definition of a scoped state.
Definition ScopedState.h:57
StateType * get()
Returns a pointer to the contained state.
A state space consisting of a space and a time component.
TimeStateSpace * getTimeComponent()
The time component as a TimeStateSpace pointer.
double timeToCoverDistance(const ompl::base::State *state1, const ompl::base::State *state2) const
The time to get from state1 to state2 with respect to vMax.
ompl::base::State StateType
Define the type of state allocated by this space.
Definition StateSpace.h:78
Definition of an abstract state.
Definition State.h:50
const T * as() const
Cast this instance to a desired type.
Definition State.h:66
The definition of a time state.
double position
The position in time.
bool isBounded() const
Check if the time is bounded or not.
TreeData tGoal_
The goal tree.
Definition STRRTstar.h:201
double k_rrt_
A constant for k-nearest rewiring calculations.
Definition STRRTstar.h:291
GrowState growTreeSingle(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion, Motion *nmotion)
Grow a tree towards a random state for a single nearest state.
void setOptimumApproxFactor(double optimumApproxFactor)
Set the Optimum Approximation factor. This allows the planner to converge more quickly,...
unsigned int initialBatchSize_
Number of samples of the first batch.
Definition STRRTstar.h:308
void freeMemory()
Free the memory allocated by this planner.
Definition STRRTstar.cpp:91
double bestTime_
The current best time i.e. cost of all found solutions.
Definition STRRTstar.h:213
base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc) override
Function that can solve the motion planning problem. This function can be called multiple times on th...
TreeData tStart_
The start tree.
Definition STRRTstar.h:198
GrowState
The state of the tree after an attempt to extend it.
Definition STRRTstar.h:143
@ ADVANCED
progress has been made towards the randomly sampled state
Definition STRRTstar.h:147
@ TRAPPED
no progress has been made
Definition STRRTstar.h:145
@ REACHED
the randomly sampled state was reached
Definition STRRTstar.h:149
void calculateRewiringLowerBounds()
Calculate the k_RRG* and r_RRG* terms.
void setSampleUniformForUnboundedTime(bool uniform)
Whether the state space is sampled uniformly or centered at lower time values.
double r_rrt_
A constant for r-disc rewiring calculations.
Definition STRRTstar.h:294
int goalStateSampleRatio_
The ratio, a goal state is sampled compared to the size of the goal tree.
Definition STRRTstar.h:324
double getOptimumApproxFactor() const
The Optimum Approximation factor (0 - 1).
unsigned int numIterations_
The number of while loop iterations.
Definition STRRTstar.h:216
Motion * startMotion_
The start Motion, used for conditional sampling and start tree pruning.
Definition STRRTstar.h:231
double upperTimeBound_
Upper bound for the time up to which solutions are searched for.
Definition STRRTstar.h:225
static void addDescendants(Motion *m, const TreeData &tree)
Adds given all descendants of the given motion to given tree and checks whether one of the added moti...
std::vector< Motion * > newBatchGoalMotions_
The goal Motions, that were added in the current expansion step, used for uniform sampling over a gro...
Definition STRRTstar.h:238
double optimumApproxFactor_
The factor to which found solution times need to be reduced compared to minimum time,...
Definition STRRTstar.h:228
double rewireFactor_
The rewiring factor, s, so that r_rrt = s \times r_rrt* > r_rrt* (or k_rrt = s \times k_rrt* > k_rrt*...
Definition STRRTstar.h:288
double timeBoundFactorIncrease_
The factor, the time bound is increased with after the batch is full.
Definition STRRTstar.h:315
bool sampleUniformForUnboundedTime_
Whether the samples are uniformly distributed over the whole space or are centered at lower times.
Definition STRRTstar.h:321
double getRange() const
Get the range the planner is using.
void getNeighbors(TreeData &tree, Motion *motion, std::vector< Motion * > &nbh) const
Gets the neighbours of a given motion, using either k-nearest or radius_ as appropriate.
void setTimeBoundFactorIncrease(double f)
The value by which the time bound factor is multiplied in each increase step.
double distanceBetweenTrees_
Distance between the nearest pair of start tree and goal tree nodes.
Definition STRRTstar.h:207
void setInitialTimeBoundFactor(double f)
The initial time bound factor.
base::PathPtr bestSolution_
The current best solution path with respect to shortest time.
Definition STRRTstar.h:210
double maxDistance_
The maximum length of a motion to be added to a tree.
Definition STRRTstar.h:204
void pruneStartTree()
Prune the start tree after a solution was found.
void clear() override
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
int numSolutions_
The number of found solutions.
Definition STRRTstar.h:219
void getPlannerData(base::PlannerData &data) const override
Get information about the current run of the motion planner. Repeated calls to this function will upd...
std::shared_ptr< ompl::NearestNeighbors< Motion * > > TreeData
A nearest-neighbor datastructure representing a tree of motions.
Definition STRRTstar.h:130
GrowState growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion, std::vector< Motion * > &nbh, bool connect)
Attempt to grow a tree towards a random state for the neighborhood of the random state....
STRRTstar(const ompl::base::SpaceInformationPtr &si)
Constructor.
Definition STRRTstar.cpp:41
static void removeFromParent(Motion *m)
Removes the given motion from the parent's child list.
void setup() override
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
Definition STRRTstar.cpp:60
double distanceFunction(const Motion *a, const Motion *b) const
Compute distance between motions (actually distance between contained states).
Definition STRRTstar.h:175
void setRewiringToOff()
Do not rewire at all.
bool sampleGoalTime(base::State *goal, double oldBatchTimeBoundFactor, double newBatchTimeBoundFactor)
Samples the time component of a goal state dependant on its space component. Returns false,...
ompl::RNG rng_
The random number generator.
Definition STRRTstar.h:327
void removeInvalidGoals(const std::vector< Motion * > &invalidGoals)
Remove invalid goal states from the goal set.
base::State * nextGoal(int n, double oldBatchTimeBoundFactor, double newBatchTimeBoundFactor)
N tries to sample a goal.
base::ConditionalStateSampler sampler_
State sampler.
Definition STRRTstar.h:195
double initialTimeBoundFactor_
Initial factor, the minimum time of each goal is multiplied with to calculate the upper time bound.
Definition STRRTstar.h:312
double minimumTime_
Minimum Time at which any goal can be reached, if moving on a straight line.
Definition STRRTstar.h:222
void setRewiringToRadius()
Rewire by radius.
void setRewiringToKNearest()
Rewire by k-nearest.
std::vector< Motion * > goalMotions_
The goal Motions, used for conditional sampling and pruning.
Definition STRRTstar.h:234
bool isTimeBounded_
Whether the time is bounded or not. The first solution automatically bounds the time.
Definition STRRTstar.h:302
static Motion * computeSolutionMotion(Motion *motion)
Find the solution (connecting) motion for a motion that is indirectly connected.
void setRange(double distance)
Set the range the planner is supposed to use.
unsigned int getBatchSize() const
The number of samples before the time bound is increased.
double initialTimeBound_
The time bound the planner is initialized with. Used to reset for repeated planning.
Definition STRRTstar.h:305
Motion * pruneGoalTree()
Prune the goal tree after a solution was found. Return the goal motion, that is connected to the star...
This class contains methods that automatically configure various parameters for motion planning....
Definition SelfConfig.h:59
void configurePlannerRange(double &range)
Compute what a good length for motion segments is.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition Console.h:68
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition Console.h:64
@ GOAL_SAMPLEABLE_REGION
This bit is set if casting to sampleable goal regions (ompl::base::GoalSampleableRegion) is possible.
Definition GoalTypes.h:56
PlannerTerminationCondition plannerNonTerminatingCondition()
Simple termination condition that always returns false. The termination condition will never be met.
std::function< void(const Planner *, const std::vector< const base::State * > &, const Cost)> ReportIntermediateSolutionFn
When a planner has an intermediate solution (e.g., optimizing planners), a function with this signatu...
Namespace containing time datatypes and time operations.
Definition Time.h:50
std::string toString(float val)
convert float to string using classic "C" locale semantics
Definition String.cpp:82
double unitNBallMeasure(unsigned int N)
The Lebesgue measure (i.e., "volume") of an n-dimensional ball with a unit radius.
Representation of a solution to a planning problem.
void setPlannerName(const std::string &name)
Set the name of the planner used to compute this solution.
void setOptimized(const OptimizationObjectivePtr &opt, Cost cost, bool meetsObjective)
Set the optimization objective used to optimize this solution, the cost of the solution and whether i...
A class to store the exit status of Planner::solve().
@ INVALID_START
Invalid start state or no start state specified.
@ EXACT_SOLUTION
The planner found an exact solution.
@ INVALID_GOAL
Invalid goal state.
@ UNRECOGNIZED_GOAL_TYPE
The goal is of a type that a planner does not recognize.
@ APPROXIMATE_SOLUTION
The planner found an approximate solution.
@ TIMEOUT
The planner failed to find a solution.
Information attached to growing a tree of motions (used internally).
Definition STRRTstar.h:135