Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef MATH_SPLINE_H__
00042 #define MATH_SPLINE_H__
00043
00044 #include <iostream>
00045 #include <vector>
00046 #include <cfloat>
00047 #include <stdexcept>
00048 #include <boost/shared_ptr.hpp>
00049
00050 namespace pr2_base_trajectory_action {
00051
00052 static inline void pows(int n, double base, double* ret)
00053 {
00054 ret[0] = 1.0;
00055 for(int i = 1; i <= n; ++i)
00056 {
00057 ret[i] = ret[i-1] * base;
00058 }
00059 }
00060
00061 struct Motion
00062 {
00063 double position, velocity, acceleration;
00064 Motion() : position(0.0), velocity(DBL_MAX), acceleration(DBL_MAX) {}
00065 Motion(double position) : position(position), velocity(DBL_MAX), acceleration(DBL_MAX) {}
00066 Motion(double position, double velocity)
00067 : position(position), velocity(velocity), acceleration(DBL_MAX) {}
00068 Motion(double position, double velocity, double acceleration)
00069 : position(position), velocity(velocity), acceleration(acceleration) {}
00070 friend std::ostream &operator << (std::ostream &os, const Motion &m)
00071 {
00072 return os << "<pos: " << m.position << ", vel: " << m.velocity << ", acc: " << m.acceleration << ">";
00073 }
00074 };
00075 struct BaseMotion
00076 {
00077 Motion x, y, yaw;
00078 const Motion &operator[] (size_t i) const {
00079 switch (i) {
00080 case 0: return x;
00081 case 1: return y;
00082 case 2: return yaw;
00083 default: throw std::out_of_range("range must be 0-2");
00084 }
00085 }
00086 Motion &operator[] (size_t i) {
00087 switch (i) {
00088 case 0: return x;
00089 case 1: return y;
00090 case 2: return yaw;
00091 default: throw std::out_of_range("range must be 0-2");
00092 }
00093 }
00094 friend std::ostream &operator << (std::ostream &os, const BaseMotion &m) {
00095 return os << "<x: " << m.x.position << " y: " << m.y.position << " yaw: " << m.yaw.position << ">";
00096 }
00097 bool hasVelocity() const {
00098 return x.velocity != DBL_MAX && y.velocity != DBL_MAX && yaw.velocity != DBL_MAX;
00099 }
00100 bool hasAcceleration() const {
00101 return x.acceleration != DBL_MAX && y.acceleration != DBL_MAX && yaw.acceleration != DBL_MAX;
00102 }
00103 };
00104
00105 struct Spline
00106 {
00107 std::vector<double> coefficients;
00108 Spline() : coefficients(6, 0.0) {};
00109 virtual ~Spline(){ coefficients.clear(); };
00110 virtual void sample(const double &time, Motion &motion) const {
00111 double t[6];
00112 pows(5, time, t);
00113 motion.position =
00114 t[0] * coefficients[0] +
00115 t[1] * coefficients[1] +
00116 t[2] * coefficients[2] +
00117 t[3] * coefficients[3] +
00118 t[4] * coefficients[4] +
00119 t[5] * coefficients[5];
00120
00121 motion.velocity =
00122 1.0 * t[0] * coefficients[1] +
00123 2.0 * t[1] * coefficients[2] +
00124 3.0 * t[2] * coefficients[3] +
00125 4.0 * t[3] * coefficients[4] +
00126 5.0 * t[4] * coefficients[5];
00127
00128 motion.acceleration =
00129 2.0 * t[0] * coefficients[2] +
00130 6.0 * t[1] * coefficients[3] +
00131 12.0 * t[2] * coefficients[4] +
00132 20.0 * t[3] * coefficients[5];
00133 }
00134
00135 virtual void sampleWithTimeBounds(const double &duration,
00136 const double &time, Motion &motion) const {
00137 if (time < 0.0) {
00138 sample(0.0, motion);
00139 motion.velocity = 0.0;
00140 motion.acceleration = 0.0;
00141 } else if (time > duration) {
00142 sample(duration, motion);
00143 motion.velocity = 0.0;
00144 motion.acceleration = 0.0;
00145 } else {
00146 sample(time, motion);
00147 }
00148 }
00149 };
00150
00151 struct Line : public Spline {
00152 Line(const Motion &start, const Motion &end, const double &duration) {
00153 coefficients[0] = start.position;
00154 if (duration == 0.0) coefficients[1] = 0.0;
00155 else coefficients[1] = (end.position - start.position) / duration;
00156 }
00157 };
00158
00159 struct CubicSpline : public Spline {
00160 CubicSpline(const Motion &start, const Motion &end, const double &duration) {
00161 if (duration == 0.0) {
00162 coefficients[0] = end.position;
00163 coefficients[1] = end.velocity;
00164 } else {
00165 double t[4];
00166 pows(3, duration, t);
00167 coefficients[0] = start.position;
00168 coefficients[1] = start.velocity;
00169 coefficients[2] = (-3.0 * start.position +
00170 3.0 * end.position -
00171 2.0 * start.velocity * t[1] -
00172 end.velocity * t[1]) / t[2];
00173 coefficients[3] = (2.0 * start.position -
00174 2.0 * end.position +
00175 start.velocity * t[1] +
00176 end.velocity * t[1]) / t[3];
00177 }
00178 }
00179 };
00180
00181 struct QuinticSpline : public Spline {
00182 QuinticSpline(const Motion &start, const Motion &end, const double &duration) {
00183 if (duration == 0.0) {
00184 coefficients[0] = end.position;
00185 coefficients[1] = end.velocity;
00186 coefficients[2] = 0.5 * end.acceleration;
00187 } else {
00188 double t[6];
00189 pows(5, duration, t);
00190
00191 coefficients[0] = start.position;
00192 coefficients[1] = start.velocity;
00193 coefficients[2] = 0.5 * start.acceleration;
00194 coefficients[3] = (-20.0 * start.position +
00195 20.0 * end.position -
00196 3.0 * start.acceleration * t[2] +
00197 end.acceleration * t[2] -
00198 12.0 * start.velocity * t[1] -
00199 8.0 * end.velocity * t[1]) / (2.0 * t[3]);
00200 coefficients[4] = ( 30.0 * start.position -
00201 30.0 * end.position +
00202 3.0 * start.acceleration * t[2] -
00203 2.0 * end.acceleration * t[2] +
00204 16.0 * start.velocity * t[1] +
00205 14.0 * end.velocity * t[1]) / (2.0 * t[4]);
00206 coefficients[5] = (-12.0 * start.position +
00207 12.0 * end.position -
00208 start.acceleration * t[2] +
00209 end.acceleration * t[2] -
00210 6.0 * start.velocity * t[1] -
00211 6.0 * end.velocity * t[1]) / (2.0*t[5]);
00212 }
00213 }
00214 };
00215 }
00216
00217 #endif // MATH_SPLINE_H__