39 #include <ompl/multilevel/planners/qrrt/QRRTStarImpl.h>
40 #include <ompl/multilevel/datastructures/PlannerDataVertexAnnotated.h>
41 #include <ompl/tools/config/SelfConfig.h>
42 #include <ompl/base/objectives/PathLengthOptimizationObjective.h>
43 #include <boost/foreach.hpp>
44 #include <boost/math/constants/constants.hpp>
45 #include "ompl/util/GeometricEquations.h"
48 #define foreach BOOST_FOREACH
50 ompl::multilevel::QRRTStarImpl::QRRTStarImpl(
const base::SpaceInformationPtr &si, BundleSpace *parent_)
54 Planner::declareParam<double>(
"useKNearest_",
this, &ompl::multilevel::QRRTStarImpl::setKNearest,
55 &ompl::multilevel::QRRTStarImpl::getKNearest,
"0,1");
57 symmetric_ =
getBundle()->getStateSpace()->hasSymmetricInterpolate();
59 setImportance(
"exponential");
61 setGraphSampler(
"randomvertex");
62 setMetric(
"geodesic");
65 ompl::multilevel::QRRTStarImpl::~QRRTStarImpl()
69 void ompl::multilevel::QRRTStarImpl::setup()
72 calculateRewiringLowerBounds();
74 void ompl::multilevel::QRRTStarImpl::clear()
77 goalConfigurations_.clear();
91 sampleBundleGoalBias(xRandom_->state);
94 Configuration *q_nearest = nearestDatastructure_->nearest(xRandom_);
97 Configuration *q_new = steerTowards_Range(q_nearest, xRandom_);
102 std::vector<Configuration *> nearestNbh;
103 getNearestNeighbors(q_new, nearestNbh);
106 q_new->
lineCost = getOptimizationObjectivePtr()->motionCost(q_nearest->state, q_new->state);
107 q_new->
cost = getOptimizationObjectivePtr()->combineCosts(q_nearest->
cost, q_new->
lineCost);
108 q_new->
parent = q_nearest;
113 std::vector<int> validNeighbor(nearestNbh.size(), 0);
116 std::vector<ompl::base::Cost> lineCosts;
120 lineCosts.resize(nearestNbh.size());
123 for (
unsigned int i = 0; i < nearestNbh.size(); i++)
127 if (q_near == q_nearest)
129 validNeighbor.at(i) = 1;
132 lineCosts[i] = cost_nearest;
136 validNeighbor.at(i) = 0;
138 ompl::base::Cost line_cost = getOptimizationObjectivePtr()->motionCost(q_near->state, q_new->state);
139 ompl::base::Cost new_cost = getOptimizationObjectivePtr()->combineCosts(q_near->
cost, line_cost);
143 lineCosts[i] = line_cost;
146 if (getOptimizationObjectivePtr()->isCostBetterThan(new_cost, q_new->
cost))
148 if ((!useKNearest_ || distance(q_near, q_new) < maxDistance_) &&
149 getBundle()->checkMotion(q_near->state, q_new->state))
152 q_new->
cost = new_cost;
154 validNeighbor.at(i) = 1;
157 validNeighbor.at(i) = -1;
161 addConfiguration(q_new);
164 bool checkForSolution =
false;
167 for (
unsigned int i = 0; i < nearestNbh.size(); i++)
171 if (q_near != q_new->
parent)
177 line_cost = lineCosts[i];
181 line_cost = getOptimizationObjectivePtr()->motionCost(q_new->state, q_near->state);
183 base::Cost new_cost = getOptimizationObjectivePtr()->combineCosts(q_new->
cost, line_cost);
187 if (getOptimizationObjectivePtr()->isCostBetterThan(new_cost, q_near->
cost))
189 bool valid = (validNeighbor.at(i) == 1);
191 if (validNeighbor.at(i) == 0)
193 valid = ((!useKNearest_ || distance(q_near, q_new) < maxDistance_) &&
194 getBundle()->checkMotion(q_new->state, q_near->state));
204 removeFromParent(q_near);
208 q_near->
cost = new_cost;
213 updateChildCosts(q_near);
214 checkForSolution =
true;
222 bool satisfied = pdef_->getGoal()->isSatisfied(q_new->state, &dist);
225 goalConfigurations_.push_back(q_new);
226 checkForSolution =
true;
229 if (checkForSolution)
231 bool updatedSolution =
false;
232 if (!goalConfigurations_.empty() && qGoal_ ==
nullptr)
235 bestCost_ = qGoal_->
cost;
236 updatedSolution =
true;
240 for (
unsigned int k = 0; k < goalConfigurations_.size(); k++)
244 if (getOptimizationObjectivePtr()->isCostBetterThan(qk->
cost, bestCost_))
247 bestCost_ = qGoal_->
cost;
248 updatedSolution =
true;
254 OMPL_INFORM(
"Found path with cost %f (level %d).", qGoal_->cost, getLevel());
261 void ompl::multilevel::QRRTStarImpl::updateChildCosts(
Configuration *q)
263 for (std::size_t i = 0; i < q->
children.size(); ++i)
265 q->
children.at(i)->cost = getOptimizationObjectivePtr()->combineCosts(q->
cost, q->
children.at(i)->lineCost);
266 updateChildCosts(q->
children.at(i));
270 void ompl::multilevel::QRRTStarImpl::removeFromParent(
Configuration *q)
282 bool ompl::multilevel::QRRTStarImpl::getSolution(base::PathPtr &solution)
286 solutionPath_ = std::make_shared<geometric::PathGeometric>(getBundle());
289 while (intermediate_node !=
nullptr)
291 std::static_pointer_cast<geometric::PathGeometric>(solutionPath_)->append(intermediate_node->state);
292 intermediate_node = intermediate_node->
parent;
294 std::static_pointer_cast<geometric::PathGeometric>(solutionPath_)->reverse();
295 solution = solutionPath_;
304 void ompl::multilevel::QRRTStarImpl::getNearestNeighbors(
Configuration *x, std::vector<Configuration *> &nearest)
306 auto cardDbl =
static_cast<double>(nearestDatastructure_->size() + 1u);
310 unsigned int k = std::ceil(k_rrt_Constant_ *
log(cardDbl));
311 nearestDatastructure_->nearestK(x, k, nearest);
315 double r = std::min(maxDistance_, r_rrt_Constant_ * std::pow(
log(cardDbl) / cardDbl, 1 / d_));
316 nearestDatastructure_->nearestR(x, r, nearest);
320 void ompl::multilevel::QRRTStarImpl::calculateRewiringLowerBounds()
322 d_ = (double)getBundle()->getStateDimension();
323 double e = boost::math::constants::e<double>();
325 k_rrt_Constant_ = std::pow(2, d_ + 1) * e * (1.0 + 1.0 / d_);
328 std::pow(2 * (1.0 + 1.0 / d_) * (getBundle()->getSpaceMeasure() /
unitNBallMeasure(d_)), 1.0 / d_);
331 void ompl::multilevel::QRRTStarImpl::getPlannerData(base::PlannerData &data)
const
333 multilevel::PlannerDataVertexAnnotated pstart(qStart_->state);
334 pstart.setLevel(getLevel());
335 data.addStartVertex(pstart);
339 multilevel::PlannerDataVertexAnnotated pgoal(qGoal_->state);
340 pgoal.setLevel(getLevel());
341 data.addGoalVertex(pgoal);
344 std::vector<Configuration *> motions;
345 if (nearestDatastructure_)
346 nearestDatastructure_->list(motions);
352 multilevel::PlannerDataVertexAnnotated p1(q->
parent->state);
353 multilevel::PlannerDataVertexAnnotated p2(q->state);
354 p1.setLevel(getLevel());
355 p2.setLevel(getLevel());
356 data.addEdge(p1, p2);
360 OMPL_DEBUG(
"Tree (level %d) has %d/%d vertices/edges", getLevel(), motions.size(), motions.size() - 1);