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