37#include "ompl/geometric/planners/informedtrees/AITstar.h"
43#include <boost/range/adaptor/reversed.hpp>
45#include "ompl/base/objectives/PathLengthOptimizationObjective.h"
48using namespace std::string_literals;
49using namespace ompl::geometric::aitstar;
56 :
ompl::
base::Planner(spaceInformation,
"AITstar")
58 , graph_(solutionCost_)
59 , forwardQueue_([this](const auto &lhs, const auto &rhs) {
return isEdgeBetter(lhs, rhs); })
60 , reverseQueue_([
this](
const auto &lhs,
const auto &rhs) {
return isVertexBetter(lhs, rhs); })
64 specs_.multithreaded =
false;
65 specs_.approximateSolutions =
true;
66 specs_.optimizingPaths =
true;
67 specs_.directed =
true;
68 specs_.provingSolutionNonExistence =
false;
69 specs_.canReportIntermediateSolutions =
true;
84 addPlannerProgressProperty(
"iterations INTEGER", [
this]() {
return std::to_string(numIterations_); });
85 addPlannerProgressProperty(
"best cost DOUBLE", [
this]() {
return std::to_string(solutionCost_.value()); });
86 addPlannerProgressProperty(
"state collision checks INTEGER",
87 [
this]() {
return std::to_string(graph_.getNumberOfStateCollisionChecks()); });
88 addPlannerProgressProperty(
"edge collision checks INTEGER",
89 [
this]() {
return std::to_string(numEdgeCollisionChecks_); });
90 addPlannerProgressProperty(
"nearest neighbour calls INTEGER",
91 [
this]() {
return std::to_string(graph_.getNumberOfNearestNeighborCalls()); });
100 if (
static_cast<bool>(Planner::pdef_))
103 if (!
pdef_->hasOptimizationObjective())
105 OMPL_WARN(
"%s: No optimization objective has been specified. Defaulting to path length.",
106 Planner::getName().c_str());
107 Planner::pdef_->setOptimizationObjective(
108 std::make_shared<ompl::base::PathLengthOptimizationObjective>(Planner::si_));
111 if (
static_cast<bool>(
pdef_->getGoal()))
116 OMPL_ERROR(
"AIT* is currently only implemented for goals that can be cast to "
117 "ompl::base::GOAL_SAMPLEABLE_GOAL_REGION.");
124 objective_ =
pdef_->getOptimizationObjective();
127 solutionCost_ = objective_->infiniteCost();
128 approximateSolutionCost_ = objective_->infiniteCost();
129 approximateSolutionCostToGoal_ = objective_->infiniteCost();
132 motionValidator_ =
si_->getMotionValidator();
141 OMPL_WARN(
"AIT*: Unable to setup without a problem definition.");
172 if (!graph_.hasAStartState())
174 graph_.updateStartAndGoalStates(terminationCondition, &
pis_);
177 if (!graph_.hasAStartState())
179 OMPL_WARN(
"%s: No solution can be found as no start states are available",
name_.c_str());
185 if (!graph_.hasAGoalState())
187 graph_.updateStartAndGoalStates(terminationCondition, &
pis_);
190 if (!graph_.hasAGoalState())
192 OMPL_WARN(
"%s: No solution can be found as no goal states are available",
name_.c_str());
204 forwardQueue_.clear();
205 reverseQueue_.clear();
208 solutionCost_ = objective_->infiniteCost();
209 approximateSolutionCost_ = objective_->infiniteCost();
210 approximateSolutionCostToGoal_ = objective_->infiniteCost();
213 numInconsistentOrUnconnectedTargets_ = 0u;
239 OMPL_INFORM(
"%s: Solving the given planning problem. The current best solution cost is %.4f",
name_.c_str(),
240 solutionCost_.value());
243 while (!terminationCondition && !objective_->isSatisfied(solutionCost_))
245 iterate(terminationCondition);
250 status = updateSolution();
253 informAboutPlannerStatus(status);
259 return solutionCost_;
266 static std::set<std::shared_ptr<Vertex>,
267 std::function<bool(
const std::shared_ptr<Vertex> &,
const std::shared_ptr<Vertex> &)>>
268 liveStates([](
const auto &lhs,
const auto &rhs) {
return lhs->getId() < rhs->getId(); });
271 Planner::getPlannerData(data);
274 auto vertices = graph_.getVertices();
277 for (
const auto &vertex : vertices)
280 liveStates.insert(vertex);
283 if (graph_.isStart(vertex))
287 else if (graph_.isGoal(vertex))
297 if (vertex->hasForwardParent())
301 vertex->getForwardParent()->getId()));
308 batchSize_ = batchSize;
318 graph_.setRewireFactor(rewireFactor);
323 return graph_.getRewireFactor();
328 trackApproximateSolutions_ = track;
329 if (!trackApproximateSolutions_)
331 if (
static_cast<bool>(objective_))
333 approximateSolutionCost_ = objective_->infiniteCost();
334 approximateSolutionCostToGoal_ = objective_->infiniteCost();
341 return trackApproximateSolutions_;
346 isPruningEnabled_ = prune;
351 return isPruningEnabled_;
356 graph_.setUseKNearest(useKNearest);
361 return graph_.getUseKNearest();
366 graph_.setMaxNumberOfGoals(numberOfGoals);
371 return graph_.getMaxNumberOfGoals();
374 void AITstar::rebuildForwardQueue()
377 std::vector<Edge> edges;
381 for (
const auto &edge : edges)
383 edge.getChild()->resetForwardQueueIncomingLookup();
384 edge.getParent()->resetForwardQueueOutgoingLookup();
388 forwardQueue_.
clear();
389 numInconsistentOrUnconnectedTargets_ = 0u;
393 for (
auto &edge : edges)
395 insertOrUpdateInForwardQueue(
396 Edge(edge.getParent(), edge.getChild(), computeSortKey(edge.getParent(), edge.getChild())));
400 void AITstar::clearForwardQueue()
402 std::vector<Edge> forwardQueue;
403 forwardQueue_.getContent(forwardQueue);
404 for (
const auto &element : forwardQueue)
406 element.getChild()->resetForwardQueueIncomingLookup();
407 element.getParent()->resetForwardQueueOutgoingLookup();
409 forwardQueue_.clear();
410 numInconsistentOrUnconnectedTargets_ = 0u;
413 void AITstar::rebuildReverseQueue()
416 std::vector<aitstar::KeyVertexPair> content;
417 reverseQueue_.getContent(content);
418 for (
auto &element : content)
420 element.second->resetReverseQueuePointer();
422 reverseQueue_.clear();
424 for (
auto &vertex : content)
427 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> element(
428 computeSortKey(vertex.second), vertex.second);
429 auto reverseQueuePointer = reverseQueue_.insert(element);
430 element.second->setReverseQueuePointer(reverseQueuePointer);
434 void AITstar::clearReverseQueue()
436 std::vector<aitstar::KeyVertexPair> reverseQueue;
437 reverseQueue_.getContent(reverseQueue);
438 for (
const auto &element : reverseQueue)
440 element.second->resetReverseQueuePointer();
442 reverseQueue_.clear();
445 void AITstar::informAboutNewSolution()
const
447 OMPL_INFORM(
"%s (%u iterations): Found a new exact solution of cost %.4f. Sampled a total of %u states, %u "
448 "of which were valid samples (%.1f \%). Processed %u edges, %u of which were collision checked "
449 "(%.1f \%). The forward search tree has %u vertices, %u of which are start states. The reverse "
450 "search tree has %u vertices, %u of which are goal states.",
451 name_.c_str(), numIterations_, solutionCost_.value(), graph_.getNumberOfSampledStates(),
452 graph_.getNumberOfValidSamples(),
453 graph_.getNumberOfSampledStates() == 0u ?
455 100.0 * (
static_cast<double>(graph_.getNumberOfValidSamples()) /
456 static_cast<double>(graph_.getNumberOfSampledStates())),
457 numProcessedEdges_, numEdgeCollisionChecks_,
458 numProcessedEdges_ == 0u ? 0.0 :
459 100.0 * (
static_cast<float>(numEdgeCollisionChecks_) /
460 static_cast<float>(numProcessedEdges_)),
461 countNumVerticesInForwardTree(), graph_.getStartVertices().size(),
462 countNumVerticesInReverseTree(), graph_.getGoalVertices().size());
471 OMPL_INFORM(
"%s (%u iterations): Found an exact solution of cost %.4f.",
name_.c_str(),
472 numIterations_, solutionCost_.value());
477 OMPL_INFORM(
"%s (%u iterations): Did not find an exact solution, but found an approximate "
479 "of cost %.4f which is %.4f away from a goal (in cost space).",
480 name_.c_str(), numIterations_, approximateSolutionCost_.value(),
481 approximateSolutionCostToGoal_.value());
486 if (trackApproximateSolutions_)
488 OMPL_INFORM(
"%s (%u iterations): Did not find any solution.",
name_.c_str(), numIterations_);
492 OMPL_INFORM(
"%s (%u iterations): Did not find an exact solution, and tracking approximate "
493 "solutions is disabled.",
494 name_.c_str(), numIterations_);
507 OMPL_INFORM(
"%s (%u iterations): Unable to solve the given planning problem.",
name_.c_str(),
513 "%s (%u iterations): Sampled a total of %u states, %u of which were valid samples (%.1f \%). "
514 "Processed %u edges, %u of which were collision checked (%.1f \%). The forward search tree "
515 "has %u vertices. The reverse search tree has %u vertices.",
516 name_.c_str(), numIterations_, graph_.getNumberOfSampledStates(), graph_.getNumberOfValidSamples(),
517 graph_.getNumberOfSampledStates() == 0u ?
519 100.0 * (
static_cast<double>(graph_.getNumberOfValidSamples()) /
520 static_cast<double>(graph_.getNumberOfSampledStates())),
521 numProcessedEdges_, numEdgeCollisionChecks_,
522 numProcessedEdges_ == 0u ?
524 100.0 * (
static_cast<float>(numEdgeCollisionChecks_) /
static_cast<float>(numProcessedEdges_)),
525 countNumVerticesInForwardTree(), countNumVerticesInReverseTree());
528 void AITstar::insertGoalVerticesInReverseQueue()
530 for (
const auto &goal : graph_.getGoalVertices())
533 goal->setExpandedCostToComeFromGoal(objective_->infiniteCost());
534 goal->setCostToComeFromGoal(objective_->identityCost());
537 aitstar::KeyVertexPair element({computeCostToGoToStartHeuristic(goal), objective_->identityCost()},
541 auto reverseQueuePointer = reverseQueue_.insert(element);
542 goal->setReverseQueuePointer(reverseQueuePointer);
546 void AITstar::expandStartVerticesIntoForwardQueue()
548 for (
const auto &start : graph_.getStartVertices())
550 start->setCostToComeFromStart(objective_->identityCost());
551 insertOrUpdateInForwardQueue(getOutgoingEdges(start));
555 bool AITstar::continueReverseSearch()
const
558 if (reverseQueue_.empty() || forwardQueue_.empty())
564 const auto &bestEdge = forwardQueue_.top()->data;
565 const auto &bestVertex = reverseQueue_.top()->data;
569 return !((bestEdge.getChild()->isConsistent() &&
570 objective_->isCostBetterThan(bestEdge.getSortKey()[0u], bestVertex.first[0u])) ||
571 numInconsistentOrUnconnectedTargets_ == 0u);
574 bool AITstar::continueForwardSearch()
577 if (forwardQueue_.empty())
585 const auto &bestEdgeCost = forwardQueue_.top()->data.getSortKey()[0u];
586 if (!objective_->isFinite(bestEdgeCost))
592 return objective_->isCostBetterThan(bestEdgeCost, solutionCost_);
597 std::vector<Edge> edges;
598 forwardQueue_.getContent(edges);
605 std::vector<std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>>> content;
606 reverseQueue_.getContent(content);
609 std::vector<std::shared_ptr<Vertex>> vertices;
610 for (
const auto &pair : content)
612 vertices.emplace_back(pair.second);
619 if (!forwardQueue_.empty())
621 return forwardQueue_.top()->data;
629 if (!reverseQueue_.empty())
631 return reverseQueue_.top()->data.second;
640 auto vertices = graph_.getVertices();
643 vertices.erase(std::remove_if(vertices.begin(), vertices.end(),
644 [
this](
const std::shared_ptr<Vertex> &vertex)
645 { return !graph_.isGoal(vertex) && !vertex->hasReverseParent(); }),
653 if (numIterations_ == 0u)
655 insertGoalVerticesInReverseQueue();
656 expandStartVerticesIntoForwardQueue();
663 if (continueReverseSearch())
665 iterateReverseSearch();
667 else if (continueForwardSearch())
669 iterateForwardSearch();
674 if (graph_.addSamples(batchSize_, terminationCondition))
677 if (isPruningEnabled_)
683 for (
auto &goal : graph_.getGoalVertices())
685 invalidateCostToComeFromGoalOfReverseBranch(goal);
689 if (
pis_.haveMoreStartStates() ||
pis_.haveMoreGoalStates())
697 insertGoalVerticesInReverseQueue();
698 expandStartVerticesIntoForwardQueue();
703 void AITstar::iterateForwardSearch()
705 assert(!forwardQueue_.empty());
708 auto parent = forwardQueue_.top()->data.getParent();
709 auto child = forwardQueue_.top()->data.getChild();
710 child->removeFromForwardQueueIncomingLookup(forwardQueue_.top());
711 parent->removeFromForwardQueueOutgoingLookup(forwardQueue_.top());
715 assert(child->isConsistent());
716 assert(!graph_.isGoal(parent));
719 ++numProcessedEdges_;
722 if (child->hasForwardParent() && child->getForwardParent()->getId() == parent->getId())
724 insertOrUpdateInForwardQueue(getOutgoingEdges(child));
727 else if (objective_->isCostBetterThan(objective_->combineCosts(parent->getCostToComeFromStart(),
728 objective_->motionCostHeuristic(
729 parent->getState(), child->getState())),
730 child->getCostToComeFromStart()))
734 if (parent->isWhitelistedAsChild(child) ||
735 motionValidator_->checkMotion(parent->getState(), child->getState()))
738 if (!parent->isWhitelistedAsChild(child))
740 parent->whitelistAsChild(child);
741 numEdgeCollisionChecks_++;
745 const auto edgeCost = objective_->motionCost(parent->getState(), child->getState());
748 if (objective_->isCostBetterThan(
749 objective_->combineCosts(parent->getCostToComeFromStart(), edgeCost),
750 child->getCostToComeFromStart()))
753 child->setForwardParent(parent, edgeCost);
756 parent->addToForwardChildren(child);
759 child->updateCostOfForwardBranch();
762 updateSolution(child);
765 insertOrUpdateInForwardQueue(getOutgoingEdges(child));
771 parent->blacklistAsChild(child);
772 child->blacklistAsChild(parent);
775 if (parent->hasReverseParent() && parent->getReverseParent()->getId() == child->getId())
779 invalidateCostToComeFromGoalOfReverseBranch(parent);
785 void AITstar::iterateReverseSearch()
787 assert(!reverseQueue_.empty());
790 auto vertex = reverseQueue_.top()->data.second;
792 vertex->resetReverseQueuePointer();
795 assert(!vertex->isConsistent());
798 if (objective_->isCostBetterThan(vertex->getCostToComeFromGoal(), vertex->getExpandedCostToComeFromGoal()))
801 vertex->setExpandedCostToComeFromGoal(vertex->getCostToComeFromGoal());
802 updateReverseSearchNeighbors(vertex);
805 numInconsistentOrUnconnectedTargets_ -= vertex->getForwardQueueIncomingLookup().size();
810 vertex->setExpandedCostToComeFromGoal(objective_->infiniteCost());
813 updateReverseSearchVertex(vertex);
814 updateReverseSearchNeighbors(vertex);
818 bool AITstar::isEdgeBetter(
const Edge &lhs,
const Edge &rhs)
const
820 return std::lexicographical_compare(
822 [
this](
const auto &a,
const auto &b) { return objective_->isCostBetterThan(a, b); });
825 bool AITstar::isVertexBetter(
const aitstar::KeyVertexPair &lhs,
const aitstar::KeyVertexPair &rhs)
const
829 if (objective_->isCostEquivalentTo(lhs.first[0u], rhs.first[0u]) &&
830 objective_->isCostEquivalentTo(lhs.first[1u], rhs.first[1u]))
832 return !lhs.second->getForwardQueueIncomingLookup().empty() && !lhs.second->isConsistent();
837 return std::lexicographical_compare(lhs.first.cbegin(), lhs.first.cend(), rhs.first.cbegin(),
838 rhs.first.cend(), [
this](
const auto &a,
const auto &b)
839 { return objective_->isCostBetterThan(a, b); });
843 void AITstar::updateReverseSearchVertex(
const std::shared_ptr<Vertex> &vertex)
846 if (graph_.isGoal(vertex))
848 assert(objective_->isCostEquivalentTo(vertex->getCostToComeFromGoal(), objective_->identityCost()));
853 auto bestParent = vertex->getReverseParent();
854 auto bestCost = vertex->hasReverseParent() ? vertex->getCostToComeFromGoal() : objective_->infiniteCost();
857 for (
const auto &neighbor : graph_.getNeighbors(vertex))
859 if (neighbor->getId() != vertex->getId() && !neighbor->isBlacklistedAsChild(vertex) &&
860 !vertex->isBlacklistedAsChild(neighbor))
862 auto edgeCost = objective_->motionCostHeuristic(neighbor->getState(), vertex->getState());
863 auto parentCost = objective_->combineCosts(neighbor->getExpandedCostToComeFromGoal(), edgeCost);
864 if (objective_->isCostBetterThan(parentCost,
bestCost))
866 bestParent = neighbor;
873 for (
const auto &forwardChild : vertex->getForwardChildren())
875 auto edgeCost = objective_->motionCostHeuristic(forwardChild->getState(), vertex->getState());
876 auto parentCost = objective_->combineCosts(forwardChild->getExpandedCostToComeFromGoal(), edgeCost);
878 if (objective_->isCostBetterThan(parentCost,
bestCost))
880 bestParent = forwardChild;
886 if (vertex->hasForwardParent())
888 auto forwardParent = vertex->getForwardParent();
889 auto edgeCost = objective_->motionCostHeuristic(forwardParent->getState(), vertex->getState());
890 auto parentCost = objective_->combineCosts(forwardParent->getExpandedCostToComeFromGoal(), edgeCost);
892 if (objective_->isCostBetterThan(parentCost,
bestCost))
894 bestParent = forwardParent;
900 vertex->setCostToComeFromGoal(
bestCost);
906 vertex->setReverseParent(bestParent);
907 bestParent->addToReverseChildren(vertex);
912 if (vertex->hasReverseParent())
914 vertex->getReverseParent()->removeFromReverseChildren(vertex->getId());
915 vertex->resetReverseParent();
920 if (!vertex->isConsistent())
922 insertOrUpdateInReverseQueue(vertex);
926 auto reverseQueuePointer = vertex->getReverseQueuePointer();
927 if (reverseQueuePointer)
929 reverseQueue_.remove(reverseQueuePointer);
930 vertex->resetReverseQueuePointer();
937 for (
const auto &element : vertex->getForwardQueueIncomingLookup())
939 auto &edge = element->data;
940 edge.setSortKey(computeSortKey(edge.getParent(), edge.getChild()));
941 forwardQueue_.update(element);
945 void AITstar::updateReverseSearchNeighbors(
const std::shared_ptr<Vertex> &vertex)
949 for (
const auto &child : vertex->getReverseChildren())
951 updateReverseSearchVertex(child);
955 for (
const auto &neighbor : graph_.getNeighbors(vertex))
957 if (neighbor->getId() != vertex->getId() && !neighbor->isBlacklistedAsChild(vertex) &&
958 !vertex->isBlacklistedAsChild(neighbor))
960 updateReverseSearchVertex(neighbor);
965 for (
const auto &child : vertex->getForwardChildren())
967 updateReverseSearchVertex(child);
971 if (vertex->hasForwardParent())
973 updateReverseSearchVertex(vertex->getForwardParent());
977 void AITstar::insertOrUpdateInReverseQueue(
const std::shared_ptr<Vertex> &vertex)
980 auto element = vertex->getReverseQueuePointer();
985 element->data.first = computeSortKey(vertex);
986 reverseQueue_.update(element);
991 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> element(computeSortKey(vertex),
995 auto reverseQueuePointer = reverseQueue_.insert(element);
996 vertex->setReverseQueuePointer(reverseQueuePointer);
1000 void AITstar::insertOrUpdateInForwardQueue(
const Edge &edge)
1004 const auto it = std::find_if(lookup.begin(), lookup.end(), [&edge](
const auto element)
1005 { return element->data.getParent()->getId() == edge.getParent()->getId(); });
1007 if (it != lookup.end())
1013 { return element->data.getChild()->getId() == edge.getChild()->getId(); }) !=
1017 if (isEdgeBetter(edge, (*it)->data))
1020 forwardQueue_.update(*it);
1025 auto element = forwardQueue_.insert(edge);
1032 ++numInconsistentOrUnconnectedTargets_;
1037 void AITstar::insertOrUpdateInForwardQueue(
const std::vector<Edge> &edges)
1039 for (
const auto &edge : edges)
1041 insertOrUpdateInForwardQueue(edge);
1045 std::shared_ptr<ompl::geometric::PathGeometric>
1046 AITstar::getPathToVertex(
const std::shared_ptr<Vertex> &vertex)
const
1049 std::vector<std::shared_ptr<Vertex>> reversePath;
1050 auto current = vertex;
1051 while (!graph_.isStart(current))
1053 reversePath.emplace_back(current);
1054 current = current->getForwardParent();
1056 reversePath.emplace_back(current);
1059 auto path = std::make_shared<ompl::geometric::PathGeometric>(Planner::si_);
1060 for (
const auto &vertex : boost::adaptors::reverse(reversePath))
1062 path->append(vertex->getState());
1068 std::array<ompl::base::Cost, 3u> AITstar::computeSortKey(
const std::shared_ptr<Vertex> &parent,
1069 const std::shared_ptr<Vertex> &child)
const
1073 ompl::base::Cost edgeCostHeuristic = objective_->motionCostHeuristic(parent->getState(), child->getState());
1075 objective_->combineCosts(objective_->combineCosts(parent->getCostToComeFromStart(), edgeCostHeuristic),
1076 child->getCostToGoToGoal()),
1077 objective_->combineCosts(edgeCostHeuristic, child->getCostToGoToGoal()),
1078 parent->getCostToComeFromStart()};
1081 std::array<ompl::base::Cost, 2u> AITstar::computeSortKey(
const std::shared_ptr<Vertex> &vertex)
const
1084 return {objective_->combineCosts(objective_->betterCost(vertex->getCostToComeFromGoal(),
1085 vertex->getExpandedCostToComeFromGoal()),
1086 computeCostToGoToStartHeuristic(vertex)),
1087 objective_->betterCost(vertex->getCostToComeFromGoal(), vertex->getExpandedCostToComeFromGoal())};
1090 std::vector<Edge> AITstar::getOutgoingEdges(
const std::shared_ptr<Vertex> &vertex)
const
1093 std::vector<Edge> outgoingEdges;
1096 for (
const auto &child : vertex->getForwardChildren())
1098 outgoingEdges.emplace_back(vertex, child, computeSortKey(vertex, child));
1102 for (
const auto &neighbor : graph_.getNeighbors(vertex))
1105 if (vertex->getId() == neighbor->getId())
1111 if (vertex->hasReverseParent() && neighbor->getId() == vertex->getReverseParent()->getId())
1117 if (neighbor->isBlacklistedAsChild(vertex) || vertex->isBlacklistedAsChild(neighbor))
1123 outgoingEdges.emplace_back(vertex, neighbor, computeSortKey(vertex, neighbor));
1127 if (vertex->hasReverseParent())
1129 const auto &reverseParent = vertex->getReverseParent();
1130 outgoingEdges.emplace_back(vertex, reverseParent, computeSortKey(vertex, reverseParent));
1133 return outgoingEdges;
1136 void AITstar::updateExactSolution()
1139 for (
const auto &goal : graph_.getGoalVertices())
1143 if (objective_->isCostBetterThan(goal->getCostToComeFromStart(), solutionCost_) ||
1144 (!
pdef_->hasExactSolution() && objective_->isFinite(goal->getCostToComeFromStart())))
1147 solutionCost_ = goal->getCostToComeFromStart();
1150 ompl::base::PlannerSolution solution(getPathToVertex(goal));
1151 solution.setPlannerName(
name_);
1154 solution.setOptimized(objective_, solutionCost_, objective_->isSatisfied(solutionCost_));
1157 pdef_->addSolutionPath(solution);
1160 if (
static_cast<bool>(
pdef_->getIntermediateSolutionCallback()))
1162 const auto &path = solution.path_->as<ompl::geometric::PathGeometric>()->getStates();
1164 std::vector<const base::State *> const_path(path.begin(), path.end());
1165 pdef_->getIntermediateSolutionCallback()(
this, const_path, solutionCost_);
1169 informAboutNewSolution();
1174 void AITstar::updateApproximateSolution()
1176 for (
auto &start : graph_.getStartVertices())
1178 start->callOnForwardBranch([
this](
const auto &vertex) ->
void { updateApproximateSolution(vertex); });
1182 void AITstar::updateApproximateSolution(
const std::shared_ptr<Vertex> &vertex)
1184 assert(trackApproximateSolutions_);
1185 if (vertex->hasForwardParent() || graph_.isStart(vertex))
1187 auto costToGoal = computeCostToGoToGoal(vertex);
1191 if (objective_->isCostBetterThan(costToGoal, approximateSolutionCostToGoal_) ||
1192 !
pdef_->hasApproximateSolution())
1195 approximateSolutionCost_ = vertex->getCostToComeFromStart();
1196 approximateSolutionCostToGoal_ = costToGoal;
1197 ompl::base::PlannerSolution solution(getPathToVertex(vertex));
1198 solution.setPlannerName(
name_);
1201 solution.setApproximate(costToGoal.value());
1204 solution.setOptimized(objective_, approximateSolutionCost_,
false);
1207 pdef_->addSolutionPath(solution);
1214 updateExactSolution();
1215 if (objective_->isFinite(solutionCost_))
1219 else if (trackApproximateSolutions_)
1221 updateApproximateSolution();
1232 updateExactSolution();
1233 if (objective_->isFinite(solutionCost_))
1237 else if (trackApproximateSolutions_)
1239 updateApproximateSolution(vertex);
1248 ompl::base::Cost AITstar::computeCostToGoToStartHeuristic(
const std::shared_ptr<Vertex> &vertex)
const
1251 ompl::base::Cost
bestCost = objective_->infiniteCost();
1252 for (
const auto &start : graph_.getStartVertices())
1255 bestCost, objective_->motionCostHeuristic(vertex->getState(), start->getState()));
1260 ompl::base::Cost AITstar::computeCostToGoToGoalHeuristic(
const std::shared_ptr<Vertex> &vertex)
const
1263 ompl::base::Cost
bestCost = objective_->infiniteCost();
1264 for (
const auto &goal : graph_.getGoalVertices())
1267 bestCost, objective_->motionCostHeuristic(vertex->getState(), goal->getState()));
1272 ompl::base::Cost AITstar::computeCostToGoToGoal(
const std::shared_ptr<Vertex> &vertex)
const
1275 ompl::base::Cost
bestCost = objective_->infiniteCost();
1276 for (
const auto &goal : graph_.getGoalVertices())
1279 objective_->betterCost(
bestCost, objective_->motionCost(vertex->getState(), goal->getState()));
1284 ompl::base::Cost AITstar::computeBestCostToComeFromGoalOfAnyStart()
const
1287 ompl::base::Cost
bestCost = objective_->infiniteCost();
1288 for (
const auto &start : graph_.getStartVertices())
1290 bestCost = objective_->betterCost(
bestCost, start->getCostToComeFromGoal());
1295 std::size_t AITstar::countNumVerticesInForwardTree()
const
1297 std::size_t numVerticesInForwardTree = 0u;
1298 auto vertices = graph_.getVertices();
1299 for (
const auto &vertex : vertices)
1301 if (graph_.isStart(vertex) || vertex->hasForwardParent())
1303 ++numVerticesInForwardTree;
1306 return numVerticesInForwardTree;
1309 std::size_t AITstar::countNumVerticesInReverseTree()
const
1311 std::size_t numVerticesInReverseTree = 0u;
1312 auto vertices = graph_.getVertices();
1313 for (
const auto &vertex : vertices)
1315 if (graph_.isGoal(vertex) || vertex->hasReverseParent())
1317 ++numVerticesInReverseTree;
1320 return numVerticesInReverseTree;
1323 void AITstar::invalidateCostToComeFromGoalOfReverseBranch(
const std::shared_ptr<Vertex> &vertex)
1327 if (vertex->isConsistent())
1329 numInconsistentOrUnconnectedTargets_ += vertex->getForwardQueueIncomingLookup().size();
1333 if (!graph_.isGoal(vertex))
1336 vertex->resetCostToComeFromGoal();
1339 vertex->getReverseParent()->removeFromReverseChildren(vertex->getId());
1340 vertex->resetReverseParent();
1344 vertex->resetExpandedCostToComeFromGoal();
1347 for (
const auto &edge : vertex->getForwardQueueIncomingLookup())
1350 forwardQueue_.update(edge);
1354 auto reverseQueuePointer = vertex->getReverseQueuePointer();
1355 if (reverseQueuePointer)
1357 reverseQueue_.remove(reverseQueuePointer);
1358 vertex->resetReverseQueuePointer();
1362 for (
const auto &child : vertex->getReverseChildren())
1364 invalidateCostToComeFromGoalOfReverseBranch(child);
1368 updateReverseSearchVertex(vertex);
void getContent(std::vector< _T > &content) const
Get the data stored in this heap.
void clear()
Clear the heap.
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique,...
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...
unsigned int addVertex(const PlannerDataVertex &st)
Adds the given vertex to the graph data. The vertex index is returned. Duplicates are not added....
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
PlannerInputStates pis_
Utility class to extract valid input states.
ProblemDefinitionPtr pdef_
The user set problem definition.
std::string name_
The name of this planner.
SpaceInformationPtr si_
The space information for which planning is done.
virtual void checkValidity()
Check to see if the planner is in a working state (setup has been called, a goal was set,...
bool setup_
Flag indicating whether setup() has been called.
std::shared_ptr< aitstar::Vertex > getNextVertexInQueue() const
Get the next vertex in the queue.
void enablePruning(bool prune)
Set whether pruning is enabled or not.
void setMaxNumberOfGoals(unsigned int numberOfGoals)
Set the maximum number of goals AIT* will sample from sampleable goal regions.
double getRewireFactor() const
Get the rewire factor of the RGG graph.
bool isPruningEnabled() const
Get whether pruning is enabled or not.
void setRewireFactor(double rewireFactor)
Set the rewire factor of the RGG graph.
void setBatchSize(std::size_t batchSize)
Set the batch size.
ompl::base::PlannerStatus::StatusType ensureStartAndGoalStates(const ompl::base::PlannerTerminationCondition &terminationCondition)
Checks whether the problem is successfully setup.
ompl::base::Cost bestCost() const
Get the cost of the incumbent solution.
unsigned int getMaxNumberOfGoals() const
Get the maximum number of goals AIT* will sample from sampleable goal regions.
std::vector< std::shared_ptr< aitstar::Vertex > > getVerticesInQueue() const
Get the vertex queue.
AITstar(const ompl::base::SpaceInformationPtr &spaceInformation)
Constructs a AIT*.
bool getUseKNearest() const
Get whether to use a k-nearest RGG connection model. If false, AIT* uses an r-disc model.
aitstar::Edge getNextEdgeInQueue() const
Get the next edge in the queue.
void getPlannerData(base::PlannerData &data) const override
Get the planner data.
void setup() override
Additional setup that can only be done once a problem definition is set.
ompl::base::PlannerStatus solve(const ompl::base::PlannerTerminationCondition &terminationCondition) override
Solves a motion planning problem.
ompl::base::PlannerStatus::StatusType ensureSetup()
Checks whether the planner is successfully setup.
std::vector< std::shared_ptr< aitstar::Vertex > > getVerticesInReverseSearchTree() const
Get the vertices in the reverse search tree.
void trackApproximateSolutions(bool track)
Set whether to track approximate solutions.
void setUseKNearest(bool useKNearest)
Set whether to use a k-nearest RGG connection model. If false, AIT* uses an r-disc model.
void clear() override
Clears the algorithm's internal state.
std::vector< aitstar::Edge > getEdgesInQueue() const
Get the edge queue.
std::size_t getBatchSize() const
Get the batch size.
bool areApproximateSolutionsTracked() const
Get whether approximate solutions are tracked.
std::shared_ptr< Vertex > getChild() const
Returns the child in this edge.
const std::array< ompl::base::Cost, 3u > & getSortKey() const
Returns the sort key associated with this edge.
void setSortKey(const std::array< ompl::base::Cost, 3u > &key)
Sets the sort key associated with this edge.
std::shared_ptr< Vertex > getParent() const
Returns the parent in this edge.
std::vector< EdgeQueue::Element * > getForwardQueueIncomingLookup() const
Returns the forward queue incoming lookup of this vertex.
void addToForwardQueueOutgoingLookup(typename EdgeQueue::Element *pointer)
Adds an element to the forward queue outgoing lookup.
std::vector< EdgeQueue::Element * > getForwardQueueOutgoingLookup() const
Returns the forward queue outgoing lookup of this vertex.
bool isConsistent() const
Returns whether the vertex is consistent, i.e., whether its cost-to-come is equal to the cost-to-come...
ompl::base::Cost getCostToComeFromGoal() const
Returns the cost to come to this vertex from the goal.
void addToForwardQueueIncomingLookup(typename EdgeQueue::Element *pointer)
Adds an element to the forward queue incoming lookup.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
This namespace contains sampling based planning routines shared by both planning under geometric cons...
PlannerTerminationCondition plannerAlwaysTerminatingCondition()
Simple termination condition that always returns true. The termination condition will always be met.
@ GOAL_SAMPLEABLE_REGION
This bit is set if casting to sampleable goal regions (ompl::base::GoalSampleableRegion) is possible.
This namespace contains code that is specific to planning under geometric constraints.
Main namespace. Contains everything in this library.
A class to store the exit status of Planner::solve().
StatusType
The possible values of the status returned by a planner.
@ ABORT
The planner did not find a solution for some other reason.
@ 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.
@ UNKNOWN
Uninitialized status.
@ TYPE_COUNT
The number of possible status values.
@ INFEASIBLE
The planner decided that problem is infeasible.
@ CRASH
The planner crashed.