38#include <boost/math/constants/constants.hpp>
40#include "boost/program_options.hpp"
42#include "PlanarManipulatorPolyWorld.h"
43#include "PlanarManipulator.h"
44#include "PlanarManipulatorStateSpace.h"
45#include "PlanarManipulatorStateValidityChecker.h"
46#include "PlanarManipulatorIKGoal.h"
47#include "PlanarManipulatorTSRRTConfig.h"
48#include "PlanarManipulatorXXLDecomposition.h"
50#include <ompl/geometric/SimpleSetup.h>
53#include <ompl/geometric/planners/xxl/XXL.h>
54#include <ompl/geometric/planners/rrt/RRT.h>
55#include <ompl/geometric/planners/kpiece/KPIECE1.h>
56#include <ompl/geometric/planners/stride/STRIDE.h>
57#include <ompl/geometric/planners/rrt/TSRRT.h>
58#include <ompl/geometric/planners/rlrt/RLRT.h>
61#include <ompl/geometric/planners/rrt/RRTConnect.h>
62#include <ompl/geometric/planners/kpiece/BKPIECE1.h>
63#include <ompl/geometric/planners/rlrt/BiRLRT.h>
65#include <ompl/tools/benchmark/Benchmark.h>
80 Problem(
int links,
const std::string &problemName, PolyWorld &&world,
const Eigen::Affine2d &baseFrame,
81 const Eigen::Affine2d &goalFrame)
82 : name(problemName), manipulator(links, 1.0 / links), world(std::move(world)), goalFrame(goalFrame)
84 manipulator.setBaseFrame(baseFrame);
88 PlanarManipulator manipulator;
90 Eigen::Affine2d goalFrame;
94Problem CreateProblem(
const Arguments &args)
96 if (args.problem ==
"corridor")
98 Eigen::Affine2d baseFrame;
99 Eigen::Affine2d goalFrame;
100 PolyWorld world = createCorridorProblem(args.numLinks, baseFrame, goalFrame);
101 return Problem(args.numLinks, args.problem, std::move(world), baseFrame, goalFrame);
103 else if (args.problem ==
"constricted")
105 Eigen::Affine2d baseFrame;
106 Eigen::Affine2d goalFrame;
107 PolyWorld world = createConstrictedProblem(args.numLinks, baseFrame, goalFrame);
108 return Problem(args.numLinks, args.problem, std::move(world), baseFrame, goalFrame);
117ompl::geometric::SimpleSetupPtr setupOMPL(Problem &problem)
119 const unsigned int numLinks = problem.manipulator.getNumLinks();
123 bounds.setLow(-boost::math::constants::pi<double>());
124 bounds.setHigh(boost::math::constants::pi<double>());
128 problem.manipulator.setBounds(bounds.low, bounds.high);
133 setup->setStateValidityChecker(std::make_shared<PlanarManipulatorCollisionChecker>(
134 setup->getSpaceInformation(), problem.manipulator, &problem.world));
137 setup->getSpaceInformation()->setStateValidityCheckingResolution(0.001);
142 for (
size_t i = 0; i < numLinks; ++i)
143 start_angles[i] = 1e-7;
144 setup->getProblemDefinition()->addStartState(start);
145 setup->getStateSpace()->freeState(start);
148 &problem.manipulator,
151 setup->setGoal(goal);
159 const auto xBounds = problem.world.xBounds();
160 const auto yBounds = problem.world.yBounds();
163 double xMin = std::max(origin.first - chainLength, xBounds.first);
164 double xMax = std::min(origin.first + chainLength, xBounds.second);
165 double yMin = std::max(origin.second - chainLength, yBounds.first);
166 double yMax = std::min(origin.second + chainLength, yBounds.second);
168 reachable_bounds.setLow(0, xMin);
169 reachable_bounds.setHigh(0, xMax);
170 reachable_bounds.setLow(1, yMin);
171 reachable_bounds.setHigh(1, yMax);
173 return reachable_bounds;
178ompl::geometric::TaskSpaceConfigPtr getTaskSpaceConfig(
const Problem &problem)
181 unsigned int numLinks = manip.getNumLinks();
182 double linkLength = 1.0 / numLinks;
183 double chainLength = numLinks * linkLength;
185 const Eigen::Affine2d &baseFrame = manip.getBaseFrame();
186 Point origin = {baseFrame.translation()(0), baseFrame.translation()(1)};
191 return task_space_ptr;
198ompl::geometric::XXLDecompositionPtr getXXLDecomp(
const ompl::base::SpaceInformationPtr &si,
const Problem &problem,
202 unsigned int numLinks = manip.getNumLinks();
203 double linkLength = 1.0 / numLinks;
204 double chainLength = numLinks * linkLength;
207 const Eigen::Affine2d &baseFrame = manip.getBaseFrame();
208 Point origin = {baseFrame.translation()(0), baseFrame.translation()(1)};
212 std::vector<int> xySlices(2, numXYSlices);
213 const int thetaSlices = 1;
216 std::vector<int> projLinks;
220 projLinks.push_back((numLinks / 2) - 1);
223 projLinks.push_back(numLinks - 1);
226 si, &manip, reachable_bounds, xySlices, thetaSlices, projLinks,
true));
235 if (!planner->getProblemDefinition()->hasSolution())
238 double cartesianDist = 0.0;
240 *(planner->getProblemDefinition()->getSolutionPath().get()));
241 for (
size_t i = 0; i < path.getStateCount() - 1; ++i)
243 std::vector<Eigen::Affine2d> startFrames, endFrames;
247 for (
size_t j = 1; j < endFrames.size(); ++j)
248 cartesianDist += (endFrames[j].translation() - startFrames[j].translation()).norm();
251 run[
"Cartesian Distance REAL"] = boost::lexical_cast<std::string>(cartesianDist);
254void BenchmarkProblem(ompl::geometric::SimpleSetupPtr setup,
const Problem &problem,
int runs,
double timeout)
260 ompl::base::PlannerPtr tsrrt(
new ompl::geometric::TSRRT(setup->getSpaceInformation(), getTaskSpaceConfig(problem)));
266 const int numLinks = problem.manipulator.getNumLinks();
267 const int xySlices = std::max(2, numLinks / 3);
269 getXXLDecomp(setup->getSpaceInformation(), problem, xySlices)));
271 setup->getSpaceInformation(), getXXLDecomp(setup->getSpaceInformation(), problem, 1)));
272 xxl1->setName(
"XXL1");
274 std::string name =
"PlanarManipulator - " + problem.name;
277 benchmark.addPlanner(rrt);
278 benchmark.addPlanner(rrtc);
279 benchmark.addPlanner(rlrt);
280 benchmark.addPlanner(birlrt);
281 benchmark.addPlanner(stride);
282 benchmark.addPlanner(kpiece);
283 benchmark.addPlanner(bkpiece);
284 benchmark.addPlanner(xxl);
285 benchmark.addPlanner(xxl1);
286 benchmark.addPlanner(tsrrt);
289 { postRunEvent(planner, run, &problem.manipulator); });
290 benchmark.addExperimentParameter(
"num_links",
"INTEGER", boost::lexical_cast<std::string>(numLinks));
291 benchmark.addExperimentParameter(
"cells",
"INTEGER", boost::lexical_cast<std::string>(xySlices));
293 double memoryLimit = 8192.0;
295 benchmark.benchmark(request);
297 benchmark.saveResultsToFile();
302 const int numLinks = problem.manipulator.getNumLinks();
304 const char *world_file =
"world.yaml";
306 problem.world.writeWorld(world_file);
308 const double linkLength = 1.0 / numLinks;
309 const Eigen::Affine2d &basePose = problem.manipulator.getBaseFrame();
311 const char *path_file =
"manipulator_path.txt";
316 fout.open(path_file);
318 fout << numLinks <<
" " << linkLength <<
" " << basePose.translation()(0) <<
" " << basePose.translation()(1) <<
" "
319 << xySlices << std::endl;
321 for (
size_t i = 0; i < path.getStateCount(); ++i)
324 for (
size_t j = 0; j < problem.manipulator.getNumLinks(); ++j)
325 fout << angles[j] <<
" ";
331void SolveProblem(ompl::geometric::SimpleSetupPtr setup,
const Problem &problem,
double timeout,
bool write_viz_out)
334 const int numLinks = problem.manipulator.getNumLinks();
336 const int xySlices = std::max(2, numLinks / 3);
338 getXXLDecomp(setup->getSpaceInformation(), problem, xySlices)));
339 setup->setPlanner(xxl);
353 WriteVisualization(problem, pgeo, xySlices);
362void PlanarManipulatorPlanning(
const Arguments &args)
366 Problem problem = CreateProblem(args);
367 ompl::geometric::SimpleSetupPtr setup = setupOMPL(problem);
369 if (args.numRuns == 1)
370 SolveProblem(setup, problem, args.timeout, args.viz);
372 BenchmarkProblem(setup, problem, args.numRuns, args.timeout);
375int main(
int argc,
char **argv)
380 namespace po = boost::program_options;
381 po::options_description desc(
"Allowed options");
384 (
"help,?",
"Show this message")
385 (
"links,l", po::value<int>(&args.numLinks)->default_value(10),
386 "Set the number of links in the chain")
387 (
"runs,r", po::value<int>(&args.numRuns)->default_value(1),
388 "The number of times to execute the query. >1 implies benchmarking")
389 (
"timeout,t", po::value<double>(&args.timeout)->default_value(60.0),
390 "The maximum time (seconds) before failure is declared")
391 (
"problem,p", po::value<std::string>(&args.problem)->default_value(
"corridor"),
392 "The name of the problem [corridor,constricted] to solve")
393 (
"viz,v", po::bool_switch(&args.viz)->default_value(
false),
394 "Write visualization output to disk. Only works when runs = 1");
397 po::variables_map vm;
398 po::store(po::parse_command_line(argc, argv, desc), vm);
401 if (vm.count(
"help"))
403 std::cout << desc << std::endl;
406 PlanarManipulatorPlanning(args);
The exception type for ompl.
The lower and upper bounds for an Rn space.
The definition of a state in Rn.
double * values
The value of the actual vector in Rn.
Definition of an abstract state.
const T * as() const
Cast this instance to a desired type.
Bi-directional KPIECE with one level of discretization.
Bi-directional Range-Limited Random Tree (Ryan Luna's Random Tree).
Kinematic Planning by Interior-Exterior Cell Exploration.
Definition of a geometric path.
std::size_t getStateCount() const
Get the number of states (way-points) that make up this path.
void interpolate(unsigned int count)
Insert a number of states in a path so that the path is made up of exactly count states....
Range-Limited Random Tree (Ryan Luna's Random Tree).
RRT-Connect (RRTConnect).
Rapidly-exploring Random Trees.
Search Tree with Resolution Independent Density Estimation.
Create the set of classes typically needed to solve a geometric problem.
Task-space Rapidly-exploring Random Trees.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
void setLogLevel(LogLevel level)
Set the minimum level of logging data to output. Messages with lower logging levels will not be recor...
A class to store the exit status of Planner::solve().
@ EXACT_SOLUTION
The planner found an exact solution.
@ APPROXIMATE_SOLUTION
The planner found an approximate solution.