ompl_solver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
31 
32 #include <ompl/util/Console.h>
33 #include <ompl/util/RandomNumbers.h>
34 
35 namespace exotica
36 {
37 template <class ProblemType>
39 
40 template <class ProblemType>
42 
43 template <class ProblemType>
45 {
47  prob_ = std::static_pointer_cast<ProblemType>(pointer);
48  if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::FIXED)
49  state_space_.reset(new OMPLRNStateSpace(init_));
50  else if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::PLANAR)
51  {
52  if (init_.IsDubinsStateSpace)
53  state_space_.reset(new OMPLDubinsRNStateSpace(init_));
54  else
55  state_space_.reset(new OMPLRNStateSpace(init_)); // NB: We have a dedicated OMPLSE2RNStateSpace, however, for now we cannot set orientation bounds on it - as thus we are using the RN here. Cf. issue #629.
56  }
57  else if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::FLOATING)
58  state_space_.reset(new OMPLSE3RNStateSpace(init_));
59  else
60  ThrowNamed("Unsupported base type " << prob_->GetScene()->GetKinematicTree().GetControlledBaseType());
61  ompl_simple_setup_.reset(new ompl::geometric::SimpleSetup(state_space_));
62  ompl_simple_setup_->setStateValidityChecker(ompl::base::StateValidityCheckerPtr(new OMPLStateValidityChecker(ompl_simple_setup_->getSpaceInformation(), prob_)));
63  ompl_simple_setup_->setPlannerAllocator(boost::bind(planner_allocator_, _1, algorithm_));
64 
65  if (init_.Projection.rows() > 0)
66  {
67  std::vector<int> project_vars(init_.Projection.rows());
68  for (int i = 0; i < init_.Projection.rows(); ++i)
69  {
70  project_vars[i] = (int)init_.Projection(i);
71  if (project_vars[i] < 0 || project_vars[i] >= prob_->N) ThrowNamed("Invalid projection index! " << project_vars[i]);
72  }
73  if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::FIXED)
74  ompl_simple_setup_->getStateSpace()->registerDefaultProjection(ompl::base::ProjectionEvaluatorPtr(new OMPLRNProjection(state_space_, project_vars)));
75  else if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::PLANAR)
76  ompl_simple_setup_->getStateSpace()->registerDefaultProjection(ompl::base::ProjectionEvaluatorPtr(new OMPLSE2RNProjection(state_space_, project_vars)));
77  else if (prob_->GetScene()->GetKinematicTree().GetControlledBaseType() == BaseType::FLOATING)
78  ompl_simple_setup_->getStateSpace()->registerDefaultProjection(ompl::base::ProjectionEvaluatorPtr(new OMPLSE3RNProjection(state_space_, project_vars)));
79  }
80 }
81 
82 template <class ProblemType>
84 {
85  return ompl::RNG::getSeed();
86 }
87 
88 template <class ProblemType>
90 {
91  // Clear previously computed solutions
92  if (!multi_query_)
93  {
94  ompl_simple_setup_->getProblemDefinition()->clearSolutionPaths();
95  const ompl::base::PlannerPtr planner = ompl_simple_setup_->getPlanner();
96  if (planner)
97  planner->clear();
98  ompl_simple_setup_->getPlanner()->setProblemDefinition(ompl_simple_setup_->getProblemDefinition());
99  }
100  ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->resetMotionCounter();
101 }
102 
103 template <class ProblemType>
105 {
106  ompl_simple_setup_->clearStartStates();
107  int v = ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->getValidMotionCount();
108  int iv = ompl_simple_setup_->getSpaceInformation()->getMotionValidator()->getInvalidMotionCount();
109  if (debug_) CONSOLE_BRIDGE_logDebug("There were %d valid motions and %d invalid motions.", v, iv);
110 
111  if (ompl_simple_setup_->getProblemDefinition()->hasApproximateSolution())
112  CONSOLE_BRIDGE_logWarn("Computed solution is approximate");
113 }
114 
115 template <class ProblemType>
117 {
118  ompl::base::ScopedState<> gs(state_space_);
119  state_space_->as<OMPLStateSpace>()->ExoticaToOMPLState(qT, gs.get());
120  if (!ompl_simple_setup_->getStateValidityChecker()->isValid(gs.get()))
121  {
122  ThrowNamed("Goal state is not valid!");
123  }
124 
125  if (!ompl_simple_setup_->getSpaceInformation()->satisfiesBounds(gs.get()))
126  {
127  state_space_->as<OMPLStateSpace>()->StateDebug(qT);
128 
129  // Debug state and bounds
130  auto bounds = prob_->GetBounds();
131  std::string out_of_bounds_joint_ids = "";
132  for (int i = 0; i < qT.rows(); ++i)
133  if (qT(i) < bounds[i] || qT(i) > bounds[i + qT.rows()])
134  out_of_bounds_joint_ids += "[j" + std::to_string(i) + "=" + std::to_string(qT(i)) + ", ll=" + std::to_string(bounds[i]) + ", ul=" + std::to_string(bounds[i + qT.rows()]) + "]\n";
135 
136  ThrowNamed("Invalid goal state [Invalid joint bounds for joint indices: \n"
137  << out_of_bounds_joint_ids << "]");
138  }
139  ompl_simple_setup_->setGoalState(gs, eps);
140 }
141 
142 template <class ProblemType>
143 void OMPLSolver<ProblemType>::GetPath(Eigen::MatrixXd &traj, ompl::base::PlannerTerminationCondition &ptc)
144 {
145  ompl::geometric::PathSimplifierPtr psf = ompl_simple_setup_->getPathSimplifier();
146  const ompl::base::SpaceInformationPtr &si = ompl_simple_setup_->getSpaceInformation();
147 
148  ompl::geometric::PathGeometric pg = ompl_simple_setup_->getSolutionPath();
149  if (init_.Smooth)
150  {
151  bool try_more = true;
152  int times = 0;
153  while (init_.ReduceVertices && times < init_.SimplifyTryCnt && try_more && ptc == false)
154  {
155  pg.interpolate(init_.SimplifyInterpolationLength);
156  try_more = psf->reduceVertices(pg, 0, 0, init_.RangeRatio);
157  ++times;
158  }
159  if (init_.ShortcutPath && si->getStateSpace()->isMetricSpace())
160  {
161  times = 0;
162  while (times < init_.SimplifyTryCnt && try_more && ptc == false)
163  {
164  pg.interpolate(init_.SimplifyInterpolationLength);
165  try_more = psf->shortcutPath(pg, 0, 0, init_.RangeRatio, init_.SnapToVertex);
166  ++times;
167  }
168  }
169  }
170  std::vector<ompl::base::State *> &states = pg.getStates();
171  unsigned int length = 0;
172  if (init_.FinalInterpolationLength > 3)
173  {
174  length = init_.FinalInterpolationLength;
175  }
176  else
177  {
178  const int n1 = states.size() - 1;
179  for (int i = 0; i < n1; ++i)
180  length += si->getStateSpace()->validSegmentCount(states[i], states[i + 1]);
181  }
182  pg.interpolate(int(length * init_.SmoothnessFactor));
183 
184  traj.resize(pg.getStateCount(), prob_->GetSpaceDim());
185  Eigen::VectorXd tmp(prob_->GetSpaceDim());
186 
187  for (int i = 0; i < static_cast<int>(pg.getStateCount()); ++i)
188  {
189  state_space_->as<OMPLStateSpace>()->OMPLToExoticaState(pg.getState(i), tmp);
190  traj.row(i) = tmp.transpose();
191  }
192 }
193 
194 template <class ProblemType>
195 void OMPLSolver<ProblemType>::Solve(Eigen::MatrixXd &solution)
196 {
197  // Set log level
198  ompl::msg::setLogLevel(debug_ ? ompl::msg::LogLevel::LOG_DEBUG : ompl::msg::LogLevel::LOG_WARN);
199 
200  Eigen::VectorXd q0 = prob_->ApplyStartState();
201 
202  // check joint limits
203  const std::vector<double> bounds = prob_->GetBounds();
204  for (const double l : bounds)
205  {
206  if (!std::isfinite(l))
207  {
208  std::cerr << "Detected non-finite joint limits:" << std::endl;
209  const size_t nlim = bounds.size() / 2;
210  for (uint i = 0; i < nlim; ++i)
211  {
212  std::cout << bounds[i] << ", " << bounds[nlim + i] << std::endl;
213  }
214  throw std::runtime_error("All joint limits need to be finite!");
215  }
216  }
217 
218  if (!state_space_->as<OMPLStateSpace>()->isLocked())
219  {
220  state_space_->as<OMPLStateSpace>()->SetBounds(prob_);
221  bounds_ = prob_->GetBounds();
222  }
223  else if (!bounds_.empty() && bounds_ != prob_->GetBounds())
224  {
225  ThrowPretty("Cannot set new bounds on locked state space!");
226  }
227 
228  ompl_simple_setup_->getSpaceInformation()->setup();
229 
230  ompl_simple_setup_->setup();
231 
232  if (ompl_simple_setup_->getPlanner()->params().hasParam("Range"))
233  ompl_simple_setup_->getPlanner()->params().setParam("Range", init_.Range);
234  if (ompl_simple_setup_->getPlanner()->params().hasParam("GoalBias"))
235  ompl_simple_setup_->getPlanner()->params().setParam("GoalBias", init_.GoalBias);
236 
237  if (init_.RandomSeed > -1)
238  {
239  HIGHLIGHT_NAMED(algorithm_, "Setting random seed to " << init_.RandomSeed);
240  ompl::RNG::setSeed(static_cast<long unsigned int>(init_.RandomSeed));
241  }
242 
243  SetGoalState(prob_->GetGoalState(), init_.Epsilon);
244 
245  ompl::base::ScopedState<> ompl_start_state(state_space_);
246 
247  state_space_->as<OMPLStateSpace>()->ExoticaToOMPLState(q0, ompl_start_state.get());
248  ompl_simple_setup_->setStartState(ompl_start_state);
249 
250  PreSolve();
251  ompl::time::point start = ompl::time::now();
252  ompl::base::PlannerTerminationCondition ptc = ompl::base::timedPlannerTerminationCondition(init_.Timeout - ompl::time::seconds(ompl::time::now() - start));
253 
254  Timer t;
255  if (ompl_simple_setup_->solve(ptc) == ompl::base::PlannerStatus::EXACT_SOLUTION && ompl_simple_setup_->haveSolutionPath())
256  {
257  GetPath(solution, ptc);
258  }
259  planning_time_ = t.GetDuration();
260  PostSolve();
261 }
262 
263 template class OMPLSolver<SamplingProblem>;
264 } // namespace exotica
#define CONSOLE_BRIDGE_logWarn(fmt,...)
int GetRandomSeed() const
Definition: ompl_solver.cpp:83
#define ThrowPretty(m)
#define CONSOLE_BRIDGE_logDebug(fmt,...)
virtual void SpecifyProblem(PlanningProblemPtr pointer)
void SpecifyProblem(PlanningProblemPtr pointer) override
Definition: ompl_solver.cpp:44
#define ThrowNamed(m)
const Eigen::Ref< const Eigen::VectorXd > & VectorXdRefConst
void SetGoalState(Eigen::VectorXdRefConst qT, const double eps=0)
void GetPath(Eigen::MatrixXd &traj, ompl::base::PlannerTerminationCondition &ptc)
#define HIGHLIGHT_NAMED(name, x)
double GetDuration() const
std::shared_ptr< PlanningProblem > PlanningProblemPtr
void Solve(Eigen::MatrixXd &solution) override


exotica_ompl_solver
Author(s): Yiming Yang
autogenerated on Sat Apr 10 2021 02:36:37