37 #include "ConstrainedPlanningCommon.h"
48 Wall(
double offset,
double thickness,
double width,
double joint_radius,
unsigned int type)
49 : offset_(offset), thickness_(thickness + joint_radius), width_(width + joint_radius), type_(type)
56 bool within(
double x)
const
58 return !(x < (offset_ - thickness_) || x > (offset_ + thickness_));
61 bool checkJoint(
const Eigen::Ref<const Eigen::VectorXd> &v)
const
63 double x = v[0], y = v[1], z = v[2];
89 const double thickness_;
91 const unsigned int type_;
94 const double WALL_WIDTH = 0.5;
95 const double JOINT_RADIUS = 0.2;
96 const double LINK_LENGTH = 1.0;
111 ChainConstraint(
unsigned int links,
unsigned int obstacles = 0,
unsigned int extra = 1)
114 , length_(LINK_LENGTH)
117 , jointRadius_(JOINT_RADIUS)
118 , obstacles_(obstacles)
121 double step = 2 * radius_ / (double)(obstacles_ + 1);
122 double current = -radius_ + step;
124 for (
unsigned int i = 0; i < obstacles_; i++, current += step)
125 walls_.emplace_back(current, radius_ / 8, WALL_WIDTH, JOINT_RADIUS, i % 2);
128 void function(
const Eigen::Ref<const Eigen::VectorXd> &x, Eigen::Ref<Eigen::VectorXd> out)
const override
130 Eigen::VectorXd joint1 = Eigen::VectorXd::Zero(3);
131 for (
unsigned int i = 0; i < links_; i++)
133 auto &&joint2 = x.segment(3 * i, 3);
134 out[i] = (joint1 - joint2).norm() - length_;
139 out[links_] = x.tail(3).norm() - radius_;
141 const unsigned int o = links_ - 5;
144 out[links_ + 1] = x[(o + 0) * 3 + 2] - x[(o + 1) * 3 + 2];
146 out[links_ + 2] = x[(o + 1) * 3 + 0] - x[(o + 2) * 3 + 0];
148 out[links_ + 3] = x[(o + 2) * 3 + 2] - x[(o + 3) * 3 + 2];
151 void jacobian(
const Eigen::Ref<const Eigen::VectorXd> &x, Eigen::Ref<Eigen::MatrixXd> out)
const override
155 Eigen::VectorXd plus(3 * (links_ + 1));
156 plus.head(3 * links_) = x.segment(0, 3 * links_);
157 plus.tail(3) = Eigen::VectorXd::Zero(3);
159 Eigen::VectorXd minus(3 * (links_ + 1));
160 minus.head(3) = Eigen::VectorXd::Zero(3);
161 minus.tail(3 * links_) = x.segment(0, 3 * links_);
163 auto &&diagonal = plus - minus;
165 for (
unsigned int i = 0; i < links_; i++)
166 out.row(i).segment(3 * i + 0, 3) = diagonal.segment(3 * i, 3).normalized();
168 out.block(1, 0, links_ - 1, 3 * links_ - 3) -= out.block(1, 3, links_ - 1, 3 * links_ - 3);
171 out.row(links_).tail(3) = -diagonal.tail(3).normalized().transpose();
173 const unsigned int o = links_ - 5;
177 out(links_ + 1, (o + 0) * 3 + 2) = 1;
178 out(links_ + 1, (o + 1) * 3 + 2) = -1;
182 out(links_ + 2, (o + 1) * 3 + 0) = 1;
183 out(links_ + 2, (o + 2) * 3 + 0) = -1;
187 out(links_ + 3, (o + 2) * 3 + 2) = 1;
188 out(links_ + 3, (o + 3) * 3 + 2) = -1;
199 for (
unsigned int i = 0; i < links_; i++)
201 auto &&joint = x.segment(3 * i, 3);
205 if (joint.norm() >= (radius_ - jointRadius_))
206 for (
auto wall : walls_)
207 if (!wall.checkJoint(joint))
211 for (
unsigned int i = 0; i < links_ - 1; i++)
213 auto &&joint1 = x.segment(3 * i, 3);
214 if (joint1.cwiseAbs().maxCoeff() < jointRadius_)
217 for (
unsigned int j = i + 1; j < links_; j++)
219 auto &&joint2 = x.segment(3 * j, 3);
220 if ((joint1 - joint2).cwiseAbs().maxCoeff() < jointRadius_)
228 ob::StateSpacePtr createSpace()
const
230 auto rvss = std::make_shared<ob::RealVectorStateSpace>(3 * links_);
233 for (
int i = 0; i < (int)links_; ++i)
235 bounds.setLow(3 * i + 0, -i - 1);
236 bounds.setHigh(3 * i + 0, i + 1);
238 bounds.setLow(3 * i + 1, -i - 1);
239 bounds.setHigh(3 * i + 1, i + 1);
241 bounds.setLow(3 * i + 2, -i - 1);
242 bounds.setHigh(3 * i + 2, i + 1);
245 rvss->setBounds(bounds);
249 void setStartAndGoalStates(Eigen::VectorXd &start, Eigen::VectorXd &goal)
const
251 start = Eigen::VectorXd(3 * links_);
252 goal = Eigen::VectorXd(3 * links_);
255 for (; i < (int)links_ - 3; ++i)
257 start[3 * i] = i + 1;
258 start[3 * i + 1] = 0;
259 start[3 * i + 2] = 0;
261 goal[3 * i] = -(i + 1);
267 start[3 * i + 1] = -1;
268 start[3 * i + 2] = 0;
277 start[3 * i + 1] = -1;
278 start[3 * i + 2] = 0;
286 start[3 * i] = i - 1;
287 start[3 * i + 1] = 0;
288 start[3 * i + 2] = 0;
290 goal[3 * i] = -(i - 1);
298 ob::ProjectionEvaluatorPtr getProjection(ob::StateSpacePtr space)
const
303 ChainProjection(
const ob::StateSpacePtr &space,
unsigned int links,
double radius)
304 :
ob::ProjectionEvaluator(space), links_(links), radius_(radius)
308 unsigned int getDimension()
const override
313 void defaultCellSizes()
override
315 cellSizes_.resize(2);
320 void project(
const ob::State *state, Eigen::Ref<Eigen::VectorXd> projection)
const override
323 const unsigned int s = 3 * (links_ - 1);
325 projection(0) = atan2(x[s + 1], x[s]);
326 projection(1) = acos(x[s + 2] / radius_);
330 const unsigned int links_;
334 return std::make_shared<ChainProjection>(space, links_, radius_);
337 void dump(std::ofstream &file)
const
339 file << links_ << std::endl;
340 file << obstacles_ << std::endl;
341 file << extra_ << std::endl;
342 file << jointRadius_ << std::endl;
343 file << length_ << std::endl;
344 file << radius_ << std::endl;
345 file << width_ << std::endl;
356 const unsigned int links_;
357 const double length_;
359 const double radius_;
360 const double jointRadius_;
361 const unsigned int obstacles_;
362 const unsigned int extra_;
363 std::vector<Wall> walls_;
366 bool chainPlanningOnce(
ConstrainedProblem &cp,
enum PLANNER_TYPE planner,
bool output)
368 cp.setPlanner(planner,
"chain");
375 OMPL_INFORM(
"Dumping problem information to `chain_info.txt`.");
376 std::ofstream infofile(
"chain_info.txt");
377 infofile << cp.type << std::endl;
378 dynamic_cast<ChainConstraint *
>(cp.constraint.get())->dump(infofile);
387 bool chainPlanningBench(
ConstrainedProblem &cp, std::vector<enum PLANNER_TYPE> &planners)
389 cp.setupBenchmark(planners,
"chain");
391 auto chain =
dynamic_cast<ChainConstraint *
>(cp.constraint.get());
392 chain->addBenchmarkParameters(cp.bench);
399 bool chainPlanning(
bool output,
enum SPACE_TYPE space, std::vector<enum PLANNER_TYPE> &planners,
unsigned int links,
404 auto constraint = std::make_shared<ChainConstraint>(links, obstacles, extra);
407 cp.setConstrainedOptions(c_opt);
408 cp.setAtlasOptions(a_opt);
410 cp.css->registerProjection(
"chain", constraint->getProjection(cp.css));
412 Eigen::VectorXd start, goal;
413 constraint->setStartAndGoalStates(start, goal);
415 cp.setStartAndGoalStates(start, goal);
416 cp.ss->setStateValidityChecker(std::bind(&ChainConstraint::isValid, constraint, std::placeholders::_1));
419 return chainPlanningOnce(cp, planners[0], output);
421 return chainPlanningBench(cp, planners);
424 auto help_msg =
"Shows this help message.";
425 auto output_msg =
"Dump found solution path (if one exists) in plain text to `chain_path.txt`. "
426 "Problem information is dumped to `chain_info`.txt";
427 auto links_msg =
"Number of links in the kinematic chain. Minimum is 4.";
428 auto obstacles_msg =
"Number of `wall' obstacles on the surface of the sphere. Ranges from [0, 2]";
429 auto extra_msg =
"Number of extra constraints to add to the chain. Extra constraints are as follows:\n"
430 "1: End-effector is constrained to be on the surface of a sphere of radius links - 2\n"
431 "2: (links-5)th and (links-4)th ball have the same z-value\n"
432 "3: (links-4)th and (links-3)th ball have the same x-value\n"
433 "4: (links-3)th and (links-2)th ball have the same z-value";
434 auto bench_msg =
"Do benchmarking on provided planner list.";
436 int main(
int argc,
char **argv)
439 enum SPACE_TYPE space = PJ;
440 std::vector<enum PLANNER_TYPE> planners = {RRT};
442 unsigned int links = 5;
443 unsigned int obstacles = 0;
444 unsigned int extra = 1;
449 po::options_description desc(
"Options");
450 desc.add_options()(
"help,h", help_msg);
451 desc.add_options()(
"output,o", po::bool_switch(&output)->default_value(
false), output_msg);
452 desc.add_options()(
"links,l", po::value<unsigned int>(&links)->default_value(5), links_msg);
453 desc.add_options()(
"obstacles,x", po::value<unsigned int>(&obstacles)->default_value(0), obstacles_msg);
454 desc.add_options()(
"extra,e", po::value<unsigned int>(&extra)->default_value(1), extra_msg);
455 desc.add_options()(
"bench", po::bool_switch(&bench)->default_value(
false), bench_msg);
457 addSpaceOption(desc, &space);
458 addPlannerOption(desc, &planners);
459 addConstrainedOptions(desc, &c_opt);
460 addAtlasOptions(desc, &a_opt);
462 po::variables_map vm;
463 po::store(po::parse_command_line(argc, argv, desc), vm);
466 if (vm.count(
"help") != 0u)
468 std::cout << desc << std::endl;
472 chainPlanning(output, space, planners, links, obstacles, extra, c_opt, a_opt, bench);