00001
00002 #ifndef _SHAPE_SPACE_PLANNER_2DR_H_
00003 #define _SHAPE_SPACE_PLANNER_2DR_H_
00004
00005 #include "Motion/Kinematics.h"
00006 #include "Planners/RRT/ShapeSpacePlannerBase.h"
00007
00008
00009
00010 template <size_t N>
00011 class ShapeSpacePlanner2DR;
00012
00013 template <size_t N>
00014 class RRTNode2DR : public RRTNodeBase {
00015 public:
00016
00017 class NodeValueWrapper {
00018 private:
00019 AngSignPi angles[(N==0)?1:N];
00020 public:
00021 NodeValueWrapper() : angles() {}
00022 AngSignPi& operator[](int i) { return angles[i]; }
00023 AngSignPi operator[](int i) const { return angles[i]; }
00024 };
00025
00026 typedef NodeValueWrapper NodeValue_t;
00027 typedef typename GenericRRTBase::PlannerResult<2> PlannerResult;
00028 NodeValue_t q;
00029
00030
00031 RRTNode2DR(const NodeValue_t &_q, unsigned int _parent) : RRTNodeBase(_parent), q(_q) {};
00032
00033 class CollisionChecker : public ShapeSpaceCollisionCheckerBase<2> {
00034 protected:
00035 KinematicJoint* rootJ;
00036 public:
00037 fmat::Transform worldT;
00038 protected:
00039
00040 class JointObstacle {
00041 public:
00042 RectangularObstacle obstacle;
00043 KinematicJoint* joint;
00044 bool valid;
00045
00046 JointObstacle() : obstacle(), joint(), valid() {}
00047
00048 JointObstacle(KinematicJoint* _joint) : obstacle(), joint(_joint), valid(false) {
00049 obstacle.name = joint->outputOffset.get();
00050 }
00051
00052 JointObstacle(const RectangularObstacle& _obstacle,
00053 KinematicJoint* _joint,
00054 bool _valid) : obstacle(_obstacle), joint(_joint), valid(_valid) {}
00055
00056 virtual ~JointObstacle() {}
00057
00058 JointObstacle(const JointObstacle& other) : obstacle(other.obstacle), joint(other.joint), valid(other.valid) {}
00059 JointObstacle& operator=(const JointObstacle& other) {
00060 obstacle = other.obstacle;
00061 joint = other.joint;
00062 valid = other.valid;
00063 return *this;
00064 }
00065
00066 bool collides(const JointObstacle& other) const { if (!other.valid) return false; return other.obstacle.collides(obstacle); }
00067 bool collides(const PlannerObstacle2D& obs) const { return obs.collides(obstacle); }
00068
00069 virtual bool setObstacle(const fmat::Transform &t, bool own=false);
00070 };
00071
00072 class LinkObstacle : public JointObstacle {
00073 public:
00074 LinkComponent* link;
00075
00076 LinkObstacle() : JointObstacle(), link() {}
00077
00078 LinkObstacle(const JointObstacle& jObs) : JointObstacle(jObs.joint), link() {
00079 this->obstacle.name += "Component";
00080 }
00081
00082 virtual ~LinkObstacle() {}
00083
00084 void setLink(LinkComponent* _link) { link = _link; }
00085
00086 LinkObstacle(const LinkObstacle& other) : JointObstacle(other.obstacle, other.joint, other.valid), link(other.link) {}
00087 LinkObstacle& operator=(const LinkObstacle& other) {
00088 JointObstacle(other.obstacle, other.joint, other.valid);
00089 link = other.link;
00090 return *this;
00091 }
00092
00093 virtual bool setObstacle(const fmat::Transform &t, bool own=false);
00094 };
00095
00096 public:
00097 CollisionChecker(DualCoding::ShapeSpace & shs,
00098 const DualCoding::Shape<DualCoding::PolygonData> &_worldBounds,
00099 float _inflation,
00100 unsigned int effectorOffset) :
00101 ShapeSpaceCollisionCheckerBase<2>(shs, _worldBounds, _inflation), rootJ(), worldT() {
00102 rootJ = kine->getKinematicJoint(effectorOffset)->cloneBranch();
00103 for (unsigned int i = 0; i < N; i++)
00104 if ( rootJ )
00105 rootJ = rootJ->getNextMobileAncestor();
00106 else
00107 std::cout << "Error: ShapSpacePlanner2DR CollisionChecker constructor ran out of joints!" << std::endl;
00108 }
00109
00110 CollisionChecker(const CollisionChecker& other) : rootJ(other.rootJ) {}
00111
00112 CollisionChecker operator=(const CollisionChecker& other) {
00113 rootJ = other.rootJ;
00114 return *this;
00115 }
00116
00117 virtual bool collides(const NodeValue_t &qnew, PlannerResult* result=NULL) const;
00118
00119 template<class T, class U>
00120 static bool checkComponent(std::vector<T>& full, const U& newObs, T& collisionObs);
00121
00122 };
00123
00124 static const unsigned int maxInterpolations = 100;
00125
00126 virtual float distance(const NodeValue_t &target);
00127 static void generateSample(const NodeValue_t &lower, const NodeValue_t &upper, NodeValue_t &sample);
00128 static Interp_t interpolate(const NodeValue_t &start, const NodeValue_t &target, const NodeValue_t &interp,
00129 bool truncate, CollisionChecker *cc, NodeValue_t &reached, bool fromOtherTree);
00130
00131 virtual std::string toString() const;
00132 };
00133
00134 template<size_t N>
00135 float RRTNode2DR<N>::distance(const NodeValue_t &target) {
00136 float result = 0;
00137 for (size_t i = 0; i < N; i++) {
00138 result += target[i]*target[i];
00139 }
00140 return result;
00141 }
00142
00143 template<size_t N>
00144 void RRTNode2DR<N>::generateSample(const NodeValue_t &lower,
00145 const NodeValue_t &upper,
00146 NodeValue_t &sample) {
00147 for (size_t i = 0; i < N; i++) {
00148 sample[i] = randRange(lower[i], upper[i]);
00149 }
00150 }
00151
00152 template<size_t N>
00153 RRTNodeBase::Interp_t RRTNode2DR<N>::interpolate(const NodeValue_t &start, const NodeValue_t &target, const NodeValue_t &interp,
00154 bool truncate, CollisionChecker *cc, NodeValue_t &reached, bool fromOtherTree) {
00155 NodeValue_t delta;
00156 int numSteps = 0;
00157 for (size_t i = 0; i < N; i++) {
00158 int steps = int(fabs(target[i]-start[i])/interp[i]);
00159 if (steps > numSteps)
00160 numSteps = steps;
00161 }
00162 for (size_t i = 0; i < N; i++) {
00163 delta[i] = (target[i]-start[i])/float(numSteps);
00164 }
00165
00166 bool truncated = (unsigned int)numSteps > maxInterpolations && truncate;
00167 if ( truncated )
00168 numSteps = maxInterpolations;
00169
00170
00171 reached = start;
00172 for (int t = 0; t < numSteps; t++) {
00173 for (unsigned int i = 0; i < N; i++) {
00174 reached[i] += delta[i];
00175 }
00176 if ( cc->collides(reached) )
00177 return COLLISION;
00178 }
00179
00180 if ( !truncated )
00181 return REACHED;
00182 else
00183 return APPROACHED;
00184 }
00185
00186 template<size_t N>
00187 std::string RRTNode2DR<N>::toString() const {
00188 char buff[100];
00189 string result;
00190 for (size_t i = 0; i < N; i++) {
00191 sprintf(buff, "%7.2f ", float(q[i]));
00192 result.append(result);
00193 }
00194 return result;
00195 }
00196
00197 template<size_t N>
00198 bool RRTNode2DR<N>::CollisionChecker::collides(const NodeValue_t &qnew, RRTNode2DR<N>::PlannerResult* result) const {
00199
00200 KinematicJoint* joint = rootJ;
00201 for (unsigned int i = 0; i < N; i++) {
00202 if (!joint) {
00203 std::cout << "*** ERROR: Collision checker cannot find arm joints. Assuming collision." << std::endl;
00204 return true;
00205 }
00206
00207 joint->setQ(qnew[i]);
00208 joint = joint->nextJoint();
00209 while (joint != NULL && joint->isMobile() == false) joint = joint->nextJoint();
00210 }
00211
00212
00213 LinkObstacle collisionObs;
00214
00215
00216 std::vector<JointObstacle> obs;
00217 for (joint = rootJ; joint != NULL; joint = joint->nextJoint()) {
00218 obs.push_back(JointObstacle(joint));
00219 for (KinematicJoint::branch_iterator it = joint->getBranches().begin(); it != joint->getBranches().end(); ++it) {
00220 obs.push_back(JointObstacle(*it));
00221 }
00222 }
00223
00224 for (unsigned int i = 0; i < obs.size(); i++) {
00225
00226 if (!obs[i].setObstacle(worldT))
00227 continue;
00228
00229
00230 std::vector<int> collidingJObs;
00231 for (int j = 0; j < (int)i-1; j++) {
00232 if (obs[j].valid && obs[i].collides(obs[j])) {
00233 collidingJObs.push_back(j);
00234 }
00235 }
00236
00237
00238 std::vector<PlannerObstacle2D*> collidingPObs;
00239 for (unsigned int k = 0; k < obstacles.size(); k++) {
00240 if ((i != 0 || !(obstacles[k]->isBodyObstacle())) && obs[i].collides(*(obstacles[k]))) {
00241 collidingPObs.push_back(obstacles[k]);
00242 }
00243 }
00244
00245
00246 if (collidingJObs.empty() && collidingPObs.empty())
00247 continue;
00248
00249
00250
00251
00252 JointObstacle jointOwnObs(obs[i].joint);
00253 jointOwnObs.setObstacle(worldT, true);
00254
00255 std::vector<LinkObstacle> componentObs(obs[i].joint->components.size(), LinkObstacle(obs[i]));
00256 for (unsigned int c = 0; c < obs[i].joint->components.size(); c++) {
00257 componentObs[c].setLink(&(obs[i].joint->components[c]));
00258 componentObs[c].setObstacle(worldT, true);
00259 }
00260
00261
00262 for (unsigned int jObs = 0; jObs < collidingJObs.size(); jObs++) {
00263 unsigned int numComponents = obs[collidingJObs[jObs]].joint->components.size();
00264
00265
00266 if (componentObs.size() == 0 && numComponents == 0) {
00267 if (result) {
00268 result->movingObstacle = new RectangularObstacle(obs[i].obstacle);
00269 result->collidingObstacle = new RectangularObstacle(obs[collidingJObs[jObs]].obstacle);
00270 }
00271 return true;
00272 }
00273
00274
00275
00276 JointObstacle collidingOwnObs(obs[collidingJObs[jObs]]);
00277 collidingOwnObs.setObstacle(worldT, true);
00278
00279
00280 if (collidingOwnObs.collides(jointOwnObs)) {
00281 if (result) {
00282 result->movingObstacle = new RectangularObstacle(collidingOwnObs.obstacle);
00283 result->collidingObstacle = new RectangularObstacle(jointOwnObs.obstacle);
00284 }
00285 return true;
00286 }
00287
00288 if (checkComponent(componentObs, collidingOwnObs, collisionObs)) {
00289 if (result) {
00290 result->movingObstacle = new RectangularObstacle(collidingOwnObs.obstacle);
00291 result->collidingObstacle = new RectangularObstacle(collisionObs.obstacle);
00292 }
00293 return true;
00294 }
00295
00296
00297 LinkObstacle componentOb(obs[collidingJObs[jObs]]);
00298 for (unsigned int c = 0; i < numComponents; c++) {
00299 componentOb.setLink(&(obs[collidingJObs[jObs]].joint->components[c]));
00300 componentOb.setObstacle(worldT, true);
00301 if (componentOb.collides(jointOwnObs)) {
00302 if (result) {
00303 result->movingObstacle = new RectangularObstacle(componentOb.obstacle);
00304 result->collidingObstacle = new RectangularObstacle(jointOwnObs.obstacle);
00305 }
00306 return true;
00307 }
00308
00309
00310 if (checkComponent(componentObs, componentOb, collisionObs)) {
00311 if (result) {
00312 result->movingObstacle = new RectangularObstacle(componentOb.obstacle);
00313 result->collidingObstacle = new RectangularObstacle(collisionObs.obstacle);
00314 }
00315 return true;
00316 }
00317 }
00318 }
00319
00320
00321 for (unsigned int p = 0; p < collidingPObs.size(); p++) {
00322 if ((i != 0 || !(collidingPObs[p]->isBodyObstacle())) && jointOwnObs.collides(*(collidingPObs[p]))) {
00323 if (result) {
00324 result->movingObstacle = new RectangularObstacle(jointOwnObs.obstacle);
00325 result->collidingObstacle = collidingPObs[p];
00326 }
00327 return true;
00328 }
00329 if ((i != 0 || !(collidingPObs[p]->isBodyObstacle())) && checkComponent(componentObs, *(collidingPObs[p]), collisionObs)) {
00330 if (result) {
00331 result->movingObstacle = new RectangularObstacle(collisionObs.obstacle);
00332 result->collidingObstacle = collidingPObs[p];
00333 }
00334 return true;
00335 }
00336 }
00337 }
00338
00339
00340 return false;
00341 }
00342
00343 template<size_t N>
00344 template<class T, class U>
00345 bool RRTNode2DR<N>::CollisionChecker::checkComponent(std::vector<T>& full, const U& newObs, T& collisionObs) {
00346 for (unsigned int i = 0; i < full.size(); i++) {
00347 if (full[i].collides(newObs)) {
00348 collisionObs = full[i];
00349 return true;
00350 }
00351 }
00352 return false;
00353 }
00354
00355 template<size_t N>
00356 bool RRTNode2DR<N>::CollisionChecker::JointObstacle::setObstacle(const fmat::Transform &t, bool own) {
00357 if (joint == NULL) {
00358 std::cout << "***ERROR Joint value is null in CollisionChecker." << std::endl;
00359 valid = false;
00360 }
00361 else {
00362 if (own)
00363 valid = joint->getOwnBB2D(t * joint->getFullT(), obstacle);
00364 else
00365 valid = joint->getBB2D(t * joint->getFullT(), obstacle);
00366 }
00367 return valid;
00368 }
00369
00370 template<size_t N>
00371 bool RRTNode2DR<N>::CollisionChecker::LinkObstacle::setObstacle(const fmat::Transform &t, bool own) {
00372 if (this->joint == NULL || link == NULL) {
00373 std::cout << "***ERROR Joint/link value is null in CollisionChecker." << std::endl;
00374 this->valid = false;
00375 }
00376 else {
00377 if (own)
00378 this->valid = link->getOwnBB2D(t * this->joint->getFullT(), this->obstacle);
00379 else
00380 this->valid = link->getBB2D(t * this->joint->getFullT(), this->obstacle);
00381 }
00382 return this->valid;
00383 }
00384
00385
00386
00387
00388 template <size_t N>
00389 class ShapeSpacePlanner2DR : public GenericRRT<RRTNode2DR<N>, 2> {
00390 public:
00391 typedef RRTNode2DR<N> NodeType_t;
00392 typedef typename NodeType_t::NodeValue_t NodeValue_t;
00393 typedef typename GenericRRTBase::PlannerResult<2> PlannerResult;
00394
00395 ShapeSpacePlanner2DR(DualCoding::ShapeSpace &shs,
00396 const DualCoding::Shape<DualCoding::PolygonData> &worldBounds,
00397 float inflation,
00398 unsigned int effectorOffset,
00399 AdmissibilityPredicate<NodeType_t> *predicate=NULL);
00400
00401 ShapeSpacePlanner2DR(const ShapeSpacePlanner2DR& other) {
00402 for (size_t i = 0; i < N; i++)
00403 joints[i] = other.joints[i];
00404 }
00405
00406 ShapeSpacePlanner2DR operator=(const ShapeSpacePlanner2DR& other) {
00407 for (size_t i = 0; i < N; i++)
00408 joints[i] = other.joints[i];
00409 return *this;
00410 }
00411
00412 KinematicJoint* joints[N];
00413 fmat::Transform worldT;
00414
00415 virtual ~ShapeSpacePlanner2DR() {}
00416
00417 using GenericRRT<NodeType_t, 2>::planPath;
00418 PlannerResult
00419 planPath(NodeValue_t start,
00420 NodeValue_t end,
00421 NodeValue_t interpolationStep,
00422 const fmat::Transform& _worldT,
00423 unsigned int _maxIterations=40000,
00424 std::vector<NodeValue_t> *pathResult=NULL,
00425 std::vector<NodeType_t> *treeStartResult=NULL,
00426 std::vector<NodeType_t> *treeEndResult=NULL);
00427
00428
00429 void plotTree(const std::vector<NodeType_t> &tree,
00430 Shape<GraphicsData> &graphics,
00431 rgb color=rgb(255,0,0));
00432
00433
00434 void plotPath(const std::vector<NodeValue_t> &tree,
00435 Shape<GraphicsData> &graphics,
00436 rgb color=rgb(255,0,0));
00437
00438
00439 void getBoxes(std::vector<std::vector<std::pair<float,float> > >& boxes, const KinematicJoint& joint);
00440
00441 };
00442
00443 template<size_t N>
00444 ShapeSpacePlanner2DR<N>::ShapeSpacePlanner2DR(DualCoding::ShapeSpace &shs,
00445 const DualCoding::Shape<DualCoding::PolygonData> &worldBounds,
00446 float inflation,
00447 unsigned int effectorOffset,
00448 AdmissibilityPredicate<NodeType_t> *_predicate) :
00449 GenericRRT<NodeType_t, 2>::GenericRRT(new typename NodeType_t::CollisionChecker
00450 (shs, worldBounds, inflation, effectorOffset), _predicate), worldT() {
00451 KinematicJoint* joint = kine->getKinematicJoint(effectorOffset)->cloneBranch();
00452 if (joint->isMobile() == false) joint = joint->getNextMobileAncestor();
00453 NodeValue_t lower, upper;
00454
00455 for (unsigned int i = N; i > 0; i--) {
00456 if ( joint ) {
00457 lower[i-1] = joint->qmin;
00458 upper[i-1] = joint->qmax;
00459 joints[i-1] = joint;
00460 joint = joint->getNextMobileAncestor();
00461 } else
00462 std::cout << "Error: ShapeSpacePlanner2DR constructor ran out of joints!" << std::endl;
00463 }
00464
00465 this->setLimits(lower, upper);
00466 }
00467
00468 template<size_t N>
00469 typename ShapeSpacePlanner2DR<N>::PlannerResult
00470 ShapeSpacePlanner2DR<N>::planPath(NodeValue_t start,
00471 NodeValue_t end,
00472 NodeValue_t interpolationStep,
00473 const fmat::Transform& _worldT,
00474 unsigned int maxIterations,
00475 std::vector<NodeValue_t> *pathResult,
00476 std::vector<NodeType_t> *treeStartResult,
00477 std::vector<NodeType_t> *treeEndResult) {
00478 this->setInterpolation(interpolationStep);
00479 this->worldT = _worldT;
00480 this->cc->worldT = _worldT;
00481 return GenericRRT<NodeType_t, 2>::planPath(start, end, maxIterations,
00482 pathResult, treeStartResult, treeEndResult);
00483 }
00484
00485 template<size_t N>
00486 void ShapeSpacePlanner2DR<N>::plotTree(const std::vector<NodeType_t> &tree,
00487 Shape<GraphicsData> &graphics,
00488 rgb color) {
00489 for ( unsigned int i = 0; i < tree.size(); i++ ) {
00490
00491 for (size_t j = 0; j < N; j++)
00492 joints[j]->setQ(tree[i].q[j]);
00493
00494
00495 std::vector<std::vector<std::pair<float,float> > > boxes;
00496 getBoxes(boxes, *joints[0]);
00497
00498
00499 for (size_t b = 0; b < boxes.size(); b++) {
00500 graphics->add(new GraphicsData::PolygonElement("link", boxes[b], true, color));
00501 }
00502 }
00503 }
00504
00505 template<size_t N>
00506 void ShapeSpacePlanner2DR<N>::plotPath(const std::vector<NodeValue_t> &path,
00507 Shape<GraphicsData> &graphics,
00508 rgb color) {
00509 for ( unsigned int i = 0; i < path.size(); i++ ) {
00510
00511 for (size_t j = 0; j < N; j++)
00512 joints[j]->setQ(path[i][j]);
00513
00514
00515 DualCoding::Point p = VRmixin::theAgent->getCentroid();
00516 worldT.translation() = -fmat::pack(p.coordX(),p.coordY(),p.coordZ());
00517 worldT.rotation() = fmat::rotationZ(-VRmixin::theAgent->getOrientation());
00518
00519
00520 std::vector<std::vector<std::pair<float,float> > > boxes;
00521 getBoxes(boxes, *joints[0]);
00522
00523
00524 rgb theColor;
00525 if (i == 0) theColor = rgb(255,0,0);
00526 else if (i == path.size()-1) theColor = rgb(255,0,255);
00527
00528
00529 else theColor = color;
00530
00531
00532 for (size_t b = 0; b < boxes.size(); b++) {
00533 graphics->add(new GraphicsData::PolygonElement("link", boxes[b], true, theColor));
00534 }
00535 }
00536 }
00537
00538 template<size_t N>
00539 void ShapeSpacePlanner2DR<N>::getBoxes(std::vector<std::vector<std::pair<float,float> > >& boxes, const KinematicJoint& joint) {
00540
00541 if (joint.nextJoint() != NULL)
00542 getBoxes(boxes, *joint.nextJoint());
00543
00544
00545 std::vector<std::pair<float,float> > points(RectangularObstacle::NUM_CORNERS);
00546 RectangularObstacle ro;
00547 joint.getOwnBB2D(worldT * joint.getFullT(), ro);
00548
00549 if (ro.getExtents() != fmat::Column<2>()) {
00550
00551 for (int p = 0; p < RectangularObstacle::NUM_CORNERS; p++) {
00552 fmat::Column<2> corner = ro.getCorner(static_cast<RectangularObstacle::CornerOrder>(p));
00553 points[p] = std::pair<float,float>(corner[0], corner[1]);
00554 }
00555 boxes.push_back(points);
00556 }
00557
00558
00559 for (KinematicJoint::component_iterator it = joint.components.begin(); it != joint.components.end(); ++it) {
00560
00561 (*it)->getOwnBB2D(worldT * joint.getFullT(), ro);
00562 for (int p = 0; p < RectangularObstacle::NUM_CORNERS; p++) {
00563 fmat::Column<2> corner = ro.getCorner(static_cast<RectangularObstacle::CornerOrder>(p));
00564 points[p] = std::pair<float,float>(corner[0], corner[1]);
00565 }
00566 boxes.push_back(points);
00567 }
00568 }
00569
00570 #endif