00001
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
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];
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
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;
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
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
00194 KinematicJoint* joint = rootJ;
00195 for (unsigned int i = 0; i < N; i++) {
00196 if (!joint) {
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
00207 LinkObstacle* collisionObs = NULL;
00208
00209
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
00217 if (!obs[i].setObstacle(worldT))
00218 continue;
00219
00220
00221 std::vector<int> collidingJObs;
00222 for (int j = 0; j < (int)i-1; j++) {
00223 if (obs[j].valid && obs[i].collides(obs[j])) {
00224 collidingJObs.push_back(j);
00225 }
00226 }
00227
00228
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
00237 if (collidingJObs.empty() && collidingPObs.empty())
00238 continue;
00239
00240
00241
00242
00243 JointObstacle jointOwnObs(obs[i].joint);
00244 jointOwnObs.setObstacle(worldT, true);
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
00253 for (unsigned int jObs = 0; jObs < collidingJObs.size(); jObs++) {
00254 unsigned int numComponents = obs[collidingJObs[jObs]].joint->components.size();
00255
00256
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
00266
00267 JointObstacle collidingOwnObs(obs[collidingJObs[jObs]]);
00268 collidingOwnObs.setObstacle(worldT, true);
00269
00270
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
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
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
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
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
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
00349
00350
00351
00352
00353
00354
00355
00356
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
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 return this->valid;
00374 }
00375
00376
00377
00378
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
00420 void plotTree(const std::vector<NodeType_t> &tree,
00421 Shape<GraphicsData> &graphics,
00422 rgb color=rgb(255,0,0));
00423
00424
00425 void plotPath(const std::vector<NodeValue_t> &tree,
00426 Shape<GraphicsData> &graphics,
00427 rgb color=rgb(255,0,0));
00428
00429
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
00479 for (size_t j = 0; j < N; j++)
00480 joints[j]->setQ(tree[i].q[j]);
00481
00482
00483 std::vector<std::vector<std::pair<float,float> > > boxes;
00484 getBoxes(boxes, *joints[0]);
00485
00486
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
00499 for (size_t j = 0; j < N; j++)
00500 joints[j]->setQ(path[i][j]);
00501
00502
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
00508 std::vector<std::vector<std::pair<float,float> > > boxes;
00509 getBoxes(boxes, *joints[0]);
00510
00511
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
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
00527 if (joint.nextJoint() != NULL)
00528 getBoxes(boxes, *joint.nextJoint());
00529
00530
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
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
00545 for (KinematicJoint::component_iterator it = joint.components.begin(); it != joint.components.end(); ++it) {
00546
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