LightningRetrieveRepair.cpp
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2014, University of Colorado, Boulder
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Univ of CO, Boulder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman */
36 
37 #include "ompl/geometric/planners/experience/LightningRetrieveRepair.h"
38 #include "ompl/geometric/planners/rrt/RRTConnect.h"
39 #include "ompl/base/goals/GoalState.h"
40 #include "ompl/base/goals/GoalSampleableRegion.h"
41 #include "ompl/tools/config/SelfConfig.h"
42 #include "ompl/tools/config/MagicConstants.h"
43 #include "ompl/tools/lightning/LightningDB.h"
44 
45 #include <thread>
46 
47 #include <limits>
48 
50  const ompl::tools::LightningDBPtr &experienceDB)
51  : base::Planner(si, "LightningRetrieveRepair"),
52  experienceDB_(experienceDB),
53  nearestK_(ompl::magic::NEAREST_K_RECALL_SOLUTIONS) // default value
54 {
56  specs_.directed = true;
57 
58  // Repair Planner Specific:
60 
62 }
63 
64 ompl::geometric::LightningRetrieveRepair::~LightningRetrieveRepair()
65 {
66 }
67 
69 {
70  Planner::clear();
71 
72  // Clear the inner planner
73  if (repairPlanner_)
74  repairPlanner_->clear();
75 }
76 
77 void ompl::geometric::LightningRetrieveRepair::setLightningDB(const ompl::tools::LightningDBPtr &experienceDB)
78 {
79  experienceDB_ = experienceDB;
80 }
81 
83 {
84  if (planner && planner->getSpaceInformation().get() != si_.get())
85  throw Exception("LightningRetrieveRepair: Repair planner instance does not match space information");
86  repairPlanner_ = planner;
87  setup_ = false;
88 }
89 
91 {
92  Planner::setup();
93 
94  // Setup repair planner (for use by the rrPlanner)
95  // Note: does not use the same pdef as the main planner in this class
96  if (!repairPlanner_)
97  {
98  // Set the repair planner
99  repairPlanner_.reset(new ompl::geometric::RRTConnect(si_));
100  OMPL_DEBUG("LightningRetrieveRepair: No repairing planner specified. Using default: %s", repairPlanner_->getName().c_str() );
101  }
102 
103  // Setup the problem definition for the repair planner
104  repairProblemDef_->setOptimizationObjective(pdef_->getOptimizationObjective()); // copy primary problem def
105 
106  // Setup repair planner
107  repairPlanner_->setProblemDefinition(repairProblemDef_);
108  if (!repairPlanner_->isSetup())
109  repairPlanner_->setup();
110 }
111 
113 {
114  bool solved = false;
115 
116  // Check if the database is empty
117  if (!experienceDB_->getExperiencesCount())
118  {
119  OMPL_INFORM("LightningRetrieveRepair: Experience database is empty so unable to run LightningRetrieveRepair algorithm.");
121  }
122 
123  // Restart the Planner Input States so that the first start and goal state can be fetched
124  pis_.restart();
125 
126  // Get a single start state TODO: more than one
127  const base::State *startState = pis_.nextStart();
128  const base::State *goalState = pis_.nextGoal(ptc);
129 
130  // Error check start/goal states
131  if (!startState || !goalState)
132  {
133  OMPL_ERROR("LightningRetrieveRepair: Start or goal states are null");
135  }
136 
137  // Search for previous solution in database
138  nearestPaths_ = experienceDB_->findNearestStartGoal(nearestK_, startState, goalState);
139 
140  // Check if there are any solutions
141  if (nearestPaths_.empty())
142  {
143  OMPL_INFORM("LightningRetrieveRepair: No similar path founds in nearest neighbor tree, unable to retrieve repair");
144  return base::PlannerStatus::TIMEOUT; // The planner failed to find a solution
145  }
146 
147  ompl::base::PlannerDataPtr chosenPath;
148 
149  // Filter top n paths to 1
150  // TODO Rather than selecting 1 best path, you could also spawn n (n<=k) threads and repair the top n paths.
151  if (!findBestPath(startState, goalState, chosenPath))
152  {
154  }
155 
156  // All saved trajectories should be at least 2 states long
157  assert(chosenPath->numVertices() >= 2);
158 
159  // Convert chosen PlannerData experience to an actual path
160  ompl::geometric::PathGeometric *primaryPath = new PathGeometric(si_);
161  // Add start
162  primaryPath->append(startState);
163  // Add old states
164  for (std::size_t i = 0; i < chosenPath->numVertices(); ++i)
165  {
166  primaryPath->append(chosenPath->getVertex(i).getState());
167  }
168  // Add goal
169  primaryPath->append(goalState);
170 
171  // All save trajectories should be at least 2 states long, and then we append the start and goal states
172  assert(primaryPath->getStateCount() >= 4);
173 
174  // Repair chosen path
175  if (!repairPath(ptc, *primaryPath))
176  {
177  OMPL_INFORM("LightningRetrieveRepair: repairPath failed or aborted");
179  }
180 
181  // Smooth the result
182  OMPL_INFORM("LightningRetrieveRepair solve: Simplifying solution (smoothing)...");
183  time::point simplifyStart = time::now();
184  std::size_t numStates = primaryPath->getStateCount();
185  psk_->simplify(*primaryPath, ptc);
186  double simplifyTime = time::seconds(time::now() - simplifyStart);
187  OMPL_INFORM("LightningRetrieveRepair: Path simplification took %f seconds and removed %d states",
188  simplifyTime, numStates - primaryPath->getStateCount());
189 
190  // Finished
191  pdef_->addSolutionPath(base::PathPtr(primaryPath), false, 0., getName());
192  solved = true;
193  return base::PlannerStatus(solved, false);
194 }
195 
197 {
198  OMPL_INFORM("LightningRetrieveRepair: Found %d similar paths. Filtering", nearestPaths_.size());
199 
200  // Filter down to just 1 chosen path
201  ompl::base::PlannerDataPtr bestPath = nearestPaths_.front();
202  std::size_t bestPathScore = std::numeric_limits<std::size_t>::max();
203 
204  // Track which path has the shortest distance
205  std::vector<double> distances(nearestPaths_.size(), 0);
206  std::vector<bool> isReversed(nearestPaths_.size());
207 
208  assert(isReversed.size() == nearestPaths_.size());
209 
210  for (std::size_t pathID = 0; pathID < nearestPaths_.size(); ++pathID)
211  {
212  const ompl::base::PlannerDataPtr &currentPath = nearestPaths_[pathID];
213 
214  // Error check
215  if (currentPath->numVertices() < 2) // needs at least a start and a goal
216  {
217  OMPL_ERROR("A path was recalled that somehow has less than 2 vertices, which shouldn't happen");
218  return false;
219  }
220 
221  const ompl::base::State *pathStartState = currentPath->getVertex(0).getState();
222  const ompl::base::State *pathGoalState = currentPath->getVertex(currentPath->numVertices()-1).getState();
223 
224  double regularDistance = si_->distance(startState,pathStartState) + si_->distance(goalState,pathGoalState);
225  double reversedDistance = si_->distance(startState,pathGoalState) + si_->distance(goalState,pathStartState);
226 
227  // Check if path is reversed from normal [start->goal] direction and cache the distance
228  if ( regularDistance > reversedDistance )
229  {
230  // The distance between starts and goals is less when in reverse
231  isReversed[pathID] = true;
232  distances[pathID] = reversedDistance;
233  // We won't actually flip it until later to save memory operations and not alter our NN tree in the LightningDB
234  }
235  else
236  {
237  isReversed[pathID] = false;
238  distances[pathID] = regularDistance;
239  }
240 
241  std::size_t pathScore = 0; // the score
242 
243  // Check the validity between our start location and the path's start
244  // TODO: this might bias the score to be worse for the little connecting segment
245  if (!isReversed[pathID])
246  pathScore += checkMotionScore(startState, pathStartState);
247  else
248  pathScore += checkMotionScore(startState, pathGoalState);
249 
250  // Score current path for validity
251  std::size_t invalidStates = 0;
252  for (std::size_t vertex_id = 0; vertex_id < currentPath->numVertices(); ++vertex_id)
253  {
254  // Check if the sampled points are valid
255  if (!si_->isValid( currentPath->getVertex(vertex_id).getState()))
256  {
257  invalidStates++;
258  }
259  }
260  // Track separate for debugging
261  pathScore += invalidStates;
262 
263  // Check the validity between our goal location and the path's goal
264  // TODO: this might bias the score to be worse for the little connecting segment
265  if (!isReversed[pathID])
266  pathScore += checkMotionScore( goalState, pathGoalState );
267  else
268  pathScore += checkMotionScore( goalState, pathStartState );
269 
270  // Factor in the distance between start/goal and our new start/goal
271  OMPL_INFORM("LightningRetrieveRepair: Path %d | %d verticies | %d invalid | score %d | reversed: %s | distance: %f",
272  int(pathID), currentPath->numVertices(), invalidStates, pathScore,
273  isReversed[pathID] ? "true" : "false", distances[pathID]);
274 
275  // Check if we have a perfect score (0) and this is the shortest path (the first one)
276  if (pathID == 0 && pathScore == 0)
277  {
278  OMPL_DEBUG("LightningRetrieveRepair: --> The shortest path (path 0) has a perfect score (0), ending filtering early.");
279  bestPathScore = pathScore;
280  bestPath = currentPath;
281  nearestPathsChosenID_ = pathID;
282  break; // end the for loop
283  }
284 
285  // Check if this is the best score we've seen so far
286  if (pathScore < bestPathScore)
287  {
288  OMPL_DEBUG("LightningRetrieveRepair: --> This path is the best we've seen so far. Previous best: %d", bestPathScore);
289  bestPathScore = pathScore;
290  bestPath = currentPath;
291  nearestPathsChosenID_ = pathID;
292  }
293  // if the best score is the same as a previous one we've seen,
294  // choose the one that has the shortest connecting component
295  else if (pathScore == bestPathScore && distances[nearestPathsChosenID_] > distances[pathID])
296  {
297  // This new path is a shorter distance
298  OMPL_DEBUG("LightningRetrieveRepair: --> This path is as good as the best we've seen so far, but its path is shorter. Previous best score: %d from index %d",
299  bestPathScore, nearestPathsChosenID_);
300  bestPathScore = pathScore;
301  bestPath = currentPath;
302  nearestPathsChosenID_ = pathID;
303  }
304  else
305  OMPL_DEBUG("LightningRetrieveRepair: --> Not best. Best score: %d from index %d", bestPathScore, nearestPathsChosenID_);
306  }
307 
308  // Check if we have a solution
309  if (!bestPath)
310  {
311  OMPL_ERROR("LightningRetrieveRepair: No best path found from k filtered paths");
312  return false;
313  }
314  else if(!bestPath->numVertices() || bestPath->numVertices() == 1)
315  {
316  OMPL_ERROR("LightningRetrieveRepair: Only %d verticies found in PlannerData loaded from file. This is a bug.", bestPath->numVertices());
317  return false;
318  }
319 
320  // Reverse the path if necessary. We allocate memory for this so that we don't alter the database
321  if (isReversed[nearestPathsChosenID_])
322  {
323  OMPL_DEBUG("LightningRetrieveRepair: Reversing planner data verticies count %d", bestPath->numVertices());
325  for (std::size_t i = bestPath->numVertices(); i > 0; --i) // size_t can't go negative so subtract 1 instead
326  {
327  newPath->addVertex( bestPath->getVertex(i-1) );
328  }
329  // Set result
330  chosenPath = newPath;
331  }
332  else
333  {
334  // Set result
335  chosenPath = bestPath;
336  }
337  OMPL_DEBUG("LightningRetrieveRepair: Done Filtering\n");
338 
339  return true;
340 }
341 
343  ompl::geometric::PathGeometric &primaryPath)
344 {
345  // \todo: we should reuse our collision checking from the previous step to make this faster
346 
347  OMPL_INFORM("LightningRetrieveRepair: Repairing path");
348 
349  // Error check
350  if (primaryPath.getStateCount() < 2)
351  {
352  OMPL_ERROR("LightningRetrieveRepair: Cannot repair a path with less than 2 states");
353  return false;
354  }
355 
356  // Loop through every pair of states and make sure path is valid.
357  // If not, replan between those states
358  for (std::size_t toID = 1; toID < primaryPath.getStateCount(); ++toID)
359  {
360  std::size_t fromID = toID - 1; // this is our last known valid state
361  ompl::base::State *fromState = primaryPath.getState(fromID);
362  ompl::base::State *toState = primaryPath.getState(toID);
363 
364  // Check if our planner is out of time
365  if (ptc == true)
366  {
367  OMPL_DEBUG("LightningRetrieveRepair: Repair path function interrupted because termination condition is true.");
368  return false;
369  }
370 
371  // Check path between states
372  if (!si_->checkMotion(fromState, toState))
373  {
374  // Path between (from, to) states not valid, but perhaps to STATE is
375  // Search until next valid STATE is found in existing path
376  std::size_t subsearchID = toID;
377  ompl::base::State *new_to;
378  OMPL_DEBUG("LightningRetrieveRepair: Searching for next valid state, because state %d to %d was not valid out %d total states",
379  fromID,toID,primaryPath.getStateCount());
380  while (subsearchID < primaryPath.getStateCount())
381  {
382  new_to = primaryPath.getState(subsearchID);
383  if (si_->isValid(new_to))
384  {
385  OMPL_DEBUG("LightningRetrieveRepair: State %d was found to valid, we can now repair between states", subsearchID);
386  // This future state is valid, we can stop searching
387  toID = subsearchID;
388  toState = new_to;
389  break;
390  }
391  ++subsearchID; // keep searching for a new state to plan to
392  }
393  // Check if we ever found a next state that is valid
394  if (subsearchID >= primaryPath.getStateCount())
395  {
396  // We never found a valid state to plan to, instead we reached the goal state and it too wasn't valid. This is bad.
397  // I think this is a bug.
398  OMPL_ERROR("LightningRetrieveRepair: No state was found valid in the remainder of the path. Invalid goal state. This should not happen.");
399  return false;
400  }
401 
402  // Plan between our two valid states
403  PathGeometric newPathSegment(si_);
404 
405  // Not valid motion, replan
406  OMPL_DEBUG("LightningRetrieveRepair: Planning from %d to %d", fromID, toID);
407 
408  if (!replan(fromState, toState, newPathSegment, ptc))
409  {
410  OMPL_INFORM("LightningRetrieveRepair: Unable to repair path between state %d and %d", fromID, toID);
411  return false;
412  }
413 
414  // TODO make sure not approximate solution
415 
416  // Reference to the path
417  std::vector<base::State*> &primaryPathStates = primaryPath.getStates();
418 
419 
420  // Remove all invalid states between (fromID, toID) - not including those states themselves
421  while (fromID != toID - 1)
422  {
423  OMPL_INFORM("LightningRetrieveRepair: Deleting state %d", fromID + 1);
424  primaryPathStates.erase(primaryPathStates.begin() + fromID + 1);
425  --toID; // because vector has shrunk
426  OMPL_INFORM("LightningRetrieveRepair: toID is now %d", toID);
427  }
428 
429  // Insert new path segment into current path
430  OMPL_DEBUG("LightningRetrieveRepair: Inserting new %d states into old path. Previous length: %d",
431  newPathSegment.getStateCount()-2, primaryPathStates.size());
432 
433  // Note: skip first and last states because they should be same as our start and goal state, same as `fromID` and `toID`
434  for (std::size_t i = 1; i < newPathSegment.getStateCount() - 1; ++i)
435  {
436  std::size_t insertLocation = toID + i - 1;
437  OMPL_DEBUG("LightningRetrieveRepair: Inserting newPathSegment state %d into old path at position %d",
438  i, insertLocation);
439  primaryPathStates.insert(primaryPathStates.begin() + insertLocation,
440  si_->cloneState(newPathSegment.getStates()[i]) );
441  }
442  OMPL_DEBUG("LightningRetrieveRepair: Inserted new states into old path. New length: %d", primaryPathStates.size());
443 
444  // Set the toID to jump over the newly inserted states to the next unchecked state. Subtract 2 because we ignore start and goal
445  toID = toID + newPathSegment.getStateCount() - 2;
446  OMPL_DEBUG("LightningRetrieveRepair: Continuing searching at state %d", toID);
447  }
448  }
449 
450  OMPL_INFORM("LightningRetrieveRepair: Done repairing");
451 
452  return true;
453 }
454 
456  PathGeometric &newPathSegment, const base::PlannerTerminationCondition &ptc)
457 {
458  // Reset problem definition
459  repairProblemDef_->clearSolutionPaths();
460  repairProblemDef_->clearStartStates();
461  repairProblemDef_->clearGoal();
462 
463  // Reset planner
464  repairPlanner_->clear();
465 
466  // Configure problem definition
467  repairProblemDef_->setStartAndGoalStates(start, goal);
468 
469  // Configure planner
470  repairPlanner_->setProblemDefinition(repairProblemDef_);
471 
472  // Solve
473  OMPL_INFORM("LightningRetrieveRepair: Preparing to repair path");
475  time::point startTime = time::now();
476 
477  lastStatus = repairPlanner_->solve(ptc);
478 
479  // Results
480  double planTime = time::seconds(time::now() - startTime);
481  if (!lastStatus)
482  {
483  OMPL_INFORM("LightningRetrieveRepair: No replan solution between disconnected states found after %f seconds", planTime);
484  return false;
485  }
486 
487  // Check if approximate
488  if (repairProblemDef_->hasApproximateSolution() || repairProblemDef_->getSolutionDifference() > std::numeric_limits<double>::epsilon())
489  {
490  OMPL_INFORM("LightningRetrieveRepair: Solution is approximate, not using");
491  return false;
492  }
493 
494  // Convert solution into a PathGeometric path
495  base::PathPtr p = repairProblemDef_->getSolutionPath();
496  if (!p)
497  {
498  OMPL_ERROR("LightningRetrieveRepair: Unable to get solution path from problem definition");
499  return false;
500  }
501 
502  newPathSegment = static_cast<ompl::geometric::PathGeometric&>(*p);
503 
504  // Smooth the result
505  OMPL_INFORM("LightningRetrieveRepair: Simplifying solution (smoothing)...");
506  time::point simplifyStart = time::now();
507  std::size_t numStates = newPathSegment.getStateCount();
508  psk_->simplify(newPathSegment, ptc);
509  double simplifyTime = time::seconds(time::now() - simplifyStart);
510  OMPL_INFORM("LightningRetrieveRepair: Path simplification took %f seconds and removed %d states",
511  simplifyTime, numStates - newPathSegment.getStateCount());
512 
513  // Save the planner data for debugging purposes
514  repairPlannerDatas_.push_back(ompl::base::PlannerDataPtr( new ompl::base::PlannerData(si_) ));
515  repairPlanner_->getPlannerData( *repairPlannerDatas_.back() );
516  repairPlannerDatas_.back()->decoupleFromPlanner(); // copy states so that when planner unloads/clears we don't lose them
517 
518  // Return success
519  OMPL_INFORM("LightningRetrieveRepair: solution found in %f seconds with %d states",
520  planTime, newPathSegment.getStateCount() );
521 
522  return true;
523 }
524 
526 {
527  OMPL_INFORM("LightningRetrieveRepair: including %d similar paths", nearestPaths_.size());
528 
529  // Visualize the n candidate paths that we recalled from the database
530  for (std::size_t i = 0 ; i < nearestPaths_.size() ; ++i)
531  {
532  ompl::base::PlannerDataPtr pd = nearestPaths_[i];
533  for (std::size_t j = 1; j < pd->numVertices(); ++j)
534  {
535  data.addEdge(
536  base::PlannerDataVertex(pd->getVertex(j - 1).getState()),
537  base::PlannerDataVertex(pd->getVertex(j).getState()));
538  }
539  }
540 }
541 
542 const std::vector<ompl::base::PlannerDataPtr>& ompl::geometric::LightningRetrieveRepair::getLastRecalledNearestPaths() const
543 {
544  return nearestPaths_; // list of candidate paths
545 }
546 
548 {
549  return nearestPathsChosenID_; // of the candidate paths list, the one we chose
550 }
551 
553 {
554  return nearestPaths_[nearestPathsChosenID_];
555 }
556 
557 void ompl::geometric::LightningRetrieveRepair::getRepairPlannerDatas(std::vector<base::PlannerDataPtr> &data) const
558 {
559  data = repairPlannerDatas_;
560 }
561 
563 {
564  int segmentCount = si_->getStateSpace()->validSegmentCount(s1, s2);
565 
566  std::size_t invalidStatesScore = 0; // count number of interpolated states in collision
567 
568  // temporary storage for the checked state
569  ompl::base::State *test = si_->allocState();
570 
571  // Linerarly step through motion between state 0 to state 1
572  for (double location = 0.0; location <= 1.0; location += 1.0/double(segmentCount) )
573  {
574  si_->getStateSpace()->interpolate(s1, s2, location, test);
575 
576  if (!si_->isValid(test))
577  {
578  invalidStatesScore++;
579  }
580  }
581  si_->freeState(test);
582 
583  return invalidStatesScore;
584 }
bool approximateSolutions
Flag indicating whether the planner is able to compute approximate solutions.
Definition: Planner.h:212
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique...
Definition: PlannerData.h:163
virtual void clear()
Clear all internal datastructures. Planner settings are not affected. Subsequent calls to solve() wil...
virtual void setup()
Perform extra configuration steps, if needed. This call will also issue a call to ompl::base::SpaceIn...
void setRepairPlanner(const base::PlannerPtr &planner)
Set the planner that will be used for repairing invalid paths recalled from experience.
The planner failed to find a solution.
Definition: PlannerStatus.h:62
base::PlannerDataPtr getChosenRecallPath() const
Get the chosen path used from database for repair.
std::size_t getLastRecalledNearestPathChosen() const
Get debug information about the top recalled paths that were chosen for further filtering.
std::size_t checkMotionScore(const base::State *s1, const base::State *s2) const
Count the number of states along the discretized path that are in collision Note: This is kind of an ...
LightningRetrieveRepair(const base::SpaceInformationPtr &si, const tools::LightningDBPtr &experienceDB)
Constructor.
Encapsulate a termination condition for a motion planner. Planners will call operator() to decide whe...
bool directed
Flag indicating whether the planner is able to account for the fact that the validity of a motion fro...
Definition: Planner.h:220
base::State * getState(unsigned int index)
Get the state located at index along the path.
std::size_t getStateCount() const
Get the number of states (way-points) that make up this path.
virtual void getPlannerData(base::PlannerData &data) const
Get information about the exploration data structure the planning from scratch motion planner used...
Base class for a vertex in the PlannerData structure. All derived classes must implement the clone an...
Definition: PlannerData.h:59
duration seconds(double sec)
Return the time duration representing a given number of seconds.
Definition: Time.h:78
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...
void getRepairPlannerDatas(std::vector< base::PlannerDataPtr > &data) const
Get information about the exploration data structure the repair motion planner used each call...
A shared pointer wrapper for ompl::base::Planner.
The goal is of a type that a planner does not recognize.
Definition: PlannerStatus.h:60
The planner did not find a solution for some other reason.
Definition: PlannerStatus.h:70
std::vector< base::State * > & getStates()
Get the states that make up the path (as a reference, so it can be modified, hence the function is no...
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition: Console.h:64
geometric::PathSimplifierPtr psk_
The instance of the path simplifier.
bool repairPath(const base::PlannerTerminationCondition &ptc, geometric::PathGeometric &path)
Repairs a path to be valid in the current planning environment.
RRT-Connect (RRTConnect)
Definition: RRTConnect.h:61
A class to store the exit status of Planner::solve()
Definition: PlannerStatus.h:48
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...
This class contains routines that attempt to simplify geometric paths.
A shared pointer wrapper for ompl::base::SpaceInformation.
Definition of an abstract state.
Definition: State.h:50
PlannerSpecs specs_
The specifications of the planner (its capabilities)
Definition: Planner.h:410
bool findBestPath(const base::State *startState, const base::State *goalState, base::PlannerDataPtr &chosenPath)
Filters the top n paths in nearestPaths_ to the top 1, based on state validity with current environme...
The exception type for ompl.
Definition: Exception.h:47
#define OMPL_DEBUG(fmt,...)
Log a formatted debugging string.
Definition: Console.h:70
Definition of a problem to be solved. This includes the start state(s) for the system and a goal spec...
const std::vector< base::PlannerDataPtr > & getLastRecalledNearestPaths() const
Get debug information about the top recalled paths that were chosen for further filtering.
point now()
Get the current time point.
Definition: Time.h:72
Definition of a geometric path.
Definition: PathGeometric.h:60
std::chrono::system_clock::time_point point
Representation of a point in time.
Definition: Time.h:66
SpaceInformationPtr si_
The space information for which planning is done.
Definition: Planner.h:398
void setLightningDB(const tools::LightningDBPtr &experienceDB)
Pass a pointer of the database from the lightning framework.
base::ProblemDefinitionPtr repairProblemDef_
A secondary problem definition for the repair planner to use.
A shared pointer wrapper for ompl::base::PlannerData.
bool replan(const base::State *start, const base::State *goal, geometric::PathGeometric &newPathSegment, const base::PlannerTerminationCondition &ptc)
Use our secondary planner to find a valid path between start and goal, and return that path...
A shared pointer wrapper for ompl::base::Path.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition: Console.h:68