00001
00002 #ifndef _GENERIC_RRT_H_
00003 #define _GENERIC_RRT_H_
00004
00005 #include <vector>
00006 #include <ostream>
00007 #include <cmath>
00008
00009 #include "Shared/Measures.h"
00010
00011 using namespace DualCoding;
00012
00013
00014
00015
00016
00017
00018
00019
00020 class RRTNodeBase {
00021 public:
00022 RRTNodeBase(unsigned int p) : parent(p) {}
00023 unsigned int parent;
00024 enum Interp_t { COLLISION, APPROACHED, REACHED };
00025
00026 static float randRange(float minVal, float maxVal) {
00027 return (maxVal - minVal) * (rand()/((float)RAND_MAX)) + minVal;
00028 }
00029 virtual ~RRTNodeBase() {}
00030 virtual std::string toString() const = 0;
00031 };
00032
00033
00034
00035
00036
00037
00038
00039
00040 template<typename NODE>
00041 class AdmissibilityPredicate {
00042 public:
00043
00044 AdmissibilityPredicate() {}
00045
00046
00047 virtual ~AdmissibilityPredicate() {}
00048
00049
00050 virtual bool admissible(typename NODE::NodeValue_t q, std::vector<NODE>& tree, unsigned int parent) = 0;
00051 };
00052
00053
00054
00055 class GenericRRTBase {
00056 public:
00057 enum PlanPathResultCode {SUCCESS, START_COLLIDES, END_COLLIDES, MAX_ITER};
00058
00059
00060
00061
00062 template <size_t N>
00063 class PlannerResult {
00064 public:
00065 GenericRRTBase::PlanPathResultCode code;
00066 PlannerObstacle<N> *movingObstacle;
00067 PlannerObstacle<N> *collidingObstacle;
00068
00069 PlannerResult() : code(), movingObstacle(NULL), collidingObstacle(NULL) {}
00070
00071 ~PlannerResult() {
00072 delete movingObstacle;
00073 delete collidingObstacle;
00074 }
00075
00076
00077 PlannerResult(const PlannerResult &other) :
00078 code(other.code),
00079 movingObstacle(other.movingObstacle ? dynamic_cast<PlannerObstacle<N>*>(other.movingObstacle->clone()) : NULL),
00080 collidingObstacle(other.collidingObstacle ? dynamic_cast<PlannerObstacle<N>*>(other.collidingObstacle->clone()) : NULL) {}
00081
00082
00083 PlannerResult& operator=(const PlannerResult &other) {
00084 delete movingObstacle;
00085 delete collidingObstacle;
00086 code = other.code;
00087 movingObstacle = other.movingObstacle ? dynamic_cast<PlannerObstacle<N>*>(other.movingObstacle->clone()) : NULL;
00088 collidingObstacle = other.collidingObstacle ? dynamic_cast<PlannerObstacle<N>*>(other.collidingObstacle->clone()) : NULL;
00089 return *this;
00090 }
00091
00092 };
00093
00094 virtual ~GenericRRTBase() {}
00095
00096 typedef PlannerResult<2> PlannerResult2D;
00097 typedef PlannerResult<3> PlannerResult3D;
00098 };
00099
00100
00101 template<typename NODE, size_t N>
00102 class GenericRRT : public GenericRRTBase {
00103 public:
00104 typedef typename NODE::NodeValue_t NodeValue_t;
00105 protected:
00106
00107 NodeValue_t lowerLimits;
00108
00109 NodeValue_t upperLimits;
00110
00111 NodeValue_t extendingInterpolationStep;
00112
00113 NodeValue_t smoothingInterpolationStep;
00114
00115
00116 typename NODE::CollisionChecker *cc;
00117
00118
00119 AdmissibilityPredicate<NODE> *predicate;
00120
00121 public:
00122
00123 GenericRRT(typename NODE::CollisionChecker *collCheck,
00124 AdmissibilityPredicate<NODE> *predicate=NULL);
00125
00126
00127 GenericRRT(const GenericRRT &other) :
00128 GenericRRTBase(other),
00129 lowerLimits(other.lowerLimits), upperLimits(other.upperLimits),
00130 extendingInterpolationStep(other.extendingInterpolationStep),
00131 smoothingInterpolationStep(other.smoothingInterpolationStep),
00132 cc(other.cc), predicate(other.predicate) {}
00133
00134
00135
00136 virtual ~GenericRRT() { delete cc; delete predicate; }
00137
00138
00139 void setLimits(const NodeValue_t &_lowerLimits, const NodeValue_t &_upperLimits) {
00140 lowerLimits = _lowerLimits;
00141 upperLimits = _upperLimits;
00142 }
00143
00144
00145 virtual void setInterpolation(const NodeValue_t &_interpolationStep) { setSmoothingInterpolation(_interpolationStep); setExtendingInterpolation(_interpolationStep); }
00146
00147
00148 virtual void setExtendingInterpolation(const NodeValue_t &_extendingInterpolationStep) { extendingInterpolationStep = _extendingInterpolationStep; }
00149
00150
00151 virtual void setSmoothingInterpolation(const NodeValue_t &_smoothingInterpolationStep) { smoothingInterpolationStep = _smoothingInterpolationStep; }
00152
00153
00154 virtual PlannerResult<N> planPath(const NodeValue_t &start,
00155 const NodeValue_t &end,
00156 unsigned int maxIterations,
00157 std::vector<NodeValue_t> *pathResult=NULL,
00158 std::vector<NODE> *treeStartResult=NULL,
00159 std::vector<NODE> *treeEndResult=NULL);
00160
00161 virtual void dumpTree(const std::vector<NODE> &tree, const std::string &header="");
00162
00163 void addObstaclesToShapeSpace(ShapeSpace &space) const;
00164
00165 protected:
00166
00167 virtual void initialize(const NodeValue_t &start, std::vector<NODE> &treeStartResult,
00168 const NodeValue_t &end, std::vector<NODE> &treeEndResult);
00169 virtual void buildPath(const std::vector<NODE> *treeStart, const std::vector<NODE> *treeEnd,
00170 std::vector<NodeValue_t> &path);
00171
00172 void addNode(std::vector<NODE> *tree, const NodeValue_t &q, unsigned int parent);
00173
00174 private:
00175 unsigned int nearestNode(std::vector<NODE> *tree, const NodeValue_t &target);
00176 RRTNodeBase::Interp_t extend(std::vector<NODE> *tree, const NodeValue_t &q, bool truncate, bool fromOtherTree);
00177
00178 GenericRRT& operator=(const GenericRRT&);
00179 };
00180
00181
00182
00183 template<typename NODE, size_t N>
00184 GenericRRT<NODE, N>::GenericRRT(typename NODE::CollisionChecker *collCheck,
00185 AdmissibilityPredicate<NODE> *_predicate) :
00186 lowerLimits(), upperLimits(), extendingInterpolationStep(), smoothingInterpolationStep(), cc(collCheck), predicate(_predicate) {}
00187
00188 template<typename NODE, size_t N>
00189 void GenericRRT<NODE, N>::initialize(const NodeValue_t &start, std::vector<NODE> &treeStart,
00190 const NodeValue_t &end, std::vector<NODE> &treeEnd) {
00191 addNode(&treeStart, start, 0);
00192 addNode(&treeEnd, end, 0);
00193 }
00194
00195 template<typename NODE, size_t N>
00196 GenericRRTBase::PlannerResult<N>
00197 GenericRRT<NODE, N>::planPath(const NodeValue_t &start, const NodeValue_t &end,
00198 unsigned int maxIterations,
00199 std::vector<NodeValue_t> *pathResult,
00200 std::vector<NODE> *treeStartResult, std::vector<NODE> *treeEndResult) {
00201 PlannerResult<N> result;
00202
00203
00204 if ( cc->collides(start, &result) ) {
00205 result.code = START_COLLIDES;
00206 return result;
00207 }
00208
00209 if ( cc->collides(end, &result) ) {
00210 result.code = END_COLLIDES;
00211 return result;
00212 }
00213
00214
00215 std::vector<NODE> privateTreeStart, privateTreeEnd;
00216 std::vector<NODE> *treeStart = treeStartResult ? treeStartResult : &privateTreeStart;
00217 std::vector<NODE> *treeEnd = treeEndResult ? treeEndResult : &privateTreeEnd;
00218 treeStart->clear();
00219 treeEnd->clear();
00220
00221
00222 initialize(start, *treeStart, end, *treeEnd);
00223
00224 std::vector<NODE> *A = treeStart;
00225 std::vector<NODE> *B = treeEnd;
00226
00227 unsigned int iter = 0;
00228
00229 if ( extend(A, end, false, false) != RRTNodeBase::REACHED ) {
00230
00231 while ( iter < maxIterations ) {
00232 NodeValue_t qrand;
00233 NODE::generateSample(lowerLimits,upperLimits,qrand);
00234 if ( cc->collides(qrand) )
00235 continue;
00236 if ( extend(A, qrand, true, false) != RRTNodeBase::COLLISION )
00237 if ( extend(B, A->back().q, true, true) == RRTNodeBase::REACHED )
00238 break;
00239 swap(A,B);
00240 iter++;
00241 }
00242 }
00243
00244 if ( iter >= maxIterations ) {
00245
00246
00247 result.code = MAX_ITER;
00248 return result;
00249 }
00250
00251 if ( pathResult != NULL )
00252 buildPath(treeStart, treeEnd, *pathResult);
00253
00254 result.code = SUCCESS;
00255 return result;
00256 }
00257
00258
00259 template<typename NODE, size_t N>
00260 unsigned int GenericRRT<NODE, N>::nearestNode(std::vector<NODE> *tree, const NodeValue_t &target) {
00261 unsigned int nearest = 0;
00262 float dist = (*tree)[nearest].distance(target);
00263 for (unsigned int i = 1; i < tree->size(); i++) {
00264 float d = (*tree)[i].distance(target);
00265 if (d < dist) {
00266 nearest = i;
00267 dist = d;
00268 }
00269 }
00270 return nearest;
00271 }
00272
00273
00274 template<typename NODE, size_t N>
00275 RRTNodeBase::Interp_t GenericRRT<NODE, N>::extend(std::vector<NODE> *tree, const NodeValue_t &target, bool truncate, bool fromOtherTree) {
00276 unsigned int nearest = nearestNode(tree, target);
00277 NodeValue_t reached;
00278
00279 RRTNodeBase::Interp_t result = NODE::interpolate((*tree)[nearest].q, target, extendingInterpolationStep, truncate, cc, reached, fromOtherTree);
00280 if ( result != RRTNodeBase::COLLISION ) {
00281 if ( predicate != NULL && predicate->admissible(reached, *tree, nearest) == false )
00282 result = RRTNodeBase::COLLISION;
00283 else
00284 addNode(tree, reached, nearest);
00285 }
00286 return result;
00287 }
00288
00289
00290 template<typename NODE, size_t N>
00291 void GenericRRT<NODE, N>::addNode(std::vector<NODE> *tree, const NodeValue_t &q, unsigned int parent) {
00292 tree->push_back(NODE(q, parent));
00293 }
00294
00295
00296 template<typename NODE, size_t N>
00297 void GenericRRT<NODE, N>::buildPath(const std::vector<NODE> *treeStart, const std::vector<NODE> *treeEnd,
00298 std::vector<NodeValue_t> &path) {
00299
00300
00301 unsigned int n = treeStart->size() - 1;
00302 while (n != 0) {
00303 n = (*treeStart)[n].parent;
00304 path.push_back((*treeStart)[n].q);
00305 }
00306
00307 std::reverse(path.begin(), path.end());
00308 path.push_back(treeEnd->back().q);
00309
00310 n = treeEnd->size() - 1;
00311 while (n != 0) {
00312 n = (*treeEnd)[n].parent;
00313 path.push_back((*treeEnd)[n].q);
00314 }
00315
00316
00317 size_t maxIter = max((size_t)20, 2*path.size());
00318
00319 for (size_t i = 0; i < maxIter; i++) {
00320 int a = rand() % path.size();
00321 int b = rand() % path.size();
00322 if (a > b)
00323 std::swap(a,b);
00324 else if (a == b)
00325 continue;
00326
00327 NodeValue_t dummy;
00328 if ( NODE::interpolate(path[a], path[b], smoothingInterpolationStep,
00329 false, cc, dummy, true) == RRTNodeBase::REACHED ) {
00330
00331
00332
00333 path.erase(path.begin()+a+1,path.begin()+b);
00334
00335 }
00336 }
00337
00338 for (size_t i = 0; i+2 < path.size(); i++) {
00339 size_t j;
00340 for (j = i + 2; j < path.size(); j++) {
00341 NodeValue_t dummy;
00342 if ( NODE::interpolate(path[i], path[j], smoothingInterpolationStep, false, cc, dummy, true) != RRTNodeBase::REACHED )
00343 break;
00344 }
00345 if (j > i + 3 && j < path.size())
00346 path.erase(path.begin()+i+1, path.begin()+j-1);
00347 }
00348 }
00349
00350 template<typename NODE, size_t N>
00351 void GenericRRT<NODE, N>::dumpTree(const std::vector<NODE> &tree, const std::string &header) {
00352 if ( header.size() > 0 )
00353 std::cout << header << std::endl;
00354 for ( size_t i = 0; i < tree.size(); i++ )
00355 if ( tree[i].parent != 0 )
00356 std::cout << " " << tree[i].toString() << " " << tree[tree[i].parent].toString() << std::endl;
00357 }
00358
00359 template<typename NODE, size_t N>
00360 void GenericRRT<NODE, N>::addObstaclesToShapeSpace(ShapeSpace &space) const {
00361 cc->addObstaclesToShapeSpace(space);
00362 }
00363
00364 #endif