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_)
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();
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);
383 ompl::base::Cost ForwardQueue::inflateCost(
const ompl::base::Cost &cost,
double factor)
const
386 if (!std::isfinite(factor) || !objective_->isFinite(cost))
388 return objective_->infiniteCost();
392 return ompl::base::Cost(cost.
value() * factor);
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;
429 edge.
target->getEstimatedCostToGo());
435 objective_->
combineCosts(edge.source->getCurrentCostToCome(),
437 edge.target->getAdmissibleCostToGo());
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
double value() const
The value of the cost.
virtual Cost motionCostHeuristic(const State *s1, const State *s2) const
Defines an admissible estimate on the optimal cost on the motion between states s1 and s2....
virtual Cost combineCosts(Cost c1, Cost c2) const
Get the cost that corresponds to combining the costs c1 and c2. Default implementation defines this c...
virtual bool isCostBetterThan(Cost c1, Cost c2) const
Check whether the the cost c1 is considered better than the cost c2. By default, this returns true if...
virtual Cost motionCostBestEstimate(const State *s1, const State *s2) const
Defines a possibly inadmissible estimate on the optimal cost on the motion between states s1 and s2....
virtual Cost infiniteCost() const
Get a cost which is greater than all other costs in this OptimizationObjective; required for use in D...
void clear()
Clears the queue, i.e., deletes all elements from it.
void updateIfExists(const Edge &edge)
Update an edge in the queue. Does nothing if the edge is not in the queue.
bool empty() const
Returns whether the queue is empty.
std::vector< Edge > getEdges() const
Copies all edges into a vector and returns the vector.
bool containsOpenTargets(std::size_t reverseSearchTag) const
Returns whether the queue contains edges with targets that are open or unconnected in the reverse sea...
ompl::base::Cost getLowerBoundOnOptimalSolutionCost() const
Returns a lower bound on the resolution-optimal solution cost.
void remove(const Edge &edge)
Removes an edge from the queue. Throws if the edge is not in the queue.
std::size_t estimateEffort(const Edge &edge) const
Estimates the effort that remains to validate a solution through an edge.
std::size_t size() const
Returns how many elements are in the queue.
void insertOrUpdate(const Edge &edge)
Inserts or updates an edge in the queue.
Edge peek(double suboptimalityFactor)
Returns a copy to the next edge.
unsigned int getMinEffortToCome() const
Returns the minimum effort that remains.
Edge pop(double suboptimalityFactor)
Returns and deletes the top element of the queue.
void rebuild()
Rebuilds the queue.
ForwardQueue(const std::shared_ptr< const ompl::base::OptimizationObjective > &objective, const std::shared_ptr< const ompl::base::StateSpace > &space)
Constructs the queue given the objective and state space.
This namespace contains code that is specific to planning under geometric constraints.
Main namespace. Contains everything in this library.
A struct for basic edge data.
std::shared_ptr< State > source
The parent state of this edge.
std::shared_ptr< State > target
The child state of this edge.