Loading...
Searching...
No Matches
GeometricCarPlanning.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2010, Rice University
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 Rice University 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: Mark Moll */
36
37#include <ompl/base/spaces/DubinsStateSpace.h>
38#include <ompl/base/spaces/ReedsSheppStateSpace.h>
39#include <ompl/base/spaces/TrochoidStateSpace.h>
40#include <ompl/base/ScopedState.h>
41#include <ompl/geometric/SimpleSetup.h>
42#include <boost/program_options.hpp>
43
44namespace ob = ompl::base;
45namespace og = ompl::geometric;
46namespace po = boost::program_options;
47
48// The easy problem is the standard narrow passage problem: two big open
49// spaces connected by a narrow passage. The hard problem is essentially
50// one long narrow passage with the robot facing towards the long walls
51// in both the start and goal configurations.
52
53bool isStateValidEasy(const ob::SpaceInformation *si, const ob::State *state)
54{
55 const auto *s = state->as<ob::SE2StateSpace::StateType>();
56 double x = s->getX(), y = s->getY();
57 return si->satisfiesBounds(s) && (x < 5 || x > 13 || (y > 8.5 && y < 9.5));
58}
59
60bool isStateValidHard(const ob::SpaceInformation *si, const ob::State *state)
61{
62 return si->satisfiesBounds(state);
63}
64
65void plan(const ob::StateSpacePtr &space, bool easy)
66{
67 ob::ScopedState<> start(space), goal(space);
68 ob::RealVectorBounds bounds(2);
69 bounds.setLow(0);
70 if (easy)
71 bounds.setHigh(18);
72 else
73 {
74 bounds.high[0] = 6;
75 bounds.high[1] = .6;
76 }
77 space->as<ob::SE2StateSpace>()->setBounds(bounds);
78
79 // define a simple setup class
80 og::SimpleSetup ss(space);
81
82 // set state validity checking for this space
83 const ob::SpaceInformation *si = ss.getSpaceInformation().get();
84 auto isStateValid = easy ? isStateValidEasy : isStateValidHard;
85 ss.setStateValidityChecker([isStateValid, si](const ob::State *state) { return isStateValid(si, state); });
86
87 // set the start and goal states
88 if (easy)
89 {
90 start[0] = start[1] = 1.;
91 start[2] = 0.;
92 goal[0] = goal[1] = 17;
93 goal[2] = -.99 * boost::math::constants::pi<double>();
94 }
95 else
96 {
97 start[0] = start[1] = .5;
98 start[2] = .5 * boost::math::constants::pi<double>();
99 ;
100 goal[0] = 5.5;
101 goal[1] = .5;
102 goal[2] = .5 * boost::math::constants::pi<double>();
103 }
104 ss.setStartAndGoalStates(start, goal);
105
106 // this call is optional, but we put it in to get more output information
107 ss.getSpaceInformation()->setStateValidityCheckingResolution(0.005);
108 ss.setup();
109 ss.print();
110
111 // attempt to solve the problem within 300 seconds of planning time
112 ob::PlannerStatus solved = ss.solve(300.0);
113
115 {
116 std::vector<double> reals;
117
118 std::cout << "Found solution:" << std::endl;
119 ss.simplifySolution();
120 og::PathGeometric path = ss.getSolutionPath();
121 path.interpolate(1000);
122 path.printAsMatrix(std::cout);
123 }
124 else
125 std::cout << "No solution found" << std::endl;
126}
127
128void printTrajectory(const ob::StateSpacePtr &space, const std::vector<double> &pt)
129{
130 if (pt.size() != 3)
131 throw ompl::Exception("3 arguments required for trajectory option");
132 const unsigned int num_pts = 50;
133 ob::ScopedState<> from(space), to(space), s(space);
134 std::vector<double> reals;
135
136 from[0] = from[1] = from[2] = 0.;
137
138 to[0] = pt[0];
139 to[1] = pt[1];
140 to[2] = pt[2];
141
142 std::cout << "distance: " << space->distance(from(), to()) << "\npath:\n";
143 for (unsigned int i = 0; i <= num_pts; ++i)
144 {
145 space->interpolate(from(), to(), (double)i / num_pts, s());
146 reals = s.reals();
147 std::cout << "path " << reals[0] << ' ' << reals[1] << ' ' << reals[2] << ' ' << std::endl;
148 }
149}
150
151void printDistanceGrid(const ob::StateSpacePtr &space)
152{
153 // print the distance for (x,y,theta) for all points in a 3D grid in SE(2)
154 // over [-5,5) x [-5, 5) x [-pi,pi).
155 //
156 // The output should be redirected to a file, say, distance.txt. This
157 // can then be read and plotted in Matlab like so:
158 // x = reshape(load('distance.txt'),200,200,200);
159 // for i=1:200,
160 // contourf(squeeze(x(i,:,:)),30);
161 // axis equal; axis tight; colorbar; pause;
162 // end;
163 const unsigned int num_pts = 200;
164 ob::ScopedState<> from(space), to(space);
165 from[0] = from[1] = from[2] = 0.;
166
167 for (unsigned int i = 0; i < num_pts; ++i)
168 for (unsigned int j = 0; j < num_pts; ++j)
169 for (unsigned int k = 0; k < num_pts; ++k)
170 {
171 to[0] = 5. * (2. * (double)i / num_pts - 1.);
172 to[1] = 5. * (2. * (double)j / num_pts - 1.);
173 to[2] = boost::math::constants::pi<double>() * (2. * (double)k / num_pts - 1.);
174 std::cout << space->distance(from(), to()) << '\n';
175 }
176}
177
178int main(int argc, char *argv[])
179{
180 try
181 {
182 po::options_description desc("Options");
183 desc.add_options()("help", "show help message")("dubins", "use Dubins state space")(
184 "dubinssym", "use symmetrized Dubins state space")(
185 "trochoid", "use trochoid state space (default wind ratio: 0.3)")("reedsshepp",
186 "use Reeds-Shepp state space (default)")(
187 "easyplan", "solve easy planning problem and print path")("hardplan",
188 "solve hard planning problem and print path")(
189 "trajectory", po::value<std::vector<double>>()->multitoken(),
190 "print trajectory from (0,0,0) to a user-specified x, y, and theta")("distance", "print distance grid");
191
192 po::variables_map vm;
193 po::store(po::parse_command_line(argc, argv, desc,
194 po::command_line_style::unix_style ^ po::command_line_style::allow_short),
195 vm);
196 po::notify(vm);
197
198 if ((vm.count("help") != 0u) || argc == 1)
199 {
200 std::cout << desc << "\n";
201 return 1;
202 }
203
204 ob::StateSpacePtr space(std::make_shared<ob::ReedsSheppStateSpace>());
205
206 if (vm.count("dubins") != 0u)
207 space = std::make_shared<ob::DubinsStateSpace>();
208 if (vm.count("dubinssym") != 0u)
209 space = std::make_shared<ob::DubinsStateSpace>(1., true);
210 if (vm.count("trochoid") != 0u)
211 space = std::make_shared<ob::TrochoidStateSpace>(1., 0.3);
212 if (vm.count("easyplan") != 0u)
213 plan(space, true);
214 if (vm.count("hardplan") != 0u)
215 plan(space, false);
216 if (vm.count("trajectory") != 0u)
217 printTrajectory(space, vm["trajectory"].as<std::vector<double>>());
218 if (vm.count("distance") != 0u)
219 printDistanceGrid(space);
220 }
221 catch (std::exception &e)
222 {
223 std::cerr << "error: " << e.what() << "\n";
224 return 1;
225 }
226 catch (...)
227 {
228 std::cerr << "Exception of unknown type!\n";
229 }
230
231 return 0;
232}
The exception type for ompl.
Definition Exception.h:47
The lower and upper bounds for an Rn space.
A state in SE(2): (x, y, yaw).
A state space representing SE(2).
Definition of a scoped state.
Definition ScopedState.h:57
The base class for space information. This contains all the information about the space planning is d...
void setStateValidityChecker(const StateValidityCheckerPtr &svc)
Set the instance of the state validity checker to use. Parallel implementations of planners assume th...
Definition of an abstract state.
Definition State.h:50
const T * as() const
Cast this instance to a desired type.
Definition State.h:66
Definition of a geometric path.
Create the set of classes typically needed to solve a geometric problem.
Definition SimpleSetup.h:63
This namespace contains sampling based planning routines shared by both planning under geometric cons...
This namespace contains code that is specific to planning under geometric constraints.
A class to store the exit status of Planner::solve().
@ EXACT_SOLUTION
The planner found an exact solution.