37 #ifndef PLANAR_MANIPULATOR_XXL_DECOMPOSITION_
38 #define PLANAR_MANIPULATOR_XXL_DECOMPOSITION_
40 #include <Eigen/Dense>
41 #include <ompl/base/SpaceInformation.h>
42 #include <ompl/geometric/planners/xxl/XXLPlanarDecomposition.h>
43 #include "PlanarManipulator.h"
44 #include "PlanarManipulatorStateSpace.h"
54 const int thetaSlices, std::vector<int> &projectedJoints,
bool diagonalEdges)
58 , projectedJoints_(projectedJoints)
60 if (projectedJoints_.size() == 0)
62 OMPL_WARN(
"No projected joints. Assuming end effector projection");
63 projectedJoints_.push_back(manip_->getNumLinks() - 1);
67 const std::vector<double> &linkLengths = manip_->getLinkLengths();
68 for (
size_t i = 0; i < projectedJoints_.size(); ++i)
70 if (projectedJoints_[i] >= (
int)manip_->getNumLinks())
72 if (projectedJoints_[i] < startLink)
73 throw ompl::Exception(
"Projected joints must be unique and sorted in ascending order");
75 int numLinks = projectedJoints_[i] - startLink + 1;
76 OMPL_DEBUG(
"PMXXLDecomposition: Constructing partial manipulator %lu with %d links [from links %d to %d]",
77 i, numLinks, startLink, startLink + numLinks);
78 std::vector<double> lengths(numLinks);
79 for (
int j = startLink; j < startLink + numLinks; ++j)
80 lengths[j - startLink] = linkLengths[j];
82 startLink = projectedJoints_[i] + 1;
85 partialManips_[0].setBaseFrame(manip_->getBaseFrame());
95 return (
int)projectedJoints_.size();
98 static void frameToPose(
const Eigen::Affine2d &frame, Eigen::VectorXd &pose)
100 pose = Eigen::VectorXd(3);
101 pose(0) = frame.translation()(0);
102 pose(1) = frame.translation()(1);
103 pose(2) = acos(frame.matrix()(0, 0));
107 std::vector<ompl::base::State *> &states)
const
109 if (layer >= (
int)partialManips_.size())
120 std::vector<Eigen::Affine2d> frames;
124 partialManip.setBaseFrame(frames[projectedJoints_[layer - 1]]);
128 Eigen::VectorXd angles(partialManip.getNumLinks());
135 partialManip.getNumLinks() *
sizeof(
double));
138 partialManip.getNumLinks() *
sizeof(
double));
141 Eigen::VectorXd desired(3);
142 sampleCoordinateFromRegion(r, &desired(0));
145 Eigen::Affine2d link_pose = Eigen::Affine2d::Identity();
146 link_pose.rotate(desired[2]);
147 link_pose.translation()(0) = desired[0];
148 link_pose.translation()(1) = desired[1];
150 Eigen::Affine2d current_frame;
151 partialManip.FK(angles, current_frame);
152 Eigen::VectorXd current;
153 frameToPose(current_frame, current);
155 std::vector<int> projection;
159 if (projection[layer] == r)
167 Eigen::VectorXd e(desired - current);
169 unsigned int iter = 0;
170 unsigned int maxIter = 20;
172 Eigen::MatrixXd jac = Eigen::MatrixXd::Zero(3, partialManip.getNumLinks());
173 Eigen::JacobiSVD<Eigen::MatrixXd> svd(3, partialManip.getNumLinks(), Eigen::ComputeFullU | Eigen::ComputeFullV);
174 Eigen::MatrixXd D = Eigen::MatrixXd::Zero(partialManip.getNumLinks(), 3);
176 unsigned int precedingVals = 0;
178 precedingVals = projectedJoints_[layer - 1] + 1;
181 while (projection[layer] != r && iter++ < maxIter)
183 partialManip.Jacobian(angles, jac);
188 const Eigen::JacobiSVD<Eigen::MatrixXd>::SingularValuesType &d = svd.singularValues();
191 for (
int i = 0; i < d.size(); ++i)
193 D(i, i) = 1.0 / d(i);
198 Eigen::MatrixXd jac_inv = svd.matrixV() * D * svd.matrixU().transpose();
199 Eigen::VectorXd delta_theta = jac_inv * e;
201 if (delta_theta(0) != delta_theta(0))
208 angles = angles + (alpha * delta_theta);
209 partialManip.FK(angles, current_frame);
210 frameToPose(current_frame, current);
213 e = desired - current;
220 if (precedingVals > 0)
222 precedingVals *
sizeof(
double));
225 memcpy(&values[precedingVals], &angles[0], partialManip.getNumLinks() *
sizeof(
double));
229 if (precedingVals + partialManip.getNumLinks() < manip_->getNumLinks())
232 unsigned int index = precedingVals + partialManip.getNumLinks();
233 unsigned int attempts = 5;
236 double variance = 0.025;
237 for (
unsigned int att = 0; att < attempts && !valid; ++att)
241 for (
unsigned int i = index; i < manip_->getNumLinks(); ++i)
242 values[i] = rng_.
gaussian(seed[i], variance);
244 variance += variance;
247 si_->getStateSpace()->enforceBounds(newState);
250 valid = si_->isValid(newState);
255 const ompl::base::State *previous = (states.size() == 0 ? start : states.back());
256 if (valid && si_->checkMotion(previous, newState))
259 states.push_back(newState);
264 for (
size_t i = 0; i < states.size(); ++i)
265 si_->freeState(states[i]);
273 if (projection[layer] == r)
287 void initializePartialManipulator(
int layer,
const double *seedAngles)
const
293 std::vector<Eigen::Affine2d> frames;
294 manip_->FK(seedAngles, frames);
295 partialManip.setBaseFrame(frames[projectedJoints_[layer - 1]]);
299 void sampleEndEffectorPose(
int region, Eigen::Affine2d &pose)
const
302 std::vector<double> coord;
303 sampleCoordinateFromRegion(region, coord);
306 pose = Eigen::Affine2d::Identity();
307 pose.rotate(coord[2]);
308 pose.translation()(0) = coord[0];
309 pose.translation()(1) = coord[1];
312 void initializePartialSeed(
int layer,
const double *seedAngles, std::vector<double> &partialSeed)
const
316 partialSeed.resize(partialManip.getNumLinks());
319 memcpy(&partialSeed[0], seedAngles, partialManip.getNumLinks() *
sizeof(
double));
323 for (
size_t i = 0; i < partialSeed.size(); ++i)
328 bool sampleRemainingJoints(
int layer,
ompl::base::State *s,
const double *
const seedVals,
329 const std::vector<double> &partialSln)
const
333 unsigned int precedingVals =
334 (layer > 0 ? projectedJoints_[layer - 1] + 1 : 0);
337 if (precedingVals > 0)
338 memcpy(values, seedVals, precedingVals *
sizeof(
double));
342 memcpy(&values[precedingVals], &partialSln[0], partialManip.getNumLinks() *
sizeof(
double));
344 precedingVals += partialManip.getNumLinks();
347 if (precedingVals < manip_->getNumLinks())
349 int maxAttempts = 10;
350 double variance = 0.05;
351 for (
int att = 0; att < maxAttempts; ++att)
354 for (
unsigned int i = precedingVals; i < manip_->getNumLinks(); ++i)
356 if (!seedVals || random)
359 values[i] = rng_.
gaussian(seedVals[i], variance);
362 variance += variance;
370 return si_->isValid(s);
378 if (layer >= (
int)partialManips_.size())
380 if (!seed && layer > 0)
381 throw ompl::Exception(
"You must set the seed value to sample from a layer > 0");
384 initializePartialManipulator(layer, seedVals);
387 int maxPoses = 3 * (layer + 1);
388 for (
int npose = 0; npose < maxPoses; ++npose)
390 Eigen::Affine2d link_pose;
391 sampleEndEffectorPose(r, link_pose);
395 Eigen::Affine2d frame;
396 manip_->FK(seedVals, frame);
397 double theta = rng_.
gaussian(acos(frame.matrix()(0, 0)), 0.2);
399 double diff = theta - acos(link_pose.matrix()(0, 0));
400 link_pose.rotate(diff);
403 std::vector<double> joint_seed;
404 initializePartialSeed(layer, seedVals, joint_seed);
407 std::vector<double> solution;
408 if (partialManip.FABRIK(solution, joint_seed, link_pose))
411 if (sampleRemainingJoints(layer, s, seedVals, solution))
413 si_->getStateSpace()->enforceBounds(s);
425 std::vector<Eigen::Affine2d> frames;
429 coord[0] = frames[projectedJoints_[layer]].translation()[0];
430 coord[1] = frames[projectedJoints_[layer]].translation()[1];
432 atan2(frames[projectedJoints_[layer]].matrix()(1, 0), frames[projectedJoints_[layer]].matrix()(1, 1));
438 std::vector<Eigen::Affine2d> frames;
441 layers.resize(projectedJoints_.size());
442 std::vector<double> coord(3);
443 for (
size_t i = 0; i < projectedJoints_.size(); ++i)
445 coord[0] = frames[projectedJoints_[i]].translation()[0];
446 coord[1] = frames[projectedJoints_[i]].translation()[1];
447 coord[2] = atan2(frames[projectedJoints_[i]].matrix()(1, 0), frames[projectedJoints_[i]].matrix()(1, 1));
455 mutable std::vector<PlanarManipulator> partialManips_;
456 std::vector<int> projectedJoints_;