37 #include "ompl/geometric/planners/sbl/pSBL.h"
38 #include "ompl/base/goals/GoalState.h"
39 #include "ompl/tools/config/SelfConfig.h"
43 ompl::geometric::pSBL::pSBL(
const base::SpaceInformationPtr &si) : base::Planner(si,
"pSBL"),
50 connectionPoint_ = std::make_pair<base::State*, base::State*>(
nullptr,
nullptr);
56 ompl::geometric::pSBL::~pSBL()
68 tStart_.grid.setDimension(projectionEvaluator_->getDimension());
69 tGoal_.grid.setDimension(projectionEvaluator_->getDimension());
76 samplerArray_.clear();
88 removeList_.motions.clear();
89 connectionPoint_ = std::make_pair<base::State*, base::State*>(
nullptr,
nullptr);
96 for (
unsigned int i = 0 ; i < it->second->data.size() ; ++i)
98 if (it->second->data[i]->state)
99 si_->freeState(it->second->data[i]->state);
100 delete it->second->data[i];
105 void ompl::geometric::pSBL::threadSolve(
unsigned int tid,
const base::PlannerTerminationCondition &ptc, SolutionInfo *sol)
109 std::vector<Motion*> solution;
110 base::State *xstate = si_->allocState();
111 bool startTree = rng.uniformBool();
113 while (!sol->found && ptc ==
false)
116 while (retry && !sol->found && ptc ==
false)
118 removeList_.lock.lock();
119 if (!removeList_.motions.empty())
121 if (loopLock_.try_lock())
124 std::map<Motion*, bool> seen;
125 for (
unsigned int i = 0 ; i < removeList_.motions.size() ; ++i)
126 if (seen.find(removeList_.motions[i].motion) == seen.end())
127 removeMotion(*removeList_.motions[i].tree, removeList_.motions[i].motion, seen);
128 removeList_.motions.clear();
134 removeList_.lock.unlock();
137 if (sol->found || ptc)
140 loopLockCounter_.lock();
141 if (loopCounter_ == 0)
144 loopLockCounter_.unlock();
147 TreeData &tree = startTree ? tStart_ : tGoal_;
148 startTree = !startTree;
149 TreeData &otherTree = startTree ? tStart_ : tGoal_;
151 Motion *existing = selectMotion(rng, tree);
152 if (!samplerArray_[tid]->sampleNear(xstate, existing->state, maxDistance_))
156 Motion *motion =
new Motion(si_);
157 si_->copyState(motion->state, xstate);
158 motion->parent = existing;
159 motion->root = existing->root;
161 existing->lock.lock();
162 existing->children.push_back(motion);
163 existing->lock.unlock();
165 addMotion(tree, motion);
167 if (checkSolution(rng, !startTree, tree, otherTree, motion, solution))
173 PathGeometric *path =
new PathGeometric(si_);
174 for (
unsigned int i = 0 ; i < solution.size() ; ++i)
175 path->append(solution[i]->state);
176 pdef_->addSolutionPath(base::PathPtr(path),
false, 0.0, getName());
182 loopLockCounter_.lock();
184 if (loopCounter_ == 0)
186 loopLockCounter_.unlock();
189 si_->freeState(xstate);
200 OMPL_ERROR(
"%s: Unknown type of goal", getName().c_str());
207 si_->copyState(motion->state, st);
208 motion->valid =
true;
209 motion->root = motion->state;
210 addMotion(tStart_, motion);
213 if (tGoal_.size == 0)
215 if (si_->satisfiesBounds(goal->
getState()) && si_->isValid(goal->
getState()))
218 si_->copyState(motion->state, goal->
getState());
219 motion->valid =
true;
220 motion->root = motion->state;
221 addMotion(tGoal_, motion);
224 OMPL_ERROR(
"%s: Goal state is invalid!", getName().c_str());
227 if (tStart_.size == 0)
229 OMPL_ERROR(
"%s: Motion planning start tree could not be initialized!", getName().c_str());
232 if (tGoal_.size == 0)
234 OMPL_ERROR(
"%s: Motion planning goal tree could not be initialized!", getName().c_str());
238 samplerArray_.resize(threadCount_);
240 OMPL_INFORM(
"%s: Starting planning with %d states already in datastructure", getName().c_str(), (
int)(tStart_.size + tGoal_.size));
246 std::vector<std::thread*> th(threadCount_);
247 for (
unsigned int i = 0 ; i < threadCount_ ; ++i)
248 th[i] =
new std::thread(std::bind(&pSBL::threadSolve,
this, i, ptc, &sol));
249 for (
unsigned int i = 0 ; i < threadCount_ ; ++i)
255 OMPL_INFORM(
"%s: Created %u (%u start + %u goal) states in %u cells (%u start + %u goal)",
256 getName().c_str(), tStart_.size + tGoal_.size, tStart_.size, tGoal_.size,
257 tStart_.grid.size() + tGoal_.grid.size(), tStart_.grid.size(), tGoal_.grid.size());
262 bool ompl::geometric::pSBL::checkSolution(
RNG &rng,
bool start, TreeData &tree, TreeData &otherTree, Motion *motion, std::vector<Motion*> &solution)
265 projectionEvaluator_->computeCoordinates(motion->state, coord);
267 otherTree.lock.lock();
270 if (cell && !cell->
data.empty())
273 otherTree.lock.unlock();
275 if (pdef_->getGoal()->isStartGoalPairValid(start ? motion->root : connectOther->root, start ? connectOther->root : motion->root))
277 Motion *connect =
new Motion(si_);
279 si_->copyState(connect->state, connectOther->state);
280 connect->parent = motion;
281 connect->root = motion->root;
284 motion->children.push_back(connect);
285 motion->lock.unlock();
287 addMotion(tree, connect);
289 if (isPathValid(tree, connect) && isPathValid(otherTree, connectOther))
292 connectionPoint_ = std::make_pair(motion->state, connectOther->state);
294 connectionPoint_ = std::make_pair(connectOther->state, motion->state);
298 std::vector<Motion*> mpath1;
299 while (motion !=
nullptr)
301 mpath1.push_back(motion);
302 motion = motion->parent;
305 std::vector<Motion*> mpath2;
306 while (connectOther !=
nullptr)
308 mpath2.push_back(connectOther);
309 connectOther = connectOther->parent;
315 for (
int i = mpath1.size() - 1 ; i >= 0 ; --i)
316 solution.push_back(mpath1[i]);
317 solution.insert(solution.end(), mpath2.begin(), mpath2.end());
324 otherTree.lock.unlock();
329 bool ompl::geometric::pSBL::isPathValid(TreeData &tree, Motion *motion)
331 std::vector<Motion*> mpath;
334 while (motion !=
nullptr)
336 mpath.push_back(motion);
337 motion = motion->parent;
343 for (
int i = mpath.size() - 1 ; result && i >= 0 ; --i)
345 mpath[i]->lock.lock();
346 if (!mpath[i]->valid)
348 if (si_->checkMotion(mpath[i]->parent->state, mpath[i]->state))
349 mpath[i]->valid =
true;
353 PendingRemoveMotion prm;
355 prm.motion = mpath[i];
356 removeList_.lock.lock();
357 removeList_.motions.push_back(prm);
358 removeList_.lock.unlock();
362 mpath[i]->lock.unlock();
371 GridCell* cell = tree.pdf.sample(rng.uniform01());
372 Motion *result = cell && !cell->
data.empty() ? cell->data[rng.uniformInt(0, cell->data.size() - 1)] :
nullptr;
377 void ompl::geometric::pSBL::removeMotion(TreeData &tree, Motion *motion, std::map<Motion*, bool> &seen)
382 Grid<MotionInfo>::Coord coord;
383 projectionEvaluator_->computeCoordinates(motion->state, coord);
384 Grid<MotionInfo>::Cell* cell = tree.grid.
getCell(coord);
387 for (
unsigned int i = 0 ; i < cell->data.size(); ++i)
388 if (cell->data[i] == motion)
390 cell->data.erase(cell->data.begin() + i);
394 if (cell->data.empty())
396 tree.pdf.remove(cell->data.elem_);
397 tree.grid.remove(cell);
398 tree.grid.destroyCell(cell);
402 tree.pdf.update(cell->data.elem_, 1.0/cell->data.size());
410 for (
unsigned int i = 0 ; i < motion->parent->children.size() ; ++i)
411 if (motion->parent->children[i] == motion)
413 motion->parent->children.erase(motion->parent->children.begin() + i);
419 for (
unsigned int i = 0 ; i < motion->children.size() ; ++i)
421 motion->children[i]->parent =
nullptr;
422 removeMotion(tree, motion->children[i], seen);
426 si_->freeState(motion->state);
430 void ompl::geometric::pSBL::addMotion(TreeData &tree, Motion *motion)
432 Grid<MotionInfo>::Coord coord;
433 projectionEvaluator_->computeCoordinates(motion->state, coord);
435 Grid<MotionInfo>::Cell* cell = tree.grid.getCell(coord);
438 cell->data.push_back(motion);
439 tree.pdf.update(cell->data.elem_, 1.0/cell->data.size());
443 cell = tree.grid.createCell(coord);
444 cell->data.push_back(motion);
446 cell->data.elem_ = tree.pdf.add(cell, 1.0);
454 Planner::getPlannerData(data);
456 std::vector<MotionInfo> motions;
457 tStart_.grid.getContent(motions);
459 for (
unsigned int i = 0 ; i < motions.size() ; ++i)
460 for (
unsigned int j = 0 ; j < motions[i].size() ; ++j)
461 if (motions[i][j]->parent ==
nullptr)
468 tGoal_.grid.getContent(motions);
469 for (
unsigned int i = 0 ; i < motions.size() ; ++i)
470 for (
unsigned int j = 0 ; j < motions[i].size() ; ++j)
471 if (motions[i][j]->parent ==
nullptr)
483 assert(nthreads > 0);
484 threadCount_ = nthreads;
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Representation of a simple grid.
void setThreadCount(unsigned int nthreads)
Set the number of threads the planner should use. Default is 2.
The planner failed to find a solution.
GoalType recognizedGoal
The type of goal specification the planner can use.
std::vector< int > Coord
Definition of a coordinate within this grid.
const State * getState() const
Get the goal state.
Definition of a goal state.
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...
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
_T data
The data we store in the cell.
bool multithreaded
Flag indicating whether multiple threads are used in the computation of the planner.
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Invalid start state or no start state specified.
virtual base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
Function that can solve the motion planning problem. This function can be called multiple times on th...
Cell * getCell(const Coord &coord) const
Get the cell at a specified coordinate.
virtual void clear()
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
Random number generation. An instance of this class cannot be used by multiple threads at once (membe...
The goal is of a type that a planner does not recognize.
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
The planner found an exact solution.
unsigned int vertexIndex(const PlannerDataVertex &v) const
Return the index for the vertex associated with the given data. INVALID_INDEX is returned if this ver...
A class to store the exit status of Planner::solve()
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...
iterator end() const
Return the end() iterator for the grid.
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...
Definition of an abstract state.
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition of a cell in this grid.
std::pair< base::State *, base::State * > connectionPoint_
The pair of states in each tree connected during planning. Used for PlannerData computation.
iterator begin() const
Return the begin() iterator for the grid.
This bit is set if casting to goal state (ompl::base::GoalState) is possible.
unsigned int getThreadCount() const
Get the thread count.
virtual void getPlannerData(base::PlannerData &data) const
Get information about the current run of the motion planner. Repeated calls to this function will upd...
void setRange(double distance)
Set the range the planner is supposed to use.
virtual void setup()
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
int uniformInt(int lower_bound, int upper_bound)
Generate a random integer within given bounds: [lower_bound, upper_bound].
double maxDistance_
The maximum length of a motion to be added in the tree.
double getRange() const
Get the range the planner is using.
CoordHash::const_iterator iterator
We only allow const iterators.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.