Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeSpacePlanner3DR.h

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

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:52 2012 by Doxygen 1.6.3