37 #include "ompl/geometric/planners/informedtrees/eitstar/ForwardQueue.h"
42 #include "ompl/geometric/planners/informedtrees/eitstar/Direction.h"
43 #include "ompl/geometric/planners/informedtrees/eitstar/State.h"
52 const std::shared_ptr<const ompl::base::StateSpace> &space)
53 : objective_(objective), space_(space)
70 modifiedQueue_ =
true;
73 std::pair<std::size_t, std::size_t> key = std::make_pair(edge.source->getId(), edge.target->getId());
74 const auto element = makeElement(edge);
75 auto it = queue_.find(key);
76 if (it != queue_.end())
82 queue_.insert({key, element});
86 edge.target->addToSourcesOfIncomingEdgesInForwardQueue(edge.source);
91 modifiedQueue_ =
true;
94 for (
const auto &edge : edges)
102 const std::pair<std::size_t, std::size_t> key =
103 std::make_pair(edge.source->getId(), edge.target->getId());
104 const auto it = queue_.find(key);
105 if (it != queue_.cend())
109 edge.target->removeFromSourcesOfIncomingEdgesInForwardQueue(edge.source);
111 modifiedQueue_ =
true;
115 throw std::out_of_range(
"Can not remove edge from the forward queue, because it is not in the "
120 ForwardQueue::Container::const_iterator ForwardQueue::getFrontIter(
double suboptimalityFactor)
122 if (cacheQueueLookup_ && !modifiedQueue_)
127 auto lowerBoundEdgeCost = objective_->infiniteCost();
128 auto bestCostEdgeCost = objective_->infiniteCost();
130 auto lowerBoundEdge = queue_.cbegin();
131 auto bestCostEdge = queue_.cbegin();
133 if (std::isfinite(suboptimalityFactor))
136 lowerBoundEdge = getLowerBoundCostEdge();
137 lowerBoundEdgeCost = inflateCost(get(lowerBoundEdge).first.lowerBoundCost, suboptimalityFactor);
140 bestCostEdge = getBestCostEstimateEdge();
141 bestCostEdgeCost = inflateCost(get(bestCostEdge).first.estimatedCost, suboptimalityFactor);
145 auto bestEffortEdge = queue_.cbegin();
146 auto bestEffortEdgeCost = objective_->infiniteCost();
147 auto bestEffortLowerBoundCost = objective_->infiniteCost();
148 for (
auto it = queue_.cbegin(); it != queue_.cend(); ++it)
150 if (get(it).first.estimatedEffort < get(bestEffortEdge).first.estimatedEffort &&
151 !objective_->isCostBetterThan(bestCostEdgeCost, get(it).first.estimatedCost))
153 bestEffortEdgeCost = get(it).first.estimatedCost;
154 bestEffortLowerBoundCost = get(it).first.lowerBoundCost;
157 else if (get(it).first.estimatedEffort == get(bestEffortEdge).first.estimatedEffort &&
158 !objective_->isCostBetterThan(bestCostEdgeCost, get(it).first.estimatedCost) &&
159 objective_->isCostBetterThan(get(it).first.lowerBoundCost, bestEffortLowerBoundCost))
161 bestEffortEdgeCost = get(it).first.estimatedCost;
162 bestEffortLowerBoundCost = get(it).first.lowerBoundCost;
168 if (objective_->isCostBetterThan(bestEffortEdgeCost, lowerBoundEdgeCost))
170 return bestEffortEdge;
172 else if (objective_->isCostBetterThan(get(bestCostEdge).first.estimatedCost, lowerBoundEdgeCost))
178 return lowerBoundEdge;
187 throw std::out_of_range(
"Forward queue is empty, cannot peek.");
190 front_ = getFrontIter(suboptimalityFactor);
191 auto edge = get(front_).second;
195 modifiedQueue_ =
false;
203 const std::pair<std::size_t, std::size_t> key =
204 std::make_pair(edge.
source->getId(), edge.
target->getId());
205 const auto it = queue_.find(key);
206 if (it == queue_.end())
211 it->second = makeElement(edge);
212 modifiedQueue_ =
true;
217 auto it = getFrontIter(suboptimalityFactor);
219 const auto edge = get(it).second;
221 edge.target->removeFromSourcesOfIncomingEdgesInForwardQueue(edge.source);
223 modifiedQueue_ =
true;
230 if (cacheQueueLookup_ && !modifiedQueue_)
232 return cachedMinEdgeEffort_;
235 unsigned int minEdgeEffort = std::numeric_limits<unsigned int>::max();
236 for (
auto it = queue_.cbegin(); it != queue_.cend(); ++it)
238 const auto edge = get(it).second;
240 if (edge.target->hasReverseVertex() || edge.target->hasForwardVertex())
245 if (edge.source->isWhitelisted(edge.target))
251 const unsigned int performedChecks = edge.target->getIncomingCollisionCheckResolution(edge.source);
252 const unsigned int fullSegmentCount =
253 space_->validSegmentCount(edge.source->raw(), edge.target->raw());
255 const unsigned int edgeEffort = fullSegmentCount - performedChecks;
257 if (edgeEffort < minEdgeEffort)
259 minEdgeEffort = edgeEffort;
262 if (minEdgeEffort == 0u)
264 cachedMinEdgeEffort_ = 0;
269 cachedMinEdgeEffort_ = minEdgeEffort;
270 return minEdgeEffort;
275 auto it = getLowerBoundCostEdge();
276 return get(it).first.lowerBoundCost;
281 return std::find_if(queue_.begin(), queue_.end(),
282 [reverseSearchTag](
const auto &edge)
284 auto &a = edge.second;
285 return a.second.target->asReverseVertex()->getExpandTag() != reverseSearchTag;
291 for (
const auto &element : queue_)
293 const auto &edge = element.second.second;
294 edge.target->resetSourcesOfIncomingEdgesInForwardQueue();
297 modifiedQueue_ =
true;
302 std::vector<Edge> edges;
303 edges.reserve(queue_.size());
304 for (
const auto &element : queue_)
306 const auto &edge = element.second.second;
307 edges.emplace_back(edge);
318 modifiedQueue_ =
true;
321 std::pair<ForwardQueue::EdgeKeys, Edge> ForwardQueue::makeElement(
const Edge &edge)
const
324 const auto lowerBoundCostOfEdge = lowerBoundCost(edge);
325 const auto estimatedCostOfEdge = estimateCost(edge);
328 return {{lowerBoundCostOfEdge, estimatedCostOfEdge, estimatedEffortOfEdge}, {edge.
source, edge.
target}};
331 ForwardQueue::Container::iterator ForwardQueue::getBestCostEstimateEdge()
334 return std::min_element(queue_.begin(), queue_.end(),
335 [
this](
const auto &a,
const auto &b)
337 const auto &aEdgeKey = a.second.first;
338 const auto &bEdgeKey = b.second.first;
339 return objective_->isCostBetterThan(aEdgeKey.estimatedCost,
340 bEdgeKey.estimatedCost);
344 ForwardQueue::Container::const_iterator ForwardQueue::getBestCostEstimateEdge()
const
347 return std::min_element(queue_.cbegin(), queue_.cend(),
348 [
this](
const auto &a,
const auto &b)
350 const auto &aEdgeKey = a.second.first;
351 const auto &bEdgeKey = b.second.first;
352 return objective_->isCostBetterThan(aEdgeKey.estimatedCost,
353 bEdgeKey.estimatedCost);
357 ForwardQueue::Container::iterator ForwardQueue::getLowerBoundCostEdge()
359 auto it = std::max_element(queue_.begin(), queue_.end(),
360 [
this](
const auto &a,
const auto &b)
362 const auto &aEdgeKey = a.second.first;
363 const auto &bEdgeKey = b.second.first;
364 return !objective_->isCostBetterThan(aEdgeKey.lowerBoundCost,
365 bEdgeKey.lowerBoundCost);
371 ForwardQueue::Container::const_iterator ForwardQueue::getLowerBoundCostEdge()
const
373 return std::max_element(queue_.cbegin(), queue_.cend(),
374 [
this](
const auto &a,
const auto &b)
376 const auto &aEdgeKey = a.second.first;
377 const auto &bEdgeKey = b.second.first;
378 return !objective_->isCostBetterThan(aEdgeKey.lowerBoundCost,
379 bEdgeKey.lowerBoundCost);
386 if (!std::isfinite(factor) || !objective_->isFinite(cost))
388 return objective_->infiniteCost();
398 unsigned int edgeEffort = 0u;
405 const unsigned int fullSegmentCount =
406 space_->validSegmentCount(edge.
source->raw(), edge.
target->raw());
409 const unsigned int performedChecks = edge.
target->getIncomingCollisionCheckResolution(edge.
source);
411 edgeEffort = fullSegmentCount - performedChecks;
415 if (std::numeric_limits<unsigned int>::max() - edgeEffort < edge.target->getEstimatedEffortToGo())
417 return std::numeric_limits<unsigned int>::max();
421 return edge.
target->getEstimatedEffortToGo() + edgeEffort;
426 return objective_->combineCosts(objective_->combineCosts(edge.source->getCurrentCostToCome(),
427 objective_->motionCostBestEstimate(
428 edge.source->raw(), edge.target->raw())),
429 edge.target->getEstimatedCostToGo());
434 return objective_->combineCosts(
435 objective_->combineCosts(edge.source->getCurrentCostToCome(),
436 objective_->motionCostHeuristic(edge.source->raw(), edge.target->raw())),
437 edge.target->getAdmissibleCostToGo());