39 #include "ConstrainedPlanningCommon.h"
44 virtual void getStart(Eigen::VectorXd &x) = 0;
45 virtual void getGoal(Eigen::VectorXd &x) = 0;
51 ParallelChain(
const unsigned int n, Eigen::Vector3d offset,
unsigned int links,
unsigned int chainNum,
53 :
ob::
Constraint(n, links), offset_(std::move(offset)), links_(links), chainNum_(chainNum), length_(length)
59 void getStart(Eigen::VectorXd &x)
override
61 const double angle = boost::math::constants::pi<double>() / 16;
62 const unsigned int offset = 3 * links_ * chainNum_;
63 const Eigen::VectorXd axis =
64 Eigen::AngleAxisd(boost::math::constants::pi<double>() / 2, Eigen::Vector3d::UnitZ()) * offset_;
66 const Eigen::VectorXd step = Eigen::Vector3d::UnitZ() * length_;
67 Eigen::VectorXd joint = offset_ + Eigen::AngleAxisd(angle, axis) * step;
70 for (; i < links_; ++i)
72 x.segment(3 * i + offset, 3) = joint;
76 joint += Eigen::AngleAxisd(-angle, axis) * step;
80 void getGoal(Eigen::VectorXd &x)
override
82 unsigned int offset = 3 * links_ * chainNum_;
86 Eigen::VectorXd nstep = offset_ * length_;
87 Eigen::VectorXd estep =
88 Eigen::AngleAxisd(boost::math::constants::pi<double>() / 2, Eigen::Vector3d::UnitZ()) * offset_ *
90 Eigen::VectorXd sstep =
91 Eigen::AngleAxisd(boost::math::constants::pi<double>(), Eigen::Vector3d::UnitZ()) * offset_ * length_;
92 Eigen::VectorXd wstep =
93 Eigen::AngleAxisd(3 * boost::math::constants::pi<double>() / 2, Eigen::Vector3d::UnitZ()) * offset_ *
96 Eigen::VectorXd joint = offset_ + nstep;
97 x.segment(3 * 0 + offset, 3) = joint;
98 x.segment(3 * 1 + offset, 3) = x.segment(3 * 0 + offset, 3) + estep;
99 x.segment(3 * 2 + offset, 3) = x.segment(3 * 1 + offset, 3) + estep;
100 x.segment(3 * 3 + offset, 3) = x.segment(3 * 2 + offset, 3) + Eigen::Vector3d::UnitZ() * length_;
101 x.segment(3 * 4 + offset, 3) = x.segment(3 * 3 + offset, 3) + sstep;
102 x.segment(3 * 5 + offset, 3) = x.segment(3 * 4 + offset, 3) + sstep;
103 x.segment(3 * 6 + offset, 3) = x.segment(3 * 5 + offset, 3) + wstep;
107 Eigen::VectorXd step = offset_ * length_;
108 Eigen::VectorXd joint = offset_ + step;
111 for (; i < links_ / 2; ++i, joint += step)
112 x.segment(3 * i + offset, 3) = joint;
114 joint += Eigen::Vector3d::UnitZ() * length_ - step;
115 for (; i < links_; ++i, joint -= step)
116 x.segment(3 * i + offset, 3) = joint;
120 Eigen::Ref<const Eigen::VectorXd> getLink(
const Eigen::VectorXd &x,
const unsigned int idx)
const
122 const unsigned int offset = 3 * links_ * chainNum_;
123 return x.segment(offset + 3 * idx, 3);
126 void function(
const Eigen::Ref<const Eigen::VectorXd> &x, Eigen::Ref<Eigen::VectorXd> out)
const override
128 unsigned int idx = 0;
130 Eigen::VectorXd j1 = offset_;
131 for (
unsigned int i = 0; i < links_; ++i)
133 const Eigen::VectorXd j2 = getLink(x, i);
134 out[idx++] = (j1 - j2).norm() - length_;
139 void jacobian(
const Eigen::Ref<const Eigen::VectorXd> &x, Eigen::Ref<Eigen::MatrixXd> out)
const override
141 const unsigned int offset = 3 * links_ * chainNum_;
144 Eigen::VectorXd plus(3 * (links_ + 1));
145 plus.head(3 * links_) = x.segment(offset, 3 * links_);
146 plus.tail(3) = Eigen::VectorXd::Zero(3);
148 Eigen::VectorXd minus(3 * (links_ + 1));
149 minus.head(3) = offset_;
150 minus.tail(3 * links_) = x.segment(offset, 3 * links_);
152 const Eigen::VectorXd diagonal = plus - minus;
154 for (
unsigned int i = 0; i < links_; i++)
155 out.row(i).segment(3 * i + offset, 3) = diagonal.segment(3 * i, 3).normalized();
157 out.block(1, offset, links_ - 1, 3 * links_ - 3) -= out.block(1, offset + 3, links_ - 1, 3 * links_ - 3);
161 const Eigen::Vector3d offset_;
162 const unsigned int links_;
163 const unsigned int chainNum_;
164 const double length_;
167 class ParallelPlatform :
public ob::Constraint,
public ParallelBase
170 ParallelPlatform(
unsigned int links,
unsigned int chains,
double radius = 1)
171 :
ob::
Constraint(3 * links * chains, chains), links_(links), chains_(chains), radius_(radius)
180 Eigen::Ref<const Eigen::VectorXd> getTip(
const Eigen::VectorXd &x,
unsigned int id)
const
182 return x.segment(3 * links_ * ((
id % chains_) + 1) - 3, 3);
185 void function(
const Eigen::Ref<const Eigen::VectorXd> &x, Eigen::Ref<Eigen::VectorXd> out)
const override
189 out[0] = (getTip(x, 0) - getTip(x, 1)).norm() - radius_ * 2;
193 unsigned int idx = 0;
195 Eigen::Vector3d centroid = Eigen::Vector3d::Zero();
196 for (
unsigned int i = 0; i < chains_; ++i)
197 centroid += getTip(x, i);
200 for (
unsigned int i = 0; i < chains_; ++i)
201 out[idx++] = (centroid - getTip(x, i)).norm() - radius_;
203 for (
unsigned int i = 0; i < chains_ - 3; ++i)
205 const Eigen::Vector3d ab = getTip(x, i + 1) - getTip(x, i);
206 const Eigen::Vector3d ac = getTip(x, i + 2) - getTip(x, i);
207 const Eigen::Vector3d ad = getTip(x, i + 3) - getTip(x, i);
209 out[idx++] = ad.dot(ab.cross(ac));
213 void getStart(Eigen::VectorXd &)
override
217 void getGoal(Eigen::VectorXd &)
override
222 const unsigned int links_;
223 const unsigned int chains_;
224 const double radius_;
230 ParallelConstraint(
unsigned int links,
unsigned int chains,
double radius = 1,
double length = 1,
231 double jointRadius = 0.2)
237 , jointRadius_(jointRadius)
239 Eigen::Vector3d offset = Eigen::Vector3d::UnitX();
240 for (
unsigned int i = 0; i < chains_; ++i)
242 addConstraint(std::make_shared<ParallelChain>(chains * links * 3, offset, links, i, length));
244 Eigen::AngleAxisd(2 * boost::math::constants::pi<double>() / (
double)chains, Eigen::Vector3d::UnitZ()) *
248 addConstraint(std::make_shared<ParallelPlatform>(links, chains, radius));
251 void getStart(Eigen::VectorXd &x)
override
253 x = Eigen::VectorXd(3 * links_ * chains_);
254 for (
auto &constraint : constraints_)
255 std::dynamic_pointer_cast<ParallelBase>(constraint)->getStart(x);
258 void getGoal(Eigen::VectorXd &x)
override
260 x = Eigen::VectorXd(3 * links_ * chains_);
261 for (
auto &constraint : constraints_)
262 std::dynamic_pointer_cast<ParallelBase>(constraint)->getGoal(x);
265 ob::StateSpacePtr createSpace()
const
267 auto rvss = std::make_shared<ob::RealVectorStateSpace>(3 * links_ * chains_);
270 for (
unsigned int c = 0; c < chains_; ++c)
272 const unsigned int o = 3 * c * links_;
273 for (
int i = 0; i < (int)links_; ++i)
275 bounds.setLow(o + 3 * i + 0, -i - 2);
276 bounds.setHigh(o + 3 * i + 0, i + 2);
278 bounds.setLow(o + 3 * i + 1, -i - 2);
279 bounds.setHigh(o + 3 * i + 1, i + 2);
281 bounds.setLow(o + 3 * i + 2, -i - 2);
282 bounds.setHigh(o + 3 * i + 2, i + 2);
286 rvss->setBounds(bounds);
294 for (
unsigned int i = 0; i < links_ * chains_; ++i)
296 if (x.segment(3 * i, 3)[2] < 0)
300 for (
unsigned int i = 0; i < links_ * chains_ - 1; ++i)
302 if (x.segment(3 * i, 3).cwiseAbs().maxCoeff() < jointRadius_)
305 for (
unsigned int j = i + 1; j < links_ * chains_; ++j)
306 if ((x.segment(3 * i, 3) - x.segment(3 * j, 3)).cwiseAbs().maxCoeff() < jointRadius_)
315 ob::ProjectionEvaluatorPtr getProjection(ob::StateSpacePtr space)
const
320 ParallelProjection(
const ob::StateSpacePtr &space,
unsigned int links,
unsigned int chains)
321 :
ob::ProjectionEvaluator(space), chains_(chains), links_(links)
325 unsigned int getDimension()
const override
330 void defaultCellSizes()
override
332 cellSizes_.resize(1);
336 void project(
const ob::State *state, Eigen::Ref<Eigen::VectorXd> projection)
const override
340 for (
unsigned int i = 0; i < chains_; ++i)
341 projection(0) = x[3 * (i + 1) * links_ - 1];
343 projection(0) /= chains_;
347 const unsigned int chains_;
348 const unsigned int links_;
351 return std::make_shared<ParallelProjection>(space, links_, chains_);
354 void dump(std::ofstream &file)
const
356 file << links_ << std::endl;
357 file << chains_ << std::endl;
358 file << jointRadius_ << std::endl;
359 file << length_ << std::endl;
360 file << radius_ << std::endl;
370 const unsigned int links_;
371 const unsigned int chains_;
372 const double radius_;
373 const double length_;
374 const double jointRadius_;
377 bool parallelPlanningOnce(
ConstrainedProblem &cp,
enum PLANNER_TYPE planner,
bool output)
379 cp.setPlanner(planner,
"parallel");
386 OMPL_INFORM(
"Dumping problem information to `parallel_info.txt`.");
387 std::ofstream infofile(
"parallel_info.txt");
388 infofile << cp.type << std::endl;
389 dynamic_cast<ParallelConstraint *
>(cp.constraint.get())->dump(infofile);
398 bool parallelPlanningBench(
ConstrainedProblem &cp, std::vector<enum PLANNER_TYPE> &planners)
400 cp.setupBenchmark(planners,
"parallel");
402 auto parallel =
dynamic_cast<ParallelConstraint *
>(cp.constraint.get());
403 parallel->addBenchmarkParameters(cp.bench);
410 bool parallelPlanning(
bool output,
enum SPACE_TYPE space, std::vector<enum PLANNER_TYPE> &planners,
unsigned int links,
414 auto constraint = std::make_shared<ParallelConstraint>(links, chains);
417 cp.setConstrainedOptions(c_opt);
418 cp.setAtlasOptions(a_opt);
420 cp.css->registerProjection(
"parallel", constraint->getProjection(cp.css));
422 Eigen::VectorXd start, goal;
423 constraint->getStart(start);
424 constraint->getGoal(goal);
426 cp.setStartAndGoalStates(start, goal);
427 cp.ss->setStateValidityChecker(std::bind(&ParallelConstraint::isValid, constraint, std::placeholders::_1));
430 return parallelPlanningOnce(cp, planners[0], output);
432 return parallelPlanningBench(cp, planners);
435 auto help_msg =
"Shows this help message.";
436 auto output_msg =
"Dump found solution path (if one exists) in plain text to `parallel_path.txt`. "
437 "Problem information is dumped to `parallel_info`.txt";
438 auto links_msg =
"Number of links in each kinematic chain. Minimum is 3. Must be odd.";
439 auto chains_msg =
"Number of chains in parallel mechanism. Minimum is 2.";
440 auto bench_msg =
"Do benchmarking on provided planner list.";
442 int main(
int argc,
char **argv)
445 enum SPACE_TYPE space = PJ;
446 std::vector<enum PLANNER_TYPE> planners = {RRT};
448 unsigned int links = 3;
449 unsigned int chains = 4;
454 po::options_description desc(
"Options");
455 desc.add_options()(
"help,h", help_msg);
456 desc.add_options()(
"output,o", po::bool_switch(&output)->default_value(
false), output_msg);
457 desc.add_options()(
"links,l", po::value<unsigned int>(&links)->default_value(3), links_msg);
458 desc.add_options()(
"chains,c", po::value<unsigned int>(&chains)->default_value(4), chains_msg);
459 desc.add_options()(
"bench", po::bool_switch(&bench)->default_value(
false), bench_msg);
461 addSpaceOption(desc, &space);
462 addPlannerOption(desc, &planners);
463 addConstrainedOptions(desc, &c_opt);
464 addAtlasOptions(desc, &a_opt);
466 po::variables_map vm;
467 po::store(po::parse_command_line(argc, argv, desc), vm);
470 if (vm.count(
"help") != 0u)
472 std::cout << desc << std::endl;
476 parallelPlanning(output, space, planners, links, chains, c_opt, a_opt, bench);