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