38 #include "ompl/geometric/planners/xxl/XXL.h"
39 #include "ompl/base/goals/GoalSampleableRegion.h"
40 #include "ompl/base/goals/GoalLazySamples.h"
41 #include "ompl/tools/config/MagicConstants.h"
42 #include "ompl/tools/config/SelfConfig.h"
43 #include "ompl/util/Exception.h"
47 xstate_ =
si_->allocState();
48 Planner::declareParam<double>(
"rand_walk_rate",
this, &XXL::setRandWalkRate, &XXL::getRandWalkRate,
"0.:.05:1.");
52 : base::Planner(si,
"XXL")
54 xstate_ =
si_->allocState();
55 setDecomposition(decomp);
56 Planner::declareParam<double>(
"rand_walk_rate",
this, &XXL::setRandWalkRate, &XXL::getRandWalkRate,
"0.:.05:1.");
59 ompl::geometric::XXL::~XXL()
62 si_->freeState(xstate_);
77 new Layer(-1, decomposition_->getNumRegions(), 0,
nullptr);
78 allocateLayers(topLayer_);
82 startMotions_.clear();
89 statesConnectedInRealGraph_ = 0;
93 void ompl::geometric::XXL::freeMemory()
95 for (
auto &motion : motions_)
97 si_->freeState(motion->state);
113 OMPL_ERROR(
"%s: Decomposition is not set. Cannot continue setup.", getName().c_str());
119 sampler_ = si_->allocStateSampler();
121 statesConnectedInRealGraph_ = 0;
123 maxGoalStatesPerRegion_ = 100;
124 maxGoalStates_ = 500;
131 topLayer_ =
new Layer(-1, decomposition_->getNumRegions(), 0,
nullptr);
132 allocateLayers(topLayer_);
134 if (rand_walk_rate_ < 0.0 || rand_walk_rate_ > 1.0)
136 rand_walk_rate_ = 0.05;
142 decomposition_ = decomp;
143 predecessors_.resize(decomposition_->getNumRegions());
144 closedList_.resize(decomposition_->getNumRegions());
146 if (decomposition_->numLayers() < 1)
147 throw ompl::Exception(
"Decomposition must have at least one layer of projection");
151 void ompl::geometric::XXL::allocateLayers(Layer *layer)
156 if (layer->getLevel() < decomposition_->numLayers() - 1)
158 layer->allocateSublayers();
159 if (layer->getLevel() + 1 < decomposition_->numLayers() - 1)
160 for (
size_t i = 0; i < layer->numRegions(); ++i)
161 allocateLayers(layer->getSublayer(i));
165 void ompl::geometric::XXL::updateRegionConnectivity(
const Motion *m1,
const Motion *m2,
int layer)
167 if (layer >= decomposition_->numLayers() || layer < 0)
174 std::vector<base::State *> intermediateStates;
175 std::vector<std::vector<int>> intProjections;
177 for (
int i = layer; i < decomposition_->numLayers(); ++i)
179 if (m1->levels[i] != m2->levels[i])
181 std::vector<int> nbrs;
182 decomposition_->getNeighborhood(m1->levels[i], nbrs);
183 bool isNeighbor =
false;
184 for (
size_t j = 0; j < nbrs.size() && !isNeighbor; ++j)
185 isNeighbor = nbrs[j] == m2->levels[i];
190 while (t < (1.0 - dt / 2.0))
192 std::vector<int> projection;
193 ss->interpolate(m1->state, m2->state, t, xstate_);
194 decomposition_->project(xstate_, projection);
196 intermediateStates.push_back(si_->cloneState(xstate_));
197 intProjections.push_back(projection);
206 if (intermediateStates.size())
208 std::vector<int> gaps;
211 for (
size_t i = 1; i < intProjections.size(); ++i)
213 for (
int j = layer; j < (int)intProjections[i].size(); ++j)
215 if (intProjections[i - 1][j] != intProjections[i][j])
217 std::vector<int> nbrs;
218 decomposition_->getNeighborhood(intProjections[i - 1][j], nbrs);
219 bool isNeighbor =
false;
220 for (
size_t k = 0; k < nbrs.size() && !isNeighbor; ++k)
221 isNeighbor = nbrs[k] == intProjections[i][j];
225 gaps.push_back((
int)i);
232 std::vector<std::vector<base::State *>> gapStates;
233 std::vector<std::vector<std::vector<int>>> gapProjections;
235 for (
size_t i = 0; i < gaps.size(); ++i)
237 std::vector<base::State *> gapState;
238 std::vector<std::vector<int>> gapProj;
240 double t = (gaps[i]) * dt;
242 double newdt = dt * dt;
245 std::vector<int> projection;
246 ss->interpolate(m1->state, m2->state, t, xstate_);
247 decomposition_->project(xstate_, projection);
249 gapState.push_back(si_->cloneState(xstate_));
250 gapProj.push_back(projection);
254 gapStates.push_back(gapState);
255 gapProjections.push_back(gapProj);
260 for (
size_t i = 0; i < gaps.size(); ++i)
262 auto start = intermediateStates.begin() + gaps[i] + offset;
263 intermediateStates.insert(start, gapStates[i].begin(), gapStates[i].end());
265 auto startproj = intProjections.begin() + gaps[i] + offset;
266 intProjections.insert(startproj, gapProjections[i].begin(), gapProjections[i].end());
268 offset += gapStates[i].size();
273 const Motion *prev = m1;
274 for (
size_t i = 0; i < intermediateStates.size(); ++i)
276 for (
int j = layer; j < decomposition_->numLayers(); ++j)
278 if (prev->levels[j] != intProjections[i][j])
281 int id = addState(intermediateStates[i]);
282 const Motion *newMotion = motions_[id];
285 Layer *l = topLayer_;
286 for (
size_t k = 0; k < newMotion->levels.size(); ++k)
288 l->getRegion(newMotion->levels[k]).motionsInTree.push_back(newMotion->index);
289 if (l->hasSublayers())
290 l = l->getSublayer(newMotion->levels[k]);
294 lazyGraph_.removeEdge(prev->index, newMotion->index);
295 double weight = si_->distance(prev->state, newMotion->state);
296 realGraph_.addEdge(prev->index, newMotion->index, weight);
297 if (realGraph_.numNeighbors(prev->index) == 1)
298 statesConnectedInRealGraph_++;
299 if (realGraph_.numNeighbors(newMotion->index) == 1)
300 statesConnectedInRealGraph_++;
302 Layer *l1 = getLayer(prev->levels, j);
303 Layer *l2 = getLayer(newMotion->levels, j);
305 l1->getRegionGraph().addEdge(prev->levels[j], newMotion->levels[j]);
307 l2->getRegionGraph().addEdge(prev->levels[j], newMotion->levels[j]);
317 if (layer >= decomposition_->numLayers())
320 Layer *l = topLayer_;
321 for (
int i = 0; i < layer; ++i)
322 l = l->getSublayer(regions[i]);
326 int ompl::geometric::XXL::addThisState(base::State *state)
328 auto motion =
new Motion();
329 motion->state = state;
330 decomposition_->project(motion->state, motion->levels);
333 motion->index = realGraph_.addVertex();
334 if (lazyGraph_.addVertex() != motion->index)
338 std::vector<int> nbrs;
339 decomposition_->getNeighbors(motion->levels[0], nbrs);
340 nbrs.push_back(motion->levels[0]);
341 for (
size_t i = 0; i < nbrs.size(); ++i)
343 const std::vector<int> &nbrMotions = topLayer_->getRegion(nbrs[i]).allMotions;
344 for (
size_t j = 0; j < nbrMotions.size(); ++j)
346 const Motion *nbrMotion = motions_[nbrMotions[j]];
347 double weight = si_->distance(motion->state, nbrMotion->state);
348 bool added = lazyGraph_.addEdge(motion->index, nbrMotion->index, weight);
350 throw std::runtime_error(
"Failed to add edge to graph");
355 motions_.push_back(motion);
356 assert(motion->index == motions_.size() - 1);
359 Layer *layer = topLayer_;
360 for (
size_t i = 0; i < motion->levels.size(); ++i)
362 layer->getRegion(motion->levels[i]).allMotions.push_back(motion->index);
363 if (layer->hasSublayers())
364 layer = layer->getSublayer(motion->levels[i]);
365 else if (i != motion->levels.size() - 1)
369 return motion->index;
372 int ompl::geometric::XXL::addState(
const base::State *state)
374 return addThisState(si_->cloneState(state));
377 int ompl::geometric::XXL::addGoalState(
const base::State *state)
379 std::vector<int> proj;
380 decomposition_->project(state, proj);
381 auto it = goalCount_.find(proj);
382 if (it != goalCount_.end() && it->second >= (
int)maxGoalStatesPerRegion_)
386 if (it != goalCount_.end())
389 goalCount_[proj] = 1;
392 int id = addState(state);
395 const Motion *motion = motions_[id];
396 goalMotions_.push_back(motion->index);
403 Layer *layer = topLayer_;
404 for (
size_t i = 0; i < motion->levels.size(); ++i)
406 layer->addGoalState(motion->levels[i],
id);
408 layer->getRegion(motion->levels[i]).motionsInTree.push_back(motion->index);
409 if (layer->hasSublayers())
410 layer = layer->getSublayer(motion->levels[i]);
411 else if (i != motion->levels.size() - 1)
415 return motion->index;
418 int ompl::geometric::XXL::addStartState(
const base::State *state)
420 int id = addState(state);
423 const Motion *motion = motions_[id];
424 startMotions_.push_back(motion->index);
428 Layer *layer = topLayer_;
429 for (
size_t i = 0; i < motion->levels.size(); ++i)
431 layer->getRegion(motion->levels[i]).motionsInTree.push_back(motion->index);
432 if (layer->hasSublayers())
433 layer = layer->getSublayer(motion->levels[i]);
436 return motion->index;
439 void ompl::geometric::XXL::updateRegionProperties(Layer *layer,
int reg)
448 const Region ®ion = layer->getRegion(reg);
449 double &weight = layer->getWeights()[reg];
451 int statesInRegion = (int)region.allMotions.size();
452 int statesInLayer = (layer->getLevel() == 0 ? (int)motions_.size() :
453 (int)layer->getParent()->getRegion(layer->getID()).allMotions.size());
454 double stateRatio = statesInRegion / (double)statesInLayer;
456 int connectedStatesInRegion = (int)region.motionsInTree.size();
458 double connStateRatio = (statesInRegion > 0 ? connectedStatesInRegion / (double)statesInRegion : 0.0);
459 double leadRatio = (layer->numLeads() ? layer->leadAppearances(reg) / (double)layer->numLeads() : 0.0);
461 double newWeight = (exp(-stateRatio) * exp(-10.0 * connStateRatio)) + (1.0 - exp(-leadRatio));
464 double nudgeFactor = 0.1;
465 weight += (newWeight - weight) * nudgeFactor;
468 weight = std::max(0.0, std::min(1.0, weight));
471 void ompl::geometric::XXL::updateRegionProperties(
const std::vector<int> ®ions)
473 Layer *layer = getLayer(regions, 0);
474 for (
size_t i = 0; i < regions.size(); ++i)
476 updateRegionProperties(layer, regions[i]);
478 if (layer->hasSublayers())
479 layer = layer->getSublayer(regions[i]);
480 else if (i != regions.size() - 1)
487 std::vector<int> newStates;
488 if (layer->getID() == -1)
493 sampler_->sampleUniform(xstate_);
494 if (si_->isValid(xstate_))
495 newStates.push_back(addState(xstate_));
500 const std::vector<int> &states = layer->getParent()->getRegion(layer->getID()).allMotions;
501 if (states.size() == 0)
502 throw ompl::Exception(
"Cannot sample states in a subregion where there are no states");
507 const Motion *seedMotion = motions_[states[rng_.uniformInt(0, states.size() - 1)]];
508 const base::State *seedState = seedMotion->state;
510 if (decomposition_->sampleFromRegion(layer->getID(), xstate_, seedState, layer->getLevel() - 1))
512 int idx = addState(xstate_);
513 newStates.push_back(idx);
519 for (
size_t i = 0; i < newStates.size(); ++i)
520 updateRegionProperties(motions_[newStates[i]]->levels);
523 bool ompl::geometric::XXL::sampleAlongLead(Layer *layer,
const std::vector<int> &lead,
527 int numSampleAttempts = 10;
528 std::vector<int> newStates;
530 if (lead.size() == 1)
532 std::vector<int> nbrs;
533 decomposition_->getNeighborhood(lead[0], nbrs);
534 nbrs.push_back(lead[0]);
535 for (
int j = 0; j < numSampleAttempts; ++j)
540 rng_.shuffle(nbrs.begin(), nbrs.end());
541 for (
size_t k = 0; k < nbrs.size() && !seed; ++k)
543 const Region &nbrReg = layer->getRegion(nbrs[k]);
544 if (nbrReg.allMotions.size() > 0)
545 seed = motions_[nbrReg.allMotions[rng_.uniformInt(0, nbrReg.allMotions.size() - 1)]]->state;
551 if (decomposition_->sampleFromRegion(lead[0], xstate_, seed, layer->getLevel()))
552 newStates.push_back(addState(xstate_));
558 int maxStateCount = 0;
559 for (
size_t i = 0; i < lead.size() && !ptc; ++i)
561 const Region ®ion = layer->getRegion(lead[i]);
562 if ((
int)region.allMotions.size() > maxStateCount)
563 maxStateCount = region.allMotions.size();
566 for (
size_t i = 0; i < lead.size() && !ptc; ++i)
568 const Region ®ion = layer->getRegion(lead[i]);
569 double p = 1.0 - (region.allMotions.size() / (double)maxStateCount);
570 if (rng_.uniform01() < p)
572 std::vector<int> nbrs;
573 decomposition_->getNeighborhood(lead[i], nbrs);
574 for (
int j = 0; j < numSampleAttempts; ++j)
580 rng_.shuffle(nbrs.begin(), nbrs.end());
581 for (
size_t k = 0; k < nbrs.size() && !seed; ++k)
583 const Region &nbrReg = layer->getRegion(nbrs[k]);
584 if (nbrReg.allMotions.size() > 0)
585 seed = motions_[nbrReg.allMotions[rng_.uniformInt(0, nbrReg.allMotions.size() - 1)]]
593 if (decomposition_->sampleFromRegion(lead[i], xstate_, seed, layer->getLevel()))
594 newStates.push_back(addState(xstate_));
601 for (
size_t i = 0; i < newStates.size(); ++i)
602 updateRegionProperties(motions_[newStates[i]]->levels);
603 for (
size_t i = 0; i < lead.size(); ++i)
604 updateRegionProperties(layer, lead[i]);
606 return newStates.size() > 0;
609 int ompl::geometric::XXL::steerToRegion(Layer *layer,
int from,
int to)
611 if (!decomposition_->canSteer())
612 throw ompl::Exception(
"steerToRegion not implemented in decomposition");
614 Region &fromRegion = layer->getRegion(from);
616 if (fromRegion.motionsInTree.size() == 0)
618 OMPL_DEBUG(
"%s: %d -> %d, Layer %d", __func__, from, to, layer->getLevel());
619 OMPL_WARN(
"XXL: Logic error: No existing states in the region to expand from");
624 int random = rng_.uniformInt(0, fromRegion.motionsInTree.size() - 1);
625 const Motion *fromMotion = motions_[fromRegion.motionsInTree[random]];
627 std::vector<base::State *> newStates;
629 if (decomposition_->steerToRegion(to, layer->getLevel(), fromMotion->state, newStates))
631 std::vector<int> newStateIDs(newStates.size());
633 for (
size_t i = 0; i < newStates.size(); ++i)
634 newStateIDs[i] = addThisState(newStates[i]);
637 int prev = fromMotion->index;
638 for (
size_t i = 0; i < newStateIDs.size(); ++i)
641 lazyGraph_.removeEdge(prev, newStateIDs[i]);
642 double weight = si_->distance(motions_[prev]->state, motions_[newStateIDs[i]]->state);
643 realGraph_.addEdge(prev, newStateIDs[i], weight);
646 Layer *l = topLayer_;
647 const Motion *newMotion = motions_[newStateIDs[i]];
648 for (
size_t j = 0; j < newMotion->levels.size(); ++j)
650 l->getRegion(newMotion->levels[j]).motionsInTree.push_back(newMotion->index);
651 if (l->hasSublayers())
652 l = l->getSublayer(newMotion->levels[j]);
656 if (i == 0 && realGraph_.numNeighbors(prev) == 0)
657 statesConnectedInRealGraph_++;
658 if (realGraph_.numNeighbors(newStateIDs[i]) == 0)
659 statesConnectedInRealGraph_++;
662 updateRegionConnectivity(motions_[prev], newMotion, layer->getLevel());
663 updateRegionProperties(newMotion->levels);
665 prev = newStateIDs[i];
668 return newStateIDs.back();
676 int ompl::geometric::XXL::expandToRegion(Layer *layer,
int from,
int to,
bool useExisting)
678 Region &fromRegion = layer->getRegion(from);
679 Region &toRegion = layer->getRegion(to);
681 if (fromRegion.motionsInTree.size() == 0)
683 OMPL_DEBUG(
"%s: %d -> %d, Layer %d", __func__, from, to, layer->getLevel());
684 OMPL_WARN(
"XXL: Logic error: No existing states in the region to expand from");
689 if (useExisting && toRegion.motionsInTree.size() == 0)
691 OMPL_ERROR(
"Logic error: useExisting is true but there are no existing states");
696 int random = rng_.uniformInt(0, fromRegion.motionsInTree.size() - 1);
697 const Motion *fromMotion = motions_[fromRegion.motionsInTree[random]];
700 const Motion *toMotion =
nullptr;
702 (toRegion.motionsInTree.size() > 0 && rng_.uniform01() < 0.50))
704 for (
size_t i = 0; i < toRegion.motionsInTree.size() && !toMotion; ++i)
705 if (lazyGraph_.edgeExists(fromMotion->index, motions_[toRegion.motionsInTree[i]]->index))
706 toMotion = motions_[toRegion.motionsInTree[i]];
709 bool newState =
false;
710 if (toMotion ==
nullptr)
713 if (decomposition_->sampleFromRegion(to, xstate_, fromMotion->state, layer->getLevel()))
715 int id = addState(xstate_);
716 toMotion = motions_[id];
721 if (toMotion ==
nullptr)
725 lazyGraph_.removeEdge(fromMotion->index, toMotion->index);
726 layer->selectRegion(to);
729 if (si_->checkMotion(fromMotion->state, toMotion->state))
732 double weight = si_->distance(fromMotion->state, toMotion->state);
734 if (realGraph_.numNeighbors(fromMotion->index) == 0)
735 statesConnectedInRealGraph_++;
736 if (realGraph_.numNeighbors(toMotion->index) == 0)
737 statesConnectedInRealGraph_++;
738 realGraph_.addEdge(fromMotion->index, toMotion->index, weight);
740 updateRegionConnectivity(fromMotion, toMotion, layer->getLevel());
745 Layer *l = topLayer_;
746 for (
size_t i = 0; i < toMotion->levels.size(); ++i)
748 l->getRegion(toMotion->levels[i]).motionsInTree.push_back(toMotion->index);
749 if (l->hasSublayers())
750 l = l->getSublayer(toMotion->levels[i]);
753 return toMotion->index;
759 bool ompl::geometric::XXL::feasibleLead(Layer *layer,
const std::vector<int> &lead,
762 assert(lead.size() > 0);
765 if (lead.size() == 1)
766 return layer->getRegion(lead[0]).motionsInTree.size() > 0;
770 std::vector<bool> regionInTree(lead.size(),
false);
771 size_t numRegionsInLead = 0;
772 for (
size_t i = 0; i < lead.size(); ++i)
774 regionInTree[i] = layer->getRegion(lead[i]).motionsInTree.size() > 0;
781 bool expanded =
true;
783 while (numRegionsInLead < lead.size() && expanded && !ptc)
786 for (
size_t i = 1; i < lead.size() && !ptc; ++i)
788 int from = -1, to = -1;
789 if (!regionInTree[i] && regionInTree[i - 1])
794 else if (regionInTree[i] && !regionInTree[i - 1])
803 for (
int j = 0; j < maxAttempts && !ptc && !expanded; ++j)
807 if (decomposition_->canSteer())
808 idx = steerToRegion(layer, lead[from], lead[to]);
810 idx = expandToRegion(layer, lead[from], lead[to]);
815 regionInTree[to] =
true;
821 else if (regionInTree[i] && regionInTree[i - 1])
823 const Region &r1 = layer->getRegion(lead[i - 1]);
824 const Region &r2 = layer->getRegion(lead[i]);
825 double p1 = 1.0 - (r1.motionsInTree.size() / (double)r1.allMotions.size());
826 double p2 = 1.0 - (r2.motionsInTree.size() / (double)r2.allMotions.size());
827 double p = std::max(p1, p2);
828 if (rng_.uniform01() < p)
829 connectRegions(layer, lead[i - 1], lead[i], ptc);
834 if (rng_.uniform01() < 0.05)
836 for (
size_t i = 1; i < lead.size(); ++i)
837 connectRegions(layer, lead[i - 1], lead[i], ptc);
840 for (
size_t i = 0; i < lead.size(); ++i)
841 updateRegionProperties(layer, lead[i]);
843 return numRegionsInLead == lead.size();
847 bool ompl::geometric::XXL::connectLead(Layer *layer,
const std::vector<int> &lead, std::vector<int> &candidateRegions,
850 if (lead.size() == 0)
853 AdjacencyList ®ionGraph = layer->getRegionGraph();
859 bool connected =
true;
860 for (
size_t i = 1; i < lead.size() && connected && !ptc; ++i)
862 bool regionsConnected = regionGraph.edgeExists(lead[i], lead[i - 1]);
864 const Region &r1 = layer->getRegion(lead[i - 1]);
865 const Region &r2 = layer->getRegion(lead[i]);
866 double p1 = 1.0 - (r1.motionsInTree.size() / (double)r1.allMotions.size());
867 double p2 = 1.0 - (r2.motionsInTree.size() / (double)r2.allMotions.size());
868 double p = std::max(p1, p2);
870 if (regionsConnected)
873 if (!regionsConnected || rng_.uniform01() < p)
874 connectRegions(layer, lead[i - 1], lead[i], ptc);
876 connected &= regionGraph.edgeExists(lead[i], lead[i - 1]);
888 std::set<int> startComponents;
889 std::set<int> goalComponents;
890 for (
size_t i = 0; i < startMotions_.size(); ++i)
891 startComponents.insert(realGraph_.getComponentID(startMotions_[i]));
892 for (
size_t i = 0; i < goalMotions_.size(); ++i)
893 goalComponents.insert(realGraph_.getComponentID(goalMotions_[i]));
897 std::set<int> sharedComponents;
898 for (std::set<int>::iterator it = startComponents.begin(); it != startComponents.end();)
900 std::set<int>::iterator goalIt = goalComponents.find(*it);
901 if (goalIt != goalComponents.end())
903 sharedComponents.insert(*it);
904 goalComponents.erase(goalIt);
905 startComponents.erase(it++);
911 if (sharedComponents.size())
915 std::vector<bool> inStartTree(lead.size(),
false);
916 std::vector<std::set<int>> validGoalComponents;
917 for (
size_t i = 0; i < lead.size(); ++i)
919 validGoalComponents.push_back(std::set<int>());
921 const std::vector<int> &motions = layer->getRegion(lead[i]).motionsInTree;
922 for (
size_t j = 0; j < motions.size(); ++j)
924 int component = realGraph_.getComponentID(motions[j]);
925 assert(component >= 0);
927 if (startComponents.find(component) != startComponents.end())
928 inStartTree[i] =
true;
929 else if (goalComponents.find(component) != goalComponents.end())
930 validGoalComponents[i].insert(component);
936 size_t min = validGoalComponents.size() - 1;
937 assert(validGoalComponents[min].size() > 0);
938 for (
size_t i = 0; i < validGoalComponents.size(); ++i)
939 if (validGoalComponents[i].size() && validGoalComponents[i].size() < validGoalComponents[min].size())
943 std::set<int> leadGoalComponents(validGoalComponents[min].begin(), validGoalComponents[min].end());
944 for (
size_t i = 0; i < lead.size(); ++i)
946 if (i == min || validGoalComponents[i].size() == 0)
949 for (std::set<int>::iterator it = leadGoalComponents.begin(); it != leadGoalComponents.end();)
950 if (validGoalComponents[i].find(*it) == validGoalComponents[i].end())
952 leadGoalComponents.erase(it++);
958 candidateRegions.clear();
959 for (
size_t i = 0; i < lead.size(); ++i)
965 for (std::set<int>::iterator it = validGoalComponents[i].begin(); it != validGoalComponents[i].end(); ++it)
966 if (leadGoalComponents.find(*it) != leadGoalComponents.end())
968 candidateRegions.push_back(lead[i]);
975 for (
size_t i = 0; i < candidateRegions.size(); ++i)
977 connectRegion(layer, candidateRegions[i], ptc);
980 for (
size_t i = 0; i < startMotions_.size(); ++i)
981 for (
size_t j = 0; j < goalMotions_.size(); ++j)
982 if (realGraph_.inSameComponent(startMotions_[i], goalMotions_[j]))
986 if (candidateRegions.size() == 0)
991 bool allConnectedToStart =
true;
992 for (
size_t i = 0; i < inStartTree.size(); ++i)
993 allConnectedToStart &= inStartTree[i];
995 if (allConnectedToStart && validGoalComponents[lead.size() - 1].size() > 0)
997 candidateRegions.push_back(lead.back());
998 connectRegion(layer, lead.back(), ptc);
1001 for (
size_t i = 0; i < startMotions_.size(); ++i)
1002 for (
size_t j = 0; j < goalMotions_.size(); ++j)
1003 if (realGraph_.inSameComponent(startMotions_[i], goalMotions_[j]))
1012 void ompl::geometric::XXL::connectRegion(Layer *layer,
int reg,
const base::PlannerTerminationCondition &ptc)
1015 assert(reg >= 0 && reg < decomposition_->getNumRegions());
1017 Region ®ion = layer->getRegion(reg);
1018 const std::vector<int> &allMotions = region.allMotions;
1021 std::vector<int> shuffledMotions(allMotions.begin(), allMotions.end());
1022 rng_.shuffle(shuffledMotions.begin(), shuffledMotions.end());
1025 size_t maxIdx = shuffledMotions.size();
1031 for (
size_t i = 0; i < maxIdx && !ptc; ++i)
1033 const Motion *m1 = motions_[shuffledMotions[i]];
1034 for (
size_t j = i + 1; j < maxIdx && !ptc; ++j)
1036 const Motion *m2 = motions_[shuffledMotions[j]];
1037 if (lazyGraph_.edgeExists(m1->index, m2->index) && !realGraph_.inSameComponent(m1->index, m2->index))
1040 lazyGraph_.removeEdge(m1->index, m2->index);
1044 if (si_->checkMotion(m1->state, m2->state))
1047 double weight = si_->distance(m1->state, m2->state);
1048 realGraph_.addEdge(m1->index, m2->index, weight);
1051 if (realGraph_.numNeighbors(m1->index) == 1 && !isStartState(m1->index) && !isGoalState(m1->index))
1053 statesConnectedInRealGraph_++;
1056 Layer *l = topLayer_;
1057 for (
size_t i = 0; i < m1->levels.size(); ++i)
1059 l->getRegion(m1->levels[i]).motionsInTree.push_back(m1->index);
1060 if (l->hasSublayers())
1061 l = l->getSublayer(m1->levels[i]);
1062 else if (i != m1->levels.size() - 1)
1066 if (realGraph_.numNeighbors(m2->index) == 1 && !isStartState(m2->index) && !isGoalState(m2->index))
1068 statesConnectedInRealGraph_++;
1071 Layer *l = topLayer_;
1072 for (
size_t i = 0; i < m2->levels.size(); ++i)
1074 l->getRegion(m2->levels[i]).motionsInTree.push_back(m2->index);
1075 if (l->hasSublayers())
1076 l = l->getSublayer(m2->levels[i]);
1077 else if (i != m2->levels.size() - 1)
1082 updateRegionConnectivity(m1, m2, layer->getLevel());
1085 assert(realGraph_.inSameComponent(m1->index, m2->index));
1091 layer->connectRegion(reg);
1092 updateRegionProperties(layer, reg);
1095 void ompl::geometric::XXL::connectRegions(Layer *layer,
int r1,
int r2,
const base::PlannerTerminationCondition &ptc,
1099 assert(r1 >= 0 && r1 < decomposition_->getNumRegions());
1100 assert(r2 >= 0 && r2 < decomposition_->getNumRegions());
1103 layer->selectRegion(r1, 20);
1104 layer->selectRegion(r2, 20);
1106 Region ®1 = layer->getRegion(r1);
1107 const std::vector<int> &allMotions1 = reg1.allMotions;
1109 std::vector<int> shuffledMotions1(allMotions1.begin(), allMotions1.end());
1110 rng_.shuffle(shuffledMotions1.begin(), shuffledMotions1.end());
1112 Region ®2 = layer->getRegion(r2);
1113 const std::vector<int> &allMotions2 = reg2.allMotions;
1115 std::vector<int> shuffledMotions2(allMotions2.begin(), allMotions2.end());
1116 rng_.shuffle(shuffledMotions2.begin(), shuffledMotions2.end());
1118 size_t maxConnections = std::numeric_limits<size_t>::max();
1119 size_t maxIdx1 = (all ? shuffledMotions1.size() : std::min(shuffledMotions1.size(), maxConnections));
1120 size_t maxIdx2 = (all ? shuffledMotions2.size() : std::min(shuffledMotions2.size(), maxConnections));
1123 for (
size_t i = 0; i < maxIdx1 && !ptc; ++i)
1125 const Motion *m1 = motions_[shuffledMotions1[i]];
1126 for (
size_t j = 0; j < maxIdx2 && !ptc; ++j)
1128 const Motion *m2 = motions_[shuffledMotions2[j]];
1129 if (lazyGraph_.edgeExists(m1->index, m2->index) && !realGraph_.inSameComponent(m1->index, m2->index))
1132 lazyGraph_.removeEdge(m1->index, m2->index);
1136 if (si_->checkMotion(m1->state, m2->state))
1139 double weight = si_->distance(m1->state, m2->state);
1140 realGraph_.addEdge(m1->index, m2->index, weight);
1143 if (realGraph_.numNeighbors(m1->index) == 1 && !isStartState(m1->index) && !isGoalState(m1->index))
1145 statesConnectedInRealGraph_++;
1148 Layer *l = topLayer_;
1149 for (
size_t i = 0; i < m1->levels.size(); ++i)
1151 l->getRegion(m1->levels[i]).motionsInTree.push_back(m1->index);
1152 if (l->hasSublayers())
1153 l = l->getSublayer(m1->levels[i]);
1156 if (realGraph_.numNeighbors(m2->index) == 1 && !isStartState(m2->index) && !isGoalState(m2->index))
1158 statesConnectedInRealGraph_++;
1161 Layer *l = topLayer_;
1162 for (
size_t i = 0; i < m2->levels.size(); ++i)
1164 l->getRegion(m2->levels[i]).motionsInTree.push_back(m2->index);
1165 if (l->hasSublayers())
1166 l = l->getSublayer(m2->levels[i]);
1170 updateRegionConnectivity(m1, m2, layer->getLevel());
1173 assert(realGraph_.inSameComponent(m1->index, m2->index));
1179 updateRegionProperties(layer, r1);
1180 updateRegionProperties(layer, r2);
1183 void ompl::geometric::XXL::computeLead(Layer *layer, std::vector<int> &lead)
1185 if (startMotions_.size() == 0)
1186 throw ompl::Exception(
"Cannot compute lead without at least one start state");
1187 if (goalMotions_.size() == 0)
1188 OMPL_WARN(
"No goal states to compute lead to");
1192 if (goalMotions_.size() == 0)
1194 const Motion *s = motions_[startMotions_[rng_.uniformInt(0, startMotions_.size() - 1)]];
1195 start = s->levels[layer->getLevel()];
1197 if (topLayer_->numRegions() == 1)
1203 end = rng_.uniformInt(0, topLayer_->numRegions() - 1);
1204 }
while (start == end);
1209 const Motion *s =
nullptr;
1210 const Motion *e =
nullptr;
1212 if (layer->getLevel() == 0)
1214 s = motions_[startMotions_[rng_.uniformInt(0, startMotions_.size() - 1)]];
1215 e = motions_[goalMotions_[rng_.uniformInt(0, goalMotions_.size() - 1)]];
1219 std::set<int> startComponents;
1220 for (
size_t i = 0; i < startMotions_.size(); ++i)
1221 startComponents.insert(realGraph_.getComponentID(startMotions_[i]));
1226 const Region ® = layer->getRegion(rng_.uniformInt(0, layer->numRegions() - 1));
1227 if (reg.motionsInTree.size())
1229 int random = rng_.uniformInt(0, reg.motionsInTree.size() - 1);
1231 int cid = realGraph_.getComponentID(reg.motionsInTree[random]);
1232 for (std::set<int>::const_iterator it = startComponents.begin(); it != startComponents.end(); ++it)
1235 s = motions_[reg.motionsInTree[random]];
1239 }
while (s ==
nullptr);
1241 std::set<int> goalComponents;
1242 for (
size_t i = 0; i < goalMotions_.size(); ++i)
1243 goalComponents.insert(realGraph_.getComponentID(goalMotions_[i]));
1248 const Region ® = layer->getRegion(rng_.uniformInt(0, layer->numRegions() - 1));
1249 if (reg.motionsInTree.size())
1251 int random = rng_.uniformInt(0, reg.motionsInTree.size() - 1);
1253 int cid = realGraph_.getComponentID(reg.motionsInTree[random]);
1254 for (std::set<int>::const_iterator it = goalComponents.begin(); it != goalComponents.end(); ++it)
1257 e = motions_[reg.motionsInTree[random]];
1261 }
while (e ==
nullptr);
1264 start = s->levels[layer->getLevel()];
1265 end = e->levels[layer->getLevel()];
1268 bool success =
false;
1278 if (rng_.uniform01() > rand_walk_rate_)
1279 success = shortestPath(start, end, lead, layer->getWeights()) && lead.size() > 0;
1281 success = randomWalk(start, end, lead) && lead.size() > 0;
1293 double p = layer->connectibleRegions() / ((double)layer->connectibleRegions() + 1);
1294 if (layer->hasSublayers() && layer->connectibleRegions() > 0 && rng_.uniform01() < p)
1297 int subregion = layer->connectibleRegion(rng_.uniformInt(0, layer->connectibleRegions() - 1));
1298 Layer *sublayer = layer->getSublayer(subregion);
1300 return searchForPath(sublayer, ptc);
1304 std::vector<int> lead;
1305 computeLead(layer, lead);
1306 layer->markLead(lead);
1309 sampleAlongLead(layer, lead, ptc);
1312 if (feasibleLead(layer, lead, ptc))
1314 std::vector<int> candidates;
1317 connectLead(layer, lead, candidates, ptc);
1318 if (constructSolutionPath())
1323 if (layer->hasSublayers())
1326 for (
size_t i = 0; i < candidates.size() && !ptc; ++i)
1328 Layer *sublayer = layer->getSublayer(candidates[i]);
1329 if (searchForPath(sublayer, ptc))
1341 if (!decomposition_)
1350 OMPL_ERROR(
"%s: Unknown type of goal", getName().c_str());
1355 OMPL_ERROR(
"%s: Insufficient states in sampleable goal region", getName().c_str());
1368 if (startMotions_.size() == 0)
1373 OMPL_ERROR(
"%s: No valid start states", getName().c_str());
1377 OMPL_INFORM(
"%s: Operating over %d dimensional, %d layer decomposition with %d regions per layer",
1378 getName().c_str(), decomposition_->getDimension(), decomposition_->numLayers(),
1379 decomposition_->getNumRegions());
1380 OMPL_INFORM(
"%s: Random ralk rate: %.3f", getName().c_str(), rand_walk_rate_);
1382 bool foundSolution =
false;
1384 while (!ptc && goalMotions_.size() == 0)
1387 while (!ptc && !foundSolution)
1390 foundSolution = searchForPath(topLayer_, ptc);
1393 if (!foundSolution && constructSolutionPath())
1395 OMPL_ERROR(
"Tripped and fell over a solution path.");
1396 foundSolution =
true;
1399 OMPL_INFORM(
"%s: Created %lu states (%lu start, %lu goal); %u are connected", getName().c_str(), motions_.size(),
1400 startMotions_.size(), goalMotions_.size(), statesConnectedInRealGraph_);
1409 bool ompl::geometric::XXL::isStartState(
int idx)
const
1411 for (
size_t i = 0; i < startMotions_.size(); ++i)
1412 if (idx == startMotions_[i])
1417 bool ompl::geometric::XXL::isGoalState(
int idx)
const
1419 for (
size_t i = 0; i < goalMotions_.size(); ++i)
1420 if (idx == goalMotions_[i])
1425 bool ompl::geometric::XXL::constructSolutionPath()
1427 int start = startMotions_[0];
1428 std::vector<int> predecessors;
1429 std::vector<double> cost;
1430 realGraph_.dijkstra(start, predecessors, cost);
1433 double bestCost = std::numeric_limits<double>::max();
1435 for (
size_t i = 0; i < goalMotions_.size(); ++i)
1437 if (cost[goalMotions_[i]] < bestCost)
1439 bestCost = cost[goalMotions_[i]];
1440 bestGoal = goalMotions_[i];
1447 std::vector<Motion *> slnPath;
1449 while (predecessors[v] != v)
1451 slnPath.push_back(motions_[v]);
1452 v = predecessors[v];
1454 slnPath.push_back(motions_[v]);
1456 PathGeometric *path =
new PathGeometric(si_);
1457 for (
int i = slnPath.size() - 1; i >= 0; --i)
1458 path->append(slnPath[i]->state);
1459 pdef_->addSolutionPath(base::PathPtr(path),
false, 0.0, getName());
1467 for (
size_t i = 0; i < motions_.size(); ++i)
1469 bool isStart =
false;
1470 bool isGoal =
false;
1472 for (
size_t j = 0; j < startMotions_.size(); ++j)
1473 if (startMotions_[j] == (
int)i)
1476 for (
size_t j = 0; j < goalMotions_.size(); ++j)
1477 if (goalMotions_[j] == (
int)i)
1480 if (!isStart && !isGoal)
1489 for (
size_t i = 0; i < motions_.size(); ++i)
1491 std::vector<std::pair<int, double>> nbrs;
1492 realGraph_.getNeighbors(i, nbrs);
1494 for (
size_t j = 0; j < nbrs.size(); ++j)
1499 void ompl::geometric::XXL::getGoalStates()
1503 while (pis_.haveMoreGoalStates() && newCount < maxCount )
1511 double dist = std::numeric_limits<double>::infinity();
1512 for (
size_t i = 0; i < goalMotions_.size(); ++i)
1514 double d = si_->distance(motions_[goalMotions_[i]]->state, st);
1523 OMPL_WARN(
"XXL: Rejecting goal state that is %f from another goal", dist);
1527 void ompl::geometric::XXL::getGoalStates(
const base::PlannerTerminationCondition & )
1561 void ompl::geometric::XXL::getNeighbors(
int rid,
const std::vector<double> &weights,
1562 std::vector<std::pair<int, double>> &neighbors)
const
1564 std::vector<int> nbrs;
1565 decomposition_->getNeighbors(rid, nbrs);
1567 for (
size_t i = 0; i < nbrs.size(); ++i)
1569 neighbors.push_back(std::make_pair(nbrs[i], weights[nbrs[i]]));
1577 double g{0.0}, h{std::numeric_limits<double>::infinity()};
1579 OpenListNode(
int _id) : id(_id)
1583 bool operator<(
const OpenListNode &other)
const
1585 return (g + h) > (other.g + other.h);
1591 bool ompl::geometric::XXL::shortestPath(
int r1,
int r2, std::vector<int> &path,
const std::vector<double> &weights)
1593 if (r1 < 0 || r1 >= decomposition_->getNumRegions())
1595 OMPL_ERROR(
"Start region (%d) is not valid", r1);
1599 if (r2 < 0 || r2 >= decomposition_->getNumRegions())
1601 OMPL_ERROR(
"Goal region (%d) is not valid", r2);
1606 double weight = 1.0;
1607 if (rng_.uniform01() < 0.50)
1609 if (rng_.uniform01() < 0.50)
1616 std::fill(predecessors_.begin(), predecessors_.end(), -1);
1617 std::fill(closedList_.begin(), closedList_.end(),
false);
1620 std::priority_queue<OpenListNode> openList;
1623 OpenListNode start(r1);
1625 start.h = weight * decomposition_->distanceHeuristic(r1, r2);
1627 openList.push(start);
1630 bool solution =
false;
1631 while (!openList.empty())
1633 OpenListNode node = openList.top();
1637 if (closedList_[node.id])
1641 closedList_[node.id] =
true;
1642 predecessors_[node.id] = node.parent;
1652 std::vector<std::pair<int, double>> neighbors;
1653 getNeighbors(node.id, weights, neighbors);
1656 rng_.shuffle(neighbors.begin(), neighbors.end());
1657 for (
size_t i = 0; i < neighbors.size(); ++i)
1660 if (!closedList_[neighbors[i].first])
1662 OpenListNode nbr(neighbors[i].first);
1663 nbr.g = node.g + neighbors[i].second;
1664 nbr.h = weight * decomposition_->distanceHeuristic(neighbors[i].first, r2);
1665 nbr.parent = node.id;
1676 while (predecessors_[current] != current)
1678 path.insert(path.begin(), current);
1679 current = predecessors_[current];
1682 path.insert(path.begin(), current);
1688 bool ompl::geometric::XXL::randomWalk(
int r1,
int r2, std::vector<int> &path)
1691 std::fill(predecessors_.begin(), predecessors_.end(), -1);
1692 std::fill(closedList_.begin(), closedList_.end(),
false);
1694 closedList_[r1] =
true;
1695 for (
int i = 0; i < decomposition_->getNumRegions(); ++i)
1699 while (!closedList_[u])
1701 std::vector<int> neighbors;
1702 decomposition_->getNeighbors(u, neighbors);
1703 int nbr = neighbors[rng_.uniformInt(0, neighbors.size() - 1)];
1705 predecessors_[u] = nbr;
1711 while (!closedList_[u])
1713 closedList_[u] =
true;
1714 u = predecessors_[u];
1720 while (predecessors_[current] != -1)
1722 path.insert(path.begin(), current);
1723 current = predecessors_[current];
1725 if ((
int)path.size() >= decomposition_->getNumRegions())
1728 path.insert(path.begin(), current);
1730 if (path.front() != r1)
1732 if (path.back() != r2)