trgen.cc

Go to the documentation of this file.
00001 
00011 #include <exception>
00012 #include <typeinfo>
00013 #include <iterator>
00014 #include "trgen.h"
00015 
00016 //#define DEBUG
00017 
00018 #ifdef DEBUG
00019   #ifdef MATLAB_MEX_FILE
00020     #define dbgPrintf(format, ...) ssPrintf(format, ##__VA_ARGS__)
00021   #else
00022     #define dbgPrintf(format, ...) printf(format, ##__VA_ARGS__)
00023   #endif
00024 #else
00025 #define dbgPrintf(format, ...)
00026 #endif
00027 
00028 #ifdef MATLAB_MEX_FILE
00029 #define S_FUNCTION_LEVEL 2
00030 #define S_FUNCTION_NAME  sf_trgen
00031 #include "simstruc.h"
00032 #endif
00033 
00034 namespace Segment {
00035 
00039 class Line : public TrajectorySegment 
00040 {
00041     Point *p1, *p2;
00042     double angle;               // uhle v globalnich souradnicich
00043     double length;              // delka segmentu
00044     double cosphi, sinphi;
00045 public:
00046     Line(Point *_p1, Point *_p2) : p1(_p1), p2(_p2) {
00047         length = p1->distanceTo(*p2);
00048         angle = p1->angleTo(*p2);
00049         sinphi = (p2->y-p1->y)/length;
00050         cosphi = (p2->x-p1->x)/length;
00051     }
00052     virtual ~Line() {};
00053   
00054     virtual void setMaxV(const TrajectoryConstraints &constr) {
00055         maxv = constr.maxv;
00056     }
00057 
00058     virtual double getLength() const {return length;}
00059     double getAngle() {return angle;}
00060 
00061     virtual void getPointAt(double distance, Point *p) {
00062         double ratio;
00063         if (distance > 0) {
00064             ratio = distance/length;
00065         } else {
00066             ratio = (length+distance)/length;
00067         }
00068         p->x = p1->x + ratio*(p2->x - p1->x);
00069         p->y = p1->y + ratio*(p2->y - p1->y);
00070     }
00071 
00072     virtual void shortenBy(double distance, Point *newEnd) {
00073         getPointAt(-distance, newEnd);
00074         if (distance > 0) {
00075             p2 = newEnd;
00076         } else {
00077             distance = -distance;
00078             p1 = newEnd;
00079         }
00080         length -= distance;
00081     }
00082 
00083     virtual TrajectorySegment* splitAt(double distance, Point *newEnd) {
00084         if (distance <= 0 || distance >= length) {
00085             dbgPrintf("splitAt: distance=%g length=%g\n", distance, length);
00086             return NULL;
00087         }
00088 
00089         getPointAt(distance, newEnd);
00090         Line *ns = new Line(*this);
00091         p2 = newEnd;
00092         length = distance;
00093         ns->length -= distance;
00094         ns->p1 = newEnd;
00095         return ns;
00096     }
00097 
00098     virtual void getRefPos(double time, Pos &rp) {
00099         double t = time-t1;
00100         double fraction = t/(t2-t1);
00101         double distance = (v1 + 0.5*acc*t) * t;
00102         rp.x = p1->x + distance*cosphi;
00103         rp.y = p1->y + distance*sinphi;
00104         rp.phi = angle;
00105         
00106         rp.v = v1+fraction*(v2-v1);
00107         rp.omega = 0;
00108         
00109     }
00110 #ifdef MATLAB_MEX_FILE
00111     virtual void plot(const char *style) {
00112         char cmd[300];
00113         sprintf(cmd, "plot([%g %g], [%g %g], '%so')",
00114                 p1->x, p2->x, p1->y, p2->y, style);
00115         mexEvalString(cmd);
00116     };
00117 #endif
00118 };
00119 
00124 class Arc : public TrajectorySegment 
00125 {
00126     Point *p1, *p2;
00127     double angle;               // vrcholovy uhel [-pi,+pi]
00128     double startAngle;          // uhel od stredu k p1
00129     double radius;              // polomer
00130     double length;              // delka segmentu
00131     Point center;
00132 public:
00133     Arc(Point *_p1, Point *_p2, double _radius) :
00134             p1(_p1), p2(_p2), radius(fabs(_radius)) {
00135 
00136         // Find the center of the arc
00137         double angp1p2 = p1->angleTo(*p2);
00138         double m = p1->distanceTo(*p2)/2.0;
00139         if (radius < m) {
00140             radius = m; 
00141             dbgPrintf("EEEERRRRRRRRROOOOOOOOORRRRRRRRR!!!!!!!!!!\n");
00142         }
00143         double angcen = acos(m/radius);
00144         if (_radius < 0) angcen = -angcen;
00145         center = Point(p1->x + radius * cos(angp1p2+angcen),
00146                        p1->y + radius * sin(angp1p2+angcen));
00147 
00148         startAngle = center.angleTo(*p1);
00149         angle = center.angleTo(*p2) - startAngle;
00150         if (angle < -M_PI) angle += 2.0*M_PI;
00151         if (angle > +M_PI) angle -= 2.0*M_PI;
00152 
00153         length = fabs(angle*radius);
00154     }
00155     virtual ~Arc() {};
00156 
00157     
00158     virtual void setMaxV(const TrajectoryConstraints &constr) {
00159         double r = radius;
00160         maxv = fmin(constr.maxv, constr.maxomega * r);
00161         maxv = fmin(maxv, sqrt(constr.maxcenacc * r));
00162     }
00163 
00164     virtual double getLength() const {return length;}
00165 
00166     virtual void getPointAt(double distance, Point *p) {
00167         double ratio, a;
00168         if (distance > 0) {
00169             ratio = distance/length;
00170         } else {
00171             distance = -distance;
00172             ratio = (length-distance)/length;
00173         }
00174         a = startAngle + ratio*angle;
00175         p->x = center.x + radius*cos(a);
00176         p->y = center.y + radius*sin(a);
00177     }
00178     virtual void shortenBy(double distance, Point *newEnd) {
00179         getPointAt(-distance, newEnd);
00180         if (distance > 0) {
00181             angle *= (length-distance)/length;
00182             p2 = newEnd;
00183         } else {
00184             distance = -distance;
00185             startAngle = startAngle + distance/length*angle;
00186             angle *= (length-distance)/length;
00187             p1 = newEnd;
00188         }
00189         length -= distance;
00190     }
00191 
00192     virtual TrajectorySegment* splitAt(double distance, Point *newEnd) {
00193         if (distance <= 0 || distance >= length)
00194             return NULL;
00195 
00196         getPointAt(distance, newEnd);
00197         Arc *ns = new Arc(*this);
00198 
00199         double a = distance/length*angle;
00200         angle = a;
00201         length = distance;
00202         p2 = newEnd;
00203 
00204         ns->startAngle += a;
00205         ns->angle -= a;
00206         ns->length -= distance;
00207         ns->p1 = newEnd;
00208         return ns;
00209     }
00210 
00211     virtual void getRefPos(double time, Pos &rp) {
00212         double t = time-t1;
00213         double fraction = t/(t2-t1);
00214         double distance = (v1 + 0.5*acc*t) * t;
00215         double a = startAngle + distance/length*angle;
00216         rp.x = center.x + radius*cos(a);
00217         rp.y = center.y + radius*sin(a);
00218         if (angle > 0)
00219             rp.phi = a + M_PI/2.0;
00220         else
00221             rp.phi = a - M_PI/2.0;
00222 
00223         rp.v = v1+fraction*(v2-v1);
00224         rp.omega =rp.v/radius;
00225         if (angle < 0) rp.omega = -rp.omega;
00226         
00227     }
00228 #ifdef MATLAB_MEX_FILE
00229     virtual void plot(const char *style) {
00230         char cmd[300];
00231         const int len = 10;
00232         int i;
00233         Pos rp;
00234         mxArray *x = mxCreateDoubleMatrix(1, len, mxREAL);
00235         mxArray *y = mxCreateDoubleMatrix(1, len, mxREAL);
00236         mxArray *s = mxCreateCharMatrixFromStrings(1, &style);
00237         mxArray *rhs[] = {x,y,s};
00238         
00239         for (i=0; i < len; i++) {
00240             getRefPos(t1+(t2-t1)*i/(len-1), rp);
00241             mxGetPr(x)[i] = rp.x;
00242             mxGetPr(y)[i] = rp.y;
00243         }
00244         mexCallMATLAB(0, NULL, 3, rhs, "plot");
00245         sprintf(cmd, "plot([%g %g], [%g %g], 'mo')",
00246                 p1->x, p2->x, p1->y, p2->y);
00247         mexEvalString(cmd);
00248         mxDestroyArray(x);
00249         mxDestroyArray(y);
00250         mxDestroyArray(s);
00251     };
00252 #endif
00253 };
00254 
00262 class Turn : public TrajectorySegment 
00263 {
00264     Point *center;
00265     double turnBy;            
00266     double startHeading;      
00267 public:
00268     Turn(Point *_center, double _startHeading, double _turnBy) :
00269         center(_center), turnBy(_turnBy), startHeading(_startHeading) {}
00270     virtual ~Turn() {};
00271 
00272     
00273     virtual void setMaxV(const TrajectoryConstraints &constr) {
00274             maxv = constr.maxomega;
00275     }
00276 
00277     virtual double getMaxAcc(const TrajectoryConstraints &constr) const {
00278         return constr.maxangacc;
00279     }
00280 
00281     virtual bool isTurn() const { return true; };
00282 
00283     virtual double getLength() const {return 0;}
00284     virtual double getUnifiedLength() const {
00285         return fabs(turnBy);
00286     }
00287 
00288     virtual void getPointAt(double distance, Point *p) {
00289         *p = *center;
00290     }
00291     virtual void shortenBy(double distance, Point *newEnd) {}
00292 
00293     virtual TrajectorySegment* splitAt(double distance, Point *newEnd) {
00294         if (distance <= 0 || distance >= fabs(turnBy)) {
00295             dbgPrintf("splitAt: distance=%g turnBy=%g\n", distance, turnBy);
00296             return NULL;
00297         }
00298 
00299         Turn *ns = new Turn(*this);
00300         if (turnBy < 0) 
00301                 distance = -distance;
00302         turnBy = distance;
00303         ns->startHeading+=distance;
00304         ns->turnBy -= distance;
00305         return ns;
00306     }
00307 
00308     virtual void getRefPos(double time, Pos &rp) {
00309         double t = time-t1;
00310         double fraction = t/(t2-t1);
00311         double distance = (v1 + 0.5*acc*t) * t;
00312         rp.x = center->x;
00313         rp.y = center->y;
00314         if (turnBy > 0)
00315             rp.phi = startHeading + distance;
00316         else
00317             rp.phi = startHeading - distance;
00318         rp.v=0;
00319         if (time < t2)
00320                 rp.omega = v1+fraction*(v2-v1);
00321         else
00322                 rp.omega = 0;
00323     }
00324 
00325 #ifdef MATLAB_MEX_FILE
00326     virtual void plot(const char *style) {};
00327 #endif
00328 };
00329 
00330 } // namespace Segment
00331 
00332 
00333 using namespace Segment;
00334 
00344 bool 
00345 Trajectory::splitSegment(iterator &seg, double distance) 
00346 {
00347     TrajectorySegment *ns;
00348     Point *np = NULL;
00349     if (typeid(**seg) != typeid(Turn)) 
00350         np = new Point;
00351 
00352     ns = (*seg)->splitAt(distance, np);
00353     if (ns == NULL) {
00354         dbgPrintf("ERROR\n");
00355         delete(np);
00356         return false;
00357     }
00358     if (np) 
00359         wayPoints.push_back(np);
00360     seg = insert(++seg, ns);
00361     return true;
00362 }
00363     
00364 //     iterator insert(reverse_iterator it, const value_type& val) {
00365 //         return insert((--it).base(), val);
00366 //     }
00367 
00371 bool
00372 Trajectory::points2segments() 
00373 {
00374     TrajectoryPoints::iterator p1, p2;
00375     Point ip(initPos.x, initPos.y);
00376 
00377     if (*wayPoints.front() != ip) {
00378         initialPoint = new Point(ip);
00379         wayPoints.push_front(initialPoint);
00380     } else
00381         initialPoint = wayPoints.front();
00382 
00383     // Delete old segments
00384     deleteSegments();
00385 
00386     if (wayPoints.size() < 2) {
00387         return false;
00388     }
00389     for (p1 = wayPoints.begin(), p2 = ++wayPoints.begin();
00390          p2 != wayPoints.end();
00391          p1++, p2++) {
00392         push_back(new Line(*p1, *p2));
00393     }
00394     return true;
00395 }
00396 
00397 
00403 // \f{center}
00404 // \frame{\begin{tikzpicture}
00405 //  \draw (-5cm,0) coordinate(p1) node[left]{$p_1$} --
00406 //   node[sloped,above]{$\mathrm seg_1$} (0,0) coordinate(p2)
00407 //   node[above]{$p_2$} -- node[sloped,above]{$\mathrm seg_2$} +(-30:5cm)
00408 //   node[right]{$p_3$} coordinate (p3);
00409 //   \coordinate[shift=(-105:5cm)] (c) at (p2);
00410 //   \draw (p2) -- (c);
00411 //   \draw (c) -- (c |- p2);
00412 //   \draw (c) -- (intersection of c--40:10cm and p2--p3);
00413 // \end{tikzpicture}}
00414 //    \f}
00415 
00416 void
00417 Trajectory::corners2arcs() 
00418 {
00419     iterator seg, segNext, segPrev;
00420 
00421     if (size() < 2) return;
00422         
00423     // Find radiuses to meet e <= maxe
00424     for (segPrev = begin(), segNext = ++begin();
00425          segNext != end();
00426          segPrev++, segNext++) {
00427             
00428         double alpha;       // curve angle (-pi <= alpha <= +pi)
00429         double r;           // radius of proposed arc. (alpha < 0 -> r < 0)
00430         double s;           // length of the segment replaced by the arc (s > 0)
00431         try {
00432             alpha = dynamic_cast<Line*>(*segNext)->getAngle() -
00433                 dynamic_cast<Line*>(*segPrev)->getAngle();
00434             if (alpha > +M_PI) alpha -= 2.0*M_PI;
00435             if (alpha < -M_PI) alpha += 2.0*M_PI;
00436 
00437             if (fabs(alpha) < M_PI/180.0) continue;
00438 
00439             r = constr.maxe / (1/cos(alpha/2.0) - 1);
00440             if (alpha < 0) r = -r;
00441             s = r*tan(alpha/2.0);
00442             if (s > (*segPrev)->getLength()) {
00443                 s = (*segPrev)->getLength();
00444                 r = s/tan(alpha/2.0);
00445             }
00446             if (s > (*segNext)->getLength()) {
00447                 s = (*segNext)->getLength();
00448                 r = s/tan(alpha/2.0);
00449             }
00450             (*segPrev)->r = r;                
00451             (*segPrev)->s = s;
00452             (*segPrev)->alphahalf = alpha/2.0;
00453         } 
00454         catch (std::exception& e) {} // Skip wrong dynamic_cast
00455     }
00456 
00457     if (size() >= 3) {
00458         // Reduce overlapping arcs by decreasing radiuses
00459         double s1, s2, r1, r2, l, alphahalf1, alphahalf2;
00460         bool wantSameR;
00461         for (segPrev = begin(), segNext = ++begin();
00462              segNext != --end();
00463              segPrev++, segNext++) {
00464             l = (*segNext)->getLength();
00465             s1 = (*segPrev)->s;
00466             s2 = (*segNext)->s;
00467             r1 = (*segPrev)->r;
00468             r2 = (*segNext)->r;
00469             alphahalf1 = (*segPrev)->alphahalf;
00470             alphahalf2 = (*segNext)->alphahalf;
00471             if (s1 + s2 > l) {
00472                 if (fabs(r1) > fabs(r2)) {
00473                     s1 = l - s2;
00474                     r1 = s1/tan(alphahalf1);
00475                     wantSameR = (fabs(r1) < fabs(r2));
00476                 } else {
00477                     s2 = l - s1;
00478                     r2 = s2/tan(alphahalf2);
00479                     wantSameR = (fabs(r1) > fabs(r2));
00480                 }
00481                 if (wantSameR) {
00482                     if (alphahalf1 < 0 ^ alphahalf2 < 0)
00483                         s1 = l*tan(alphahalf1)/(tan(alphahalf1)-tan(alphahalf2));
00484                     else
00485                         s1 = l*tan(alphahalf1)/(tan(alphahalf1)+tan(alphahalf2));
00486                     s2 = l - s1;
00487                     r1 = s1/tan(alphahalf1);
00488                     r2 = s2/tan(alphahalf2);
00489                 }
00490                 (*segPrev)->s = s1;
00491                 (*segNext)->s = s2;
00492                 (*segPrev)->r = r1;
00493                 (*segNext)->r = r2;
00494             }
00495         }
00496     }
00497 
00498     // replace corners by arcs with previously computed radiuses
00499     for (segPrev = begin(), segNext = ++begin();
00500          segNext != end();
00501          ++segPrev, ++segNext) {
00502         if (fabs((*segPrev)->r) > 0) {
00503             Point *newEnd1, *newEnd2;
00504             double s = (*segPrev)->s;
00505             newEnd1 = new Point();
00506             newEnd2 = new Point();
00507             (*segPrev)->shortenBy(+s, newEnd1);
00508             (*segNext)->shortenBy(-s, newEnd2);
00509             wayPoints.push_back(newEnd1);
00510             wayPoints.push_back(newEnd2);
00511             segPrev = insert(segNext, new Arc(newEnd1, newEnd2,
00512                                                         (*segPrev)->r));
00513         }
00514     }
00515 
00516     //delete zero-length segments
00517     seg = begin();
00518     while (seg != end()) {
00519         if ((*seg)->getLength() <= 1e-9) {
00520             delete(*seg);
00521             seg = erase(seg);
00522         } else
00523             seg++;
00524     }
00525 }
00526 
00527 
00562 void
00563 Trajectory::calcSpeeds() 
00564 {
00565     if (size() == 0) return;
00566 
00567     // Assign maximum speed
00568     for (iterator seg = begin(); seg != end(); seg++) {
00569         (*seg)->setMaxV(constr);
00570         (*seg)->v1 = (*seg)->maxv;
00571         (*seg)->v2 = (*seg)->maxv;
00572     }
00573 #ifdef MATLAB_MEX_FILE
00574     plotSpeed("r-o");
00575 #endif
00576 
00577     double lastv;
00578     bool turning = false;       // FIXME: turning je integer podle smeru otaceni
00579 
00580     // Accelerare where possible
00581     lastv = initPos.v;
00582     for (iterator seg = begin(); seg != end(); seg++) {
00583         if (turning != (*seg)->isTurn()) {
00584             turning = (*seg)->isTurn();
00585             lastv = 0;
00586         }
00587         double v1 = (*seg)->v1;
00588         double v2 = (*seg)->v2;
00589         double maxv = (*seg)->maxv;
00590         //dbgPrintf("processing: %p v1=%g\n", *seg, v1);
00591         if (v1 > lastv) {
00592             v1 = lastv;
00593             double l = (*seg)->getUnifiedLength();
00594             double a = (*seg)->getMaxAcc(constr);
00595             double t;
00596 
00597             t = (-v1+sqrt(v1*v1 + 2.0*a*l))/a;
00598             v2 = v1+a*t;
00599 
00600             //dbgPrintf("t=%g v2=%g l=%g\n", t, v2, l);
00601             if (v2 > maxv) {    // split this segment
00602                 v2 = maxv;
00603                 t = (v2 - v1)/a;
00604                 l = v1*t+0.5*a*t*t;
00605                 //dbgPrintf("t=%g v2=%g l=%g\n", t, v2, l);
00606                 iterator ns = seg;
00607                 if (splitSegment(ns, l)) {
00608                     (*ns)->v1 = v2;
00609                 }
00610             }
00611 
00612             (*seg)->v1 = v1;
00613             (*seg)->v2 = v2;
00614         }
00615         lastv = (*seg)->v2;
00616     }
00617 #ifdef MATLAB_MEX_FILE
00618     plotSpeed("g-o");
00619 #endif        
00620 
00621     // Deccelerate where needed
00622     turning = false;
00623     lastv = 0;              // Final speed
00624     for (reverse_iterator seg = rbegin(); seg != rend(); seg++) {
00625         if (turning != (*seg)->isTurn()) {
00626             turning = (*seg)->isTurn();
00627             lastv = 0;
00628         }
00629         double v1 = (*seg)->v1;
00630         double v2 = (*seg)->v2;
00631         double maxv = (*seg)->maxv;
00632         dbgPrintf("processing: %p v2=%g\n", *seg, v2);
00633         if (v2 > lastv) {
00634             v2 = lastv;
00635             double l = (*seg)->getUnifiedLength();
00636             double a = (*seg)->getMaxAcc(constr);
00637             double t;
00638 
00639             t = (-v2+sqrt(v2*v2 + 2.0*a*l))/a;
00640             v1 = v2+a*t;
00641 
00642             //dbgPrintf("t=%g v1=%g v2=%g l=%g\n", t, v1, v2, l);
00643             if (v1 > maxv && (*seg)->v1 == maxv) {
00644                 v1 = maxv;
00645                 t = (v1 - v2)/a;
00646                 double l2 = v2*t+0.5*a*t*t;
00647                 //dbgPrintf("t=%g v1=%g v2=%g l=%g l2=%g\n", t, v1, v2, l, l2);
00648                 iterator ns = --(seg.base());
00649                 //dbgPrintf("seg=%p ns=%p\n", *seg, *ns);
00650                 if (splitSegment(ns, l-l2)) {
00651                     //dbgPrintf("ns=%p\n", *ns);
00652                     (*ns)->v2 = v1;
00653                     (*seg)->v1 = v1;
00654                 }
00655             } else if (v1 > (*seg)->v1) {
00656                 // Acceleration and deacceleration within one segment
00657                 // Where is the crossing af acceleration and decceleration?
00658                 v1 = (*seg)->v1;
00659                 double s1 = l/2.0 + (v2*v2 - v1*v1)/4.0*a;
00660                     
00661                 if (s1 > l/1000 && s1 < l - l/1000) {
00662                     //dbgPrintf("t=%g v1=%g v2=%g l=%g s1=%g\n", t, v1, v2, l, s1);
00663                     iterator ns = --(seg.base());
00664                     //dbgPrintf("seg=%p ns=%p (before split)\n", *seg, *ns);
00665                     if (splitSegment(ns, s1)) {
00666                         ++seg; //move to the earlier subsegment of the splited one
00667                         //dbgPrintf("seg=%p ns=%p (after split)\n", *seg, *ns);
00668                         v1 = sqrt(v1*v1 + 2.0*a*s1);
00669                         (*ns)->v1 = v1;
00670                         (*ns)->v2 = v2;
00671                         v2 = v1;
00672                         v1 = (*seg)->v1;
00673                     }
00674                 }
00675             } else {
00676                 (*seg)->v1 = v1;
00677             }
00678             (*seg)->v2 = v2;
00679         }
00680         lastv = (*seg)->v1;
00681     }
00682 #ifdef MATLAB_MEX_FILE
00683     plotSpeed("b-o");
00684 #endif
00685     for (iterator seg = begin(); seg != end(); ++seg) {
00686         dbgPrintf("final: %-16s %p v1=%-8.2g v2=%-8.2g l=%-8.2g\n", 
00687                   typeid(**seg).name(),
00688                   *seg, (*seg)->v1, (*seg)->v2, (*seg)->getLength());
00689     }
00690 }
00691 
00692     
00693 double
00694 Trajectory::calcLength() 
00695 {
00696     double totLen = 0;
00697     for (iterator seg = begin(); seg != end(); ++seg) {
00698         totLen += (*seg)->getLength();
00699     }
00700     return totLen;
00701 }
00702 
00703 static double minimizeAngle(double rad)
00704 {
00705     rad = fmod(rad, 2.0*M_PI);
00706     if (rad > +M_PI/2.0) rad -= 2.0*M_PI;
00707     if (rad < -M_PI/2.0) rad += 2.0*M_PI;
00708     return rad;
00709 }
00710 
00711 void Trajectory::addTurns()
00712 {
00713     Pos p;
00714     TrajectorySegment *seg;
00715     double initialHeading = initPos.phi;
00716     double turnBy;
00717     if (backward) 
00718         initialHeading -= M_PI;
00719 
00720     if (size() == 0) {
00721         // We have to turn only. No movement.
00722         dbgPrintf("*** Adding only the turn - start: %5.2f, end %5.2f\n", initialHeading/M_PI*180, finalHeading/M_PI*180);
00723         turnBy = minimizeAngle(finalHeading - initialHeading);
00724         if (fabs(turnBy) > 1e-3) {
00725             push_front(new Turn(initialPoint, initialHeading, 
00726                                 finalHeading - initialHeading));
00727         }
00728     } else {
00729         // Add turn at beginning
00730         seg = *begin();
00731         seg->v1 = 1;           // Hack - speeds are not calculated yet
00732         seg->v2 = 1;
00733         seg->startAt(0);        // Assign times so we can use
00734                                 // getRefPos();
00735         seg->getRefPos(0, p);
00736         dbgPrintf("*** Adding initial turn - start: %5.2f, end %5.2f\n", initialHeading/M_PI*180, p.phi/M_PI*180);
00737         turnBy = minimizeAngle(p.phi - initialHeading);
00738         if (fabs(turnBy) > 1e-3) {
00739             push_front(new Turn(initialPoint, initialHeading, turnBy));
00740         }
00741 
00742         // Add turn at the end
00743         seg = *(--end());
00744         seg->v1 = 1;           // Hack - speeds are not calculated yet
00745         seg->v2 = 1;
00746         seg->startAt(0);            // Assign times so we can use getRefPos();
00747         seg->getRefPos(seg->getT2(), p);
00748         turnBy = minimizeAngle(p.phi - finalHeading);
00749         if (fabs(turnBy) > 1e-3) { // NaN in finalHeading makes the condition false
00750             dbgPrintf("*** Adding final turn - start: %5.2f, end %5.2f\n", p.phi/M_PI*180, finalHeading/M_PI*180);
00751             push_back(new Turn(finalPoint, p.phi, turnBy));
00752         }
00753     }
00754 }
00755 
00770 bool
00771 Trajectory::prepare(Pos _initPos) 
00772 {
00773     if (constr.maxv      <= 0 || constr.maxv      > 10 ||
00774         constr.maxomega  <= 0 || constr.maxomega  > 10 ||
00775         constr.maxangacc <= 0 || constr.maxangacc > 10 ||
00776         constr.maxacc    <= 0 || constr.maxacc    > 10 ||
00777         constr.maxcenacc <= 0 || constr.maxcenacc > 10 ||
00778         constr.maxe      <= 0 || constr.maxe      > 10) {
00779         dbgPrintf("wrong constraints!!!!\n");
00780     }
00781 
00782     if (wayPoints.size() == 0) {
00783         dbgPrintf("No point in trajectory!\n");
00784         return false;
00785     }
00786 
00787     initPos = _initPos;
00788     if (points2segments() == false) {
00789         dbgPrintf("points2segments error!\n");
00790         return false;
00791     }
00792     corners2arcs();
00793     addTurns();
00794     if (size() == 0)
00795         return false;
00796     calcSpeeds();
00797 
00798     // Assign times to segments
00799     double t=0;
00800     for (iterator seg = begin(); seg != end(); ++seg) {
00801         t = (*seg)->startAt(t);
00802     }
00803     currentSeg = begin();
00804     prepared = true;
00805     return true;
00806 }
00807 
00816 bool
00817 Trajectory::getRefPos(double time, Pos &rp) 
00818 {
00819     int d;
00820     bool ret = false;
00821     TrajectorySegment *seg;
00822 
00823     if (!prepared) {
00824         ret = true;
00825     } else {
00826         do {
00827             d=(*currentSeg)->containsTime(time);
00828             if (d==0) break;
00829             if (currentSeg == --end() && d > 0) break;
00830             if (currentSeg == begin() && d < 0) break;
00831             if (d>0) ++currentSeg;
00832             else if (d<0) --currentSeg;
00833         } while (1);
00834 
00835         seg = *currentSeg;
00836         if (d==0) 
00837             getSegRefPos(seg, time, rp);
00838         else if (d<0)
00839             getSegRefPos(seg, seg->getT1(), rp);
00840         else {
00841             getSegRefPos(seg, seg->getT2(), rp);
00842             ret = true;             // We are at the end.
00843         }
00844     }
00845     
00846     return ret;
00847 }
00848 
00857 void
00858 Trajectory::getSegRefPos(TrajectorySegment *seg, double time, Pos &rp) 
00859 {
00860     seg->getRefPos(time, rp);
00861 
00862     if (backward) {
00863         rp.phi += M_PI;
00864         rp.v = -rp.v;
00865     }
00866 }
00867 
00868 #ifdef MATLAB_MEX_FILE
00869 void
00870 Trajectory::plot(const char *style) 
00871 {
00872     for (iterator seg = begin(); seg != end(); ++seg) {
00873         (*seg)->plot(style);
00874     }
00875 };
00876 void
00877 Trajectory::plotSpeed(const char *style) 
00878 {
00879     char *f2 = "figure(2);";
00880     char *f1 = "hold on; figure(1)";
00881     double t = 0;
00882     mexEvalString(f2);
00883     for (iterator seg = begin(); seg != end(); ++seg) {
00884         t = (*seg)->startAt(t);
00885         (*seg)->plotSpeed(style);
00886     }
00887     mexEvalString(f1);
00888 };
00889 #endif
00890 

Generated on Thu Sep 13 11:28:28 2007 for DCE-Eurobot by  doxygen 1.5.3