9 * @date Sun Aug 12 09:30:59 2007
11 * @brief Trajectory Generator
14 /** \defgroup trgen Trajectory Generator
17 Trajectory generator calculates the trajectory and speed profile for
18 the robot movement from a list of points. For how to use the
19 trajectory generator, see the documentation of ::Trajectory.
21 #ifdef MATLAB_MEX_FILE
27 #include "trgenconstr.h"
30 * Represents a state of the robot.
34 double x, y, phi; ///< position and angle
35 double v, omega; ///< forward and angular speed
36 Pos() : x(0), y(0), phi(0), v(0), omega(0) {};
40 * Represents a point in 2D space and provides some useful methods for
41 * calculation with points.
46 Point() : x(0), y(0) {};
47 Point(double _x, double _y) : x(_x), y(_y) {};
49 double distanceTo(class Point &wp) {
50 double dx = wp.x-x, dy = wp.y-y;
51 return sqrt(dx*dx + dy*dy);
54 double angleTo(class Point &wp) {
55 double dx = wp.x-x, dy = wp.y-y;
59 bool operator==(Point &o) {
60 return (x == o.x && y == o.y);
63 bool operator!=(Point &o) {
69 * List of pointers to Point
72 class TrajectoryPoints : public std::list<Point*> {
75 for (iterator wp = begin(); wp != end(); wp++) {
84 * Abstract class for a segment of the trajectory.
87 class TrajectorySegment {
89 /** Time in the beginning and at the end of the segment. The time
90 * is relative to the start of the whole trajectory. Units are seconds. */
95 double maxv; /**< Maximum speed of the segment. Determined by constraints of the whole trajectory. */
96 double acc; /**< Acceleration at this segment [\f$\mathrm m\cdot \mathrm s^{-2}\f$] */
97 double v1, v2; ///< speed in the beginning and at the end of the segment
99 virtual void setMaxV(const TrajectoryConstraints &constr) = 0;
100 virtual double getMaxAcc(const TrajectoryConstraints &constr) const { return constr.maxacc; };
101 virtual bool isTurn() const { return false; };
102 virtual bool isSpline() const { return false; };
103 virtual double getDistance(double time) const = 0;
105 /// Helper values for Trajectory::corners2arcs()
106 double s, r, alphahalf;
108 TrajectorySegment() : s(0), r(0), alphahalf(0){};
109 virtual ~TrajectorySegment() {};
111 virtual double getLength() const = 0; /**< Length of the segment in meters. */
113 /** Unified length of the segment, used for calculations of
114 * speed and accelerations. Normally, it equal to the real
115 * length, buf for ::TrajectorySegmentTurn (whose length is zero)
116 * it represents angle. */
117 virtual double getUnifiedLength() const {
121 * Returns the point of the segment, located at the specific @c
122 * distance from the beginning or end.
124 * @param[in] distance Distance from the beginning (if positive) or end (if negative) of the segment in meters.
125 * @param[out] p Pointer to the point to sore the result.
127 virtual void getPointAt(double distance, Point *p) = 0;
129 * Shorten the segment by a specific length.
131 * @param[in] distance Distance from the end (if positive) of the segment, where should be the end of the segment.
132 * @param[in] newEnd Point which will be set to the position of the new end.
134 virtual void shortenBy(double distance, Point *newEnd) = 0;
136 * Splits the segment at the specified point. The result will be
137 * two segments following the same trajectory as the original one.
139 * @param[in] distance Distance of the split from the beginning of the segment.
140 * @param[in] newEnd Point which will be used as a middle point joining the two segments.
142 * @return Pointer to the newly created segment.
144 virtual TrajectorySegment* splitAt(double distance, Point *newEnd) = 0;
146 virtual TrajectorySegment* splitAtByTime(double time, Point *newEnd) = 0;
149 * Sets the starting time of the segment and calculates the ending
150 * time according to this. Also acceleration is calculated from
151 * these times and speed.
153 * @param time Starting time relative to the start of the whole
154 * trajectory (in seconds).
156 * @return Ending time.
158 virtual double startAt(double time) {
160 t2 = time + getUnifiedLength()/((v1+v2)/2.0);
161 acc = (v2-v1)/(t2-t1);
165 * Return the reference position at some time.
167 * @param[in] time Time (within this segment time range).
168 * @param[out] rp Reference position.
170 virtual void getRefPos(double time, Pos &rp) = 0;
172 * Return the position in time of this segment relative to the
178 * 0 if time @c t is within this segment,
179 * -1 if time @c t is before this segment,
180 * +1 if time @c t is after this segment.
182 int containsTime(double t) {
183 if (t >= t1 && t <= t2)
190 double getT1() { return t1; } /**< Returns @c t1 */
191 double getT2() { return t2; } /**< Returns @c t2 */
192 #ifdef MATLAB_MEX_FILE
193 virtual void plot(const char *style) = 0;
194 virtual void plotSpeed(const char *style) {
196 sprintf(cmd, "plot([%g %g], [%g %g], '%s')",
197 t1, t2, v1, v2, style);
206 * Represents the whole trajectory. When a new trajectory is created
207 * (by Trajectory() constructor), addPoint() should be used to add points,
208 * the trajectory should go through. After all points are added,
209 * a call to prepare() uses these points to construct optimized
210 * trajectory and find the speeds along the trajectory. After the
211 * trajectory is prepared, you can call getRefPos(), to get the
212 * reference position at a specific time.
215 class Trajectory : public std::list<TrajectorySegment*> {
218 TrajectoryPoints wayPoints; /**< Points, this trajectory is composed from. */
219 Point *initialPoint, *finalPoint;
221 bool contains_inertial;
223 void deleteSegments() {
224 for (iterator seg = begin(); seg != end(); seg++) {
230 bool splitSegment(iterator &seg, double distance);
231 bool splitSegmentByTime(iterator &seg, double time);
232 bool points2segments();
233 // void corners2arcs(); // not used
234 void corners2splines();
237 void addInertialPoint();
238 void log(const char* str);
240 void getSegRefPos(TrajectorySegment *seg, double time, Pos &rp);
243 TrajectoryConstraints constr;
244 /** Desired heading of the robot at the end of the trajectory. */
245 struct final_heading finalHeading;
249 * Trajectory constructor.
251 * @param tc Trajectory constraints
252 * @param _backward Whether the trajectory should be followed in backward direction.
254 Trajectory(TrajectoryConstraints tc, bool _backward = false) :
255 wayPoints(), initialPoint(0), finalPoint(0),
256 prepared(false), constr(tc), backward(_backward) {
257 finalHeading.turn_type = FH_DONT_TURN;
265 * Adds a new point to the trajectory.
270 void addPoint(double x, double y) {
271 finalPoint = new Point(x,y);
272 wayPoints.push_back(finalPoint);
274 void addTurn(double angle);
276 double calcLength(); /**< Returns the length of the whole trajectory. */
278 bool appendTrajectory(Trajectory &traj, double time);
279 bool prepare(Pos _initPos);
280 bool getRefPos(double time, Pos &rp);
281 #ifdef MATLAB_MEX_FILE
282 void plot(const char *style);
283 void plotSpeed(const char *style);
286 void logTraj(double start_time);
292 class Line : public TrajectorySegment {
294 double angle; // uhle v globalnich souradnicich
295 double length; // delka segmentu
296 double cosphi, sinphi;
298 Line(Point *_p1, Point *_p2);
299 virtual void setMaxV(const TrajectoryConstraints &constr);
300 virtual double getLength() const {return length;}
301 virtual double getDistance(double time) const;
302 double getAngle() {return angle;}
303 virtual void getPointAt(double distance, Point *p);
304 virtual void shortenBy(double distance, Point *newEnd);
305 virtual TrajectorySegment* splitAt(double distance, Point *newEnd);
306 virtual TrajectorySegment* splitAtByTime(double time, Point *newEnd);
307 virtual void getRefPos(double time, Pos &rp);
308 #ifdef MATLAB_MEX_FILE
309 virtual void plot(const char *style);
313 class Turn : public TrajectorySegment {
315 double turnBy; /// turn by this angle [rad]
316 double startHeading; /// turning starts at this heading [rad]
318 Turn(Point *_center, double _startHeading, double _turnBy);
319 virtual void setMaxV(const TrajectoryConstraints &constr);
320 virtual double getMaxAcc(const TrajectoryConstraints &constr) const {return constr.maxangacc;}
321 virtual bool isTurn() const { return true; };
322 virtual double getLength() const {return 0;}
323 virtual double getDistance(double time) const;
324 virtual double getUnifiedLength() const {return fabs(turnBy);}
325 virtual void getPointAt(double distance, Point *p);
326 virtual void shortenBy(double, Point *) {}
327 virtual TrajectorySegment* splitAt(double distance, Point *newEnd);
328 virtual TrajectorySegment* splitAtByTime(double time, Point *newEnd);
329 virtual void getRefPos(double time, Pos &rp);
330 #ifdef MATLAB_MEX_FILE
331 virtual void plot(const char *style) {};
336 * Spline shaped segment.
338 * The spline is represented by x-axis polynom and y-axis polynom. Both have 5-th order.
339 * P_x(t) = A_x*t^5 + B_x*t^4 + C_x*t^3 + D_x*t^2 + E_x*t + F_x
340 * P_y(t) = A_y*t^5 + B_y*t^4 + C_y*t^3 + D_y*t^2 + E_y*t + F_y
341 * The parameter t goes from param0 to param1 (initially 0 and 1)
342 * We pressume that the parameter dt/ds = const (reasonable simplification)
346 class Spline : public TrajectorySegment {
347 Point *p1, *p2; // first and final point
348 double Ax, Bx, Cx, Dx, Ex, Fx; // constants representing x-axis polynom
349 double Ay, By, Cy, Dy, Ey, Fy; // constants representing y-axis polynom
350 double length; // segment length
351 Point *corner; // Corner point this spline is substituted for
352 double distance; // distance form p1 to the corner (or p2 to the corner as well)
353 double gamma; // central angle of the corner
354 double m; // size of starting and final speed vector (parameter of spline shaping)
355 double param0, param1; // parameter value at the begining and end of the segment (initially 0 and 1)
356 double vc; // speed in the center (lowest - according to clothoid approximation)
357 double tc; // time in the center
358 double acc1; // acceleration in the first half (typically negative)
359 double acc2; // acceleration in the second half (typically positive)
361 Spline(Point *_p1, Point *_p2, Point *_corner);
362 virtual bool isSpline() const { return true; }
363 virtual void setMaxV(const TrajectoryConstraints &constr);
364 virtual double getLength() const { return length; }
365 virtual double getDistance(double time) const;
366 virtual void getPointAt(double distance, Point *p);
367 virtual void shortenBy(double distance, Point *newEnd);
368 virtual TrajectorySegment* splitAtByTime(double time, Point *newEnd);
369 virtual TrajectorySegment* splitAt(double distance, Point *newEnd);
370 virtual void getRefPos(double time, Pos &rp);
371 virtual double startAt(double time);
372 #ifdef MATLAB_MEX_FILE
373 virtual void plot(const char *style);
374 virtual void plotSpeed(const char *style);
377 double dist2param(double distance);
378 void getPointAtParam(double par, Point *p);
379 double getAngleAt(double distance);
380 double getRadiusAtParam(double par);
381 double getRadiusAt(double distance);
385 * Arc shaped segment.
387 class Arc : public TrajectorySegment
390 double angle; // vrcholovy uhel [-pi,+pi]
391 double startAngle; // uhel od stredu k p1
392 double radius; // polomer
393 double length; // delka segmentu
396 Arc(Point *_p1, Point *_p2, double _radius);
397 virtual void setMaxV(const TrajectoryConstraints &constr);
398 virtual double getLength() const {return length;}
399 virtual double getDistance(double time) const;
400 virtual void getPointAt(double distance, Point *p);
401 virtual void shortenBy(double distance, Point *newEnd);
402 virtual TrajectorySegment* splitAt(double distance, Point *newEnd);
403 virtual TrajectorySegment* splitAtByTime(double time, Point *newEnd);
404 virtual void getRefPos(double time, Pos &rp);
405 #ifdef MATLAB_MEX_FILE
406 virtual void plot(const char *style);