planar_dubins_planner.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, The Regents of the University of California (Regents).
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
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder 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 AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  * Jaime F. Fisac ( jfisac@eecs.berkeley.edu )
36  */
37 
39 //
40 // OMPL-based Dubins car planner, using GraphDynamicPlanner high level logic.
41 //
43 
44 #ifndef FASTRACK_PLANNING_PLANAR_DUBINS_PLANNER_H
45 #define FASTRACK_PLANNING_PLANAR_DUBINS_PLANNER_H
46 
47 #include <fastrack/bound/box.h>
51 #include <fastrack/utils/types.h>
52 #include <fastrack_srvs/PlanarDubinsPlannerDynamics.h>
53 
54 #include <ompl/base/SpaceInformation.h>
55 #include <ompl/base/spaces/DubinsStateSpace.h>
56 #include <ompl/base/spaces/SE2StateSpace.h>
57 #include <ompl/geometric/SimpleSetup.h>
58 
59 namespace fastrack {
60 namespace planning {
61 
62 using bound::Box;
63 using dynamics::PlanarDubinsDynamics3D;
64 using environment::BallsInBoxOccupancyMap;
65 using state::PlanarDubins3D;
66 
67 namespace ob = ompl::base;
68 namespace og = ompl::geometric;
69 
70 template <typename E, typename B, typename SB>
72  : public GraphDynamicPlanner<PlanarDubins3D, E, PlanarDubinsDynamics3D,
73  fastrack_srvs::PlanarDubinsPlannerDynamics, B,
74  SB> {
75  public:
78  : GraphDynamicPlanner<PlanarDubins3D, E, PlanarDubinsDynamics3D,
79  fastrack_srvs::PlanarDubinsPlannerDynamics, B,
80  SB>() {
81  // Set OMPL log level.
82  ompl::msg::setLogLevel(ompl::msg::LogLevel::LOG_ERROR);
83  }
84 
85  private:
86  // Generate a sub-plan that connects two states and is dynamically feasible
87  // (but not necessarily recursively feasible).
88  Trajectory<PlanarDubins3D> SubPlan(const PlanarDubins3D& start,
89  const PlanarDubins3D& goal,
90  double start_time = 0.0) const;
91 
92  // Convert OMPL state to/from PlanarDubins3D.
93  PlanarDubins3D FromOmplState(const ob::State* ompl_state) const;
94  static ob::ScopedState<ob::SE2StateSpace> ToOmplState(
95  const PlanarDubins3D& state,
96  const std::shared_ptr<ob::SE2StateSpace>& space);
97 
98 }; //\class PlanarDubinsPlanner
99 
100 // ----------------------------- IMPLEMENTATION ---------------------------- //
101 
102 // Generate a sub-plan that connects two states and is dynamically feasible
103 // (but not necessarily recursively feasible).
104 template <typename E, typename B, typename SB>
105 Trajectory<PlanarDubins3D> PlanarDubinsPlanner<E, B, SB>::SubPlan(
106  const PlanarDubins3D& start, const PlanarDubins3D& goal,
107  double start_time) const {
108  // Create an OMPL state space.
109  auto space =
110  std::make_shared<ob::DubinsStateSpace>(this->dynamics_.TurningRadius());
111 
112  // Parse start/goal states into OMPL format.
113  const auto& ompl_start = ToOmplState(start, space);
114  const auto& ompl_goal = ToOmplState(goal, space);
115 
116  // Set up state space bounds.
117  constexpr size_t kNumRealVectorBoundDimensions = 2;
118  ob::RealVectorBounds bounds(kNumRealVectorBoundDimensions);
119 
120  bounds.setLow(0, PlanarDubins3D::GetLower().X());
121  bounds.setLow(1, PlanarDubins3D::GetLower().Y());
122  bounds.setHigh(0, PlanarDubins3D::GetUpper().X());
123  bounds.setHigh(1, PlanarDubins3D::GetUpper().Y());
124  space->setBounds(bounds);
125 
126  // Set up OMPL solver.
127  og::SimpleSetup ompl_setup(space);
128  ompl_setup.setStateValidityChecker([&](const ob::State* state) {
129  return this->env_.AreValid(FromOmplState(state).OccupiedPositions(),
130  this->bound_);
131  });
132 
133  ompl_setup.setStartAndGoalStates(ompl_start, ompl_goal);
134  ompl_setup.getSpaceInformation()->setStateValidityCheckingResolution(0.005);
135  ompl_setup.setup();
136 
137  // Solve.
138  // HACK! Cap the max runtime as a fraction of the total max runtime,
139  // since this will be called repeatedly from within GraphDynamicPlanner.
140  constexpr double kMaxRuntimeFraction = 0.1;
141  if (!ompl_setup.solve(kMaxRuntimeFraction * this->max_runtime_)) {
142  ROS_WARN_THROTTLE(1.0, "%s: Could not compute a valid solution.",
143  this->name_.c_str());
144  return Trajectory<PlanarDubins3D>();
145  }
146 
147  // Unpack the solution, upsample to include roughly the states used for
148  // validity checking at planning time, and assign timesteps.
149  auto path = ompl_setup.getSolutionPath();
150  path.interpolate();
151 
152  std::vector<PlanarDubins3D> states;
153  std::vector<double> times;
154 
155  double time = start_time;
156  for (size_t ii = 0; ii < path.getStateCount(); ii++) {
157  const auto state = FromOmplState(path.getState(ii));
158 
159  if (ii > 0)
160  time += (state.Position() - states.back().Position()).norm() /
161  this->dynamics_.V();
162 
163  states.emplace_back(state);
164  times.emplace_back(time);
165  }
166 
167  return Trajectory<PlanarDubins3D>(states, times);
168 }
169 
170 // Convert OMPL state to/from PlanarDubins3D.
171 template <typename E, typename B, typename SB>
173  const ob::State* ompl_state) const {
174  // Catch null state.
175  if (!ompl_state)
176  throw std::runtime_error("PlanarDubinsPlanner: null OMPL state.");
177 
178  // Cast to proper type.
179  const ob::SE2StateSpace::StateType* cast_state =
180  static_cast<const ob::SE2StateSpace::StateType*>(ompl_state);
181 
182  // Populate PlanarDubins3D state.
183  return PlanarDubins3D(cast_state->getX(), cast_state->getY(),
184  cast_state->getYaw(), this->dynamics_.V());
185 }
186 
187 template <typename E, typename B, typename SB>
188 ob::ScopedState<ob::SE2StateSpace> PlanarDubinsPlanner<E, B, SB>::ToOmplState(
189  const PlanarDubins3D& state,
190  const std::shared_ptr<ob::SE2StateSpace>& space) {
191  ob::ScopedState<ob::SE2StateSpace> ompl_state(space);
192 
193  // Populate each field.
194  ompl_state[0] = state.X();
195  ompl_state[1] = state.Y();
196  ompl_state[2] = state.Theta();
197 
198  return ompl_state;
199 }
200 
201 } // namespace planning
202 } // namespace fastrack
203 
204 #endif
static ob::ScopedState< ob::SE2StateSpace > ToOmplState(const PlanarDubins3D &state, const std::shared_ptr< ob::SE2StateSpace > &space)
Definition: box.h:53
PlanarDubins3D FromOmplState(const ob::State *ompl_state) const
Trajectory< PlanarDubins3D > SubPlan(const PlanarDubins3D &start, const PlanarDubins3D &goal, double start_time=0.0) const


fastrack
Author(s): David Fridovich-Keil
autogenerated on Mon Aug 3 2020 21:28:37