Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeSpacePlanner2DR.h

Go to the documentation of this file.
00001 //-*-c++-*-
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 //================ RRTNode2DR ================
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]; // 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<2> PlannerResult;
00028   NodeValue_t q;
00029   
00030   //! Constructor
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; //!< Maximum number of interpolation steps in interpolate() when @a truncate is true
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   // Interpolate along the path and check for collisions
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   // set joint angles to test the NodeValue
00200   KinematicJoint* joint = rootJ;
00201   for (unsigned int i = 0; i < N; i++) {
00202     if (!joint) { // just in case...
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   // for check component
00213   LinkObstacle collisionObs;
00214   
00215   // create and assign array of joints
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     // if the joint has no boundingbox at all, skip it
00226     if (!obs[i].setObstacle(worldT))
00227       continue;
00228     
00229     // test if new joint obstacle collides with any other joint obstacle
00230     std::vector<int> collidingJObs;
00231     for (int j = 0; j < (int)i-1; j++) { // i-1 so that we don't check adjacent joint collision
00232       if (obs[j].valid && obs[i].collides(obs[j])) {
00233         collidingJObs.push_back(j);
00234       }
00235     }
00236     
00237     // test if new joint obstacle collides with any planner obstacle
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     // if there are no collisions at all, skip to the next joint
00246     if (collidingJObs.empty() && collidingPObs.empty())
00247       continue;
00248     
00249     /* Assuming there is any collision, we now test each LinkComponent,
00250      so we need to assign a vector of components, including the
00251      joint's own obstacle */
00252     JointObstacle jointOwnObs(obs[i].joint);
00253     jointOwnObs.setObstacle(worldT, true); // true flag specifies we're using the LinkComponent BB, (without children)
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     // if there is a collision with a joint obstacle, check the sub-components to confirm
00262     for (unsigned int jObs = 0; jObs < collidingJObs.size(); jObs++) {
00263       unsigned int numComponents = obs[collidingJObs[jObs]].joint->components.size();
00264       
00265       // if there aren't any subcomponents in either, then there must be a collision
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       // set the second joint's components
00275       // but whenever one is added, check for collision with previous
00276       JointObstacle collidingOwnObs(obs[collidingJObs[jObs]]);
00277       collidingOwnObs.setObstacle(worldT, true);
00278       
00279       // check if both joints' own obstacles collide
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       // check if the colliding joint's own obstacle collides with joint's components
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       // check if any of the colliding joint's components collides with the joint's own obstacle
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         // check if any of both joints' components collide
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     // if there is a collision with a planner obstacle, check the subcomponents to confirm
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   // no collision detected
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 //================ ShapeSpacePlanner2DR ================
00386 
00387 //! Plans a path in a n-dimensional angular space, uses forward kinematics for collision testing
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   //! Populates a Shape<GraphicsData> with BoundingBoxes
00429   void plotTree(const std::vector<NodeType_t> &tree,
00430                 Shape<GraphicsData> &graphics,
00431                 rgb color=rgb(255,0,0));
00432   
00433   //! Populates a Shape<GraphicsData> with BoundingBoxes
00434   void plotPath(const std::vector<NodeValue_t> &tree,
00435                 Shape<GraphicsData> &graphics,
00436                 rgb color=rgb(255,0,0));
00437   
00438   //! Returns BoundingBox of each link, for plotTree()
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     // set joint values
00491     for (size_t j = 0; j < N; j++)
00492       joints[j]->setQ(tree[i].q[j]);
00493     
00494     // get bounding box of every link
00495     std::vector<std::vector<std::pair<float,float> > > boxes;
00496     getBoxes(boxes, *joints[0]);
00497     
00498     // add to element
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     // set joint values
00511     for (size_t j = 0; j < N; j++)
00512       joints[j]->setQ(path[i][j]);
00513     
00514     // set robot transformation in WorldSpace (converts from BaseFrame -> "WorldFrame")
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     // get bounding box of every link
00520     std::vector<std::vector<std::pair<float,float> > > boxes;
00521     getBoxes(boxes, *joints[0]);
00522     
00523     // set first and last to different colors
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     // else if ((double)i == (double)(2*path.size())/5) theColor = color;
00528     // else if ((double)i == (double)(4*path.size())/5) theColor = color;
00529     else theColor = color;
00530     
00531     // add to element
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   // we don't have to go through all branches, because we already cloned the branch
00541   if (joint.nextJoint() != NULL)
00542     getBoxes(boxes, *joint.nextJoint());
00543   
00544   // get the joint's BB (in obstacle format)
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     // set points
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   // do the same for each link
00559   for (KinematicJoint::component_iterator it = joint.components.begin(); it != joint.components.end(); ++it) {
00560     // set points
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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:50 2016 by Doxygen 1.6.3