39#include "boost/program_options.hpp"
41#include "PlanarManipulatorPolyWorld.h"
42#include "PlanarManipulator.h"
43#include "PlanarManipulatorStateSpace.h"
44#include "PlanarManipulatorStateValidityChecker.h"
45#include "PlanarManipulatorIKGoal.h"
46#include "PlanarManipulatorTSRRTConfig.h"
47#include "PlanarManipulatorXXLDecomposition.h"
49#include <ompl/geometric/SimpleSetup.h>
52#include <ompl/geometric/planners/xxl/XXL.h>
53#include <ompl/geometric/planners/rrt/RRT.h>
54#include <ompl/geometric/planners/kpiece/KPIECE1.h>
55#include <ompl/geometric/planners/stride/STRIDE.h>
56#include <ompl/geometric/planners/rrt/TSRRT.h>
57#include <ompl/geometric/planners/rlrt/RLRT.h>
60#include <ompl/geometric/planners/rrt/RRTConnect.h>
61#include <ompl/geometric/planners/kpiece/BKPIECE1.h>
62#include <ompl/geometric/planners/rlrt/BiRLRT.h>
64#include <ompl/tools/benchmark/Benchmark.h>
79 Problem(
int links,
const std::string &problemName, PolyWorld &&world,
const Eigen::Affine2d &baseFrame,
80 const Eigen::Affine2d &goalFrame)
81 : name(problemName), manipulator(links, 1.0 / links), world(std::move(world)), goalFrame(goalFrame)
83 manipulator.setBaseFrame(baseFrame);
87 PlanarManipulator manipulator;
89 Eigen::Affine2d goalFrame;
93Problem CreateProblem(
const Arguments &args)
95 if (args.problem ==
"corridor")
97 Eigen::Affine2d baseFrame;
98 Eigen::Affine2d goalFrame;
99 PolyWorld world = createCorridorProblem(args.numLinks, baseFrame, goalFrame);
100 return Problem(args.numLinks, args.problem, std::move(world), baseFrame, goalFrame);
102 else if (args.problem ==
"constricted")
104 Eigen::Affine2d baseFrame;
105 Eigen::Affine2d goalFrame;
106 PolyWorld world = createConstrictedProblem(args.numLinks, baseFrame, goalFrame);
107 return Problem(args.numLinks, args.problem, std::move(world), baseFrame, goalFrame);
116ompl::geometric::SimpleSetupPtr setupOMPL(Problem &problem)
118 const unsigned int numLinks = problem.manipulator.getNumLinks();
122 bounds.setLow(-M_PI);
123 bounds.setHigh(M_PI);
127 problem.manipulator.setBounds(bounds.low, bounds.high);
132 setup->setStateValidityChecker(std::make_shared<PlanarManipulatorCollisionChecker>(
133 setup->getSpaceInformation(), problem.manipulator, &problem.world));
136 setup->getSpaceInformation()->setStateValidityCheckingResolution(0.001);
141 for (
size_t i = 0; i < numLinks; ++i)
142 start_angles[i] = 1e-7;
143 setup->getProblemDefinition()->addStartState(start);
144 setup->getStateSpace()->freeState(start);
147 &problem.manipulator,
150 setup->setGoal(goal);
158 const auto xBounds = problem.world.xBounds();
159 const auto yBounds = problem.world.yBounds();
162 double xMin = std::max(origin.first - chainLength, xBounds.first);
163 double xMax = std::min(origin.first + chainLength, xBounds.second);
164 double yMin = std::max(origin.second - chainLength, yBounds.first);
165 double yMax = std::min(origin.second + chainLength, yBounds.second);
167 reachable_bounds.setLow(0, xMin);
168 reachable_bounds.setHigh(0, xMax);
169 reachable_bounds.setLow(1, yMin);
170 reachable_bounds.setHigh(1, yMax);
172 return reachable_bounds;
177ompl::geometric::TaskSpaceConfigPtr getTaskSpaceConfig(
const Problem &problem)
180 unsigned int numLinks = manip.getNumLinks();
181 double linkLength = 1.0 / numLinks;
182 double chainLength = numLinks * linkLength;
184 const Eigen::Affine2d &baseFrame = manip.getBaseFrame();
185 Point origin = {baseFrame.translation()(0), baseFrame.translation()(1)};
190 return task_space_ptr;
197ompl::geometric::XXLDecompositionPtr getXXLDecomp(
const ompl::base::SpaceInformationPtr &si,
const Problem &problem,
201 unsigned int numLinks = manip.getNumLinks();
202 double linkLength = 1.0 / numLinks;
203 double chainLength = numLinks * linkLength;
206 const Eigen::Affine2d &baseFrame = manip.getBaseFrame();
207 Point origin = {baseFrame.translation()(0), baseFrame.translation()(1)};
211 std::vector<int> xySlices(2, numXYSlices);
212 const int thetaSlices = 1;
215 std::vector<int> projLinks;
219 projLinks.push_back((numLinks / 2) - 1);
222 projLinks.push_back(numLinks - 1);
225 si, &manip, reachable_bounds, xySlices, thetaSlices, projLinks,
true));
234 if (!planner->getProblemDefinition()->hasSolution())
237 double cartesianDist = 0.0;
239 *(planner->getProblemDefinition()->getSolutionPath().get()));
240 for (
size_t i = 0; i < path.getStateCount() - 1; ++i)
242 std::vector<Eigen::Affine2d> startFrames, endFrames;
246 for (
size_t j = 1; j < endFrames.size(); ++j)
247 cartesianDist += (endFrames[j].translation() - startFrames[j].translation()).norm();
250 run[
"Cartesian Distance REAL"] = boost::lexical_cast<std::string>(cartesianDist);
253void BenchmarkProblem(ompl::geometric::SimpleSetupPtr setup,
const Problem &problem,
int runs,
double timeout)
259 ompl::base::PlannerPtr tsrrt(
new ompl::geometric::TSRRT(setup->getSpaceInformation(), getTaskSpaceConfig(problem)));
265 const int numLinks = problem.manipulator.getNumLinks();
266 const int xySlices = std::max(2, numLinks / 3);
268 getXXLDecomp(setup->getSpaceInformation(), problem, xySlices)));
270 setup->getSpaceInformation(), getXXLDecomp(setup->getSpaceInformation(), problem, 1)));
271 xxl1->setName(
"XXL1");
273 std::string name =
"PlanarManipulator - " + problem.name;
276 benchmark.addPlanner(rrt);
277 benchmark.addPlanner(rrtc);
278 benchmark.addPlanner(rlrt);
279 benchmark.addPlanner(birlrt);
280 benchmark.addPlanner(stride);
281 benchmark.addPlanner(kpiece);
282 benchmark.addPlanner(bkpiece);
283 benchmark.addPlanner(xxl);
284 benchmark.addPlanner(xxl1);
285 benchmark.addPlanner(tsrrt);
288 { postRunEvent(planner, run, &problem.manipulator); });
289 benchmark.addExperimentParameter(
"num_links",
"INTEGER", boost::lexical_cast<std::string>(numLinks));
290 benchmark.addExperimentParameter(
"cells",
"INTEGER", boost::lexical_cast<std::string>(xySlices));
292 double memoryLimit = 8192.0;
294 benchmark.benchmark(request);
296 benchmark.saveResultsToFile();
301 const int numLinks = problem.manipulator.getNumLinks();
303 const char *world_file =
"world.yaml";
305 problem.world.writeWorld(world_file);
307 const double linkLength = 1.0 / numLinks;
308 const Eigen::Affine2d &basePose = problem.manipulator.getBaseFrame();
310 const char *path_file =
"manipulator_path.txt";
315 fout.open(path_file);
317 fout << numLinks <<
" " << linkLength <<
" " << basePose.translation()(0) <<
" " << basePose.translation()(1) <<
" "
318 << xySlices << std::endl;
320 for (
size_t i = 0; i < path.getStateCount(); ++i)
323 for (
size_t j = 0; j < problem.manipulator.getNumLinks(); ++j)
324 fout << angles[j] <<
" ";
330void SolveProblem(ompl::geometric::SimpleSetupPtr setup,
const Problem &problem,
double timeout,
bool write_viz_out)
333 const int numLinks = problem.manipulator.getNumLinks();
335 const int xySlices = std::max(2, numLinks / 3);
337 getXXLDecomp(setup->getSpaceInformation(), problem, xySlices)));
338 setup->setPlanner(xxl);
352 WriteVisualization(problem, pgeo, xySlices);
361void PlanarManipulatorPlanning(
const Arguments &args)
365 Problem problem = CreateProblem(args);
366 ompl::geometric::SimpleSetupPtr setup = setupOMPL(problem);
368 if (args.numRuns == 1)
369 SolveProblem(setup, problem, args.timeout, args.viz);
371 BenchmarkProblem(setup, problem, args.numRuns, args.timeout);
374int main(
int argc,
char **argv)
379 namespace po = boost::program_options;
380 po::options_description desc(
"Allowed options");
383 (
"help,?",
"Show this message")
384 (
"links,l", po::value<int>(&args.numLinks)->default_value(10),
385 "Set the number of links in the chain")
386 (
"runs,r", po::value<int>(&args.numRuns)->default_value(1),
387 "The number of times to execute the query. >1 implies benchmarking")
388 (
"timeout,t", po::value<double>(&args.timeout)->default_value(60.0),
389 "The maximum time (seconds) before failure is declared")
390 (
"problem,p", po::value<std::string>(&args.problem)->default_value(
"corridor"),
391 "The name of the problem [corridor,constricted] to solve")
392 (
"viz,v", po::bool_switch(&args.viz)->default_value(
false),
393 "Write visualization output to disk. Only works when runs = 1");
396 po::variables_map vm;
397 po::store(po::parse_command_line(argc, argv, desc), vm);
400 if (vm.count(
"help"))
402 std::cout << desc << std::endl;
405 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.