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 #ifndef ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_
00041 #define ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_
00042
00043 #include <robot_controllers/trajectory.h>
00044
00045 namespace robot_controllers
00046 {
00047
00049 struct Spline
00050 {
00051 double coef[6];
00052 };
00053
00054 enum SplineType
00055 {
00056 QUINTIC,
00057 CUBIC,
00058 LINEAR
00059 };
00060
00062 static inline void generatePowers(int n, double x, double* powers)
00063 {
00064 powers[0] = 1.0;
00065 for (int i=1; i<=n; i++)
00066 {
00067 powers[i] = powers[i-1]*x;
00068 }
00069 }
00070
00082 static void QuinticSpline(double p0, double v0, double a0,
00083 double p1, double v1, double a1,
00084 double t, Spline& s)
00085 {
00086 if (t == 0.0)
00087 {
00088 s.coef[0] = p1;
00089 s.coef[1] = v1;
00090 s.coef[2] = 0.5*a1;
00091 s.coef[3] = 0.0;
00092 s.coef[4] = 0.0;
00093 s.coef[5] = 0.0;
00094 }
00095 else
00096 {
00097 double T[6];
00098 generatePowers(5, t, T);
00099
00100 s.coef[0] = p0;
00101 s.coef[1] = v0;
00102 s.coef[2] = 0.5*a0;
00103 s.coef[3] = (-20.0*p0 + 20.0*p1 - 3.0*a0*T[2] + a1*T[2] -
00104 12.0*v0*T[1] - 8.0*v1*T[1]) / (2.0*T[3]);
00105 s.coef[4] = (30.0*p0 - 30.0*p1 + 3.0*a0*T[2] - 2.0*a1*T[2] +
00106 16.0*v0*T[1] + 14.0*v1*T[1]) / (2.0*T[4]);
00107 s.coef[5] = (-12.0*p0 + 12.0*p1 - a0*T[2] + a1*T[2] -
00108 6.0*v0*T[1] - 6.0*v1*T[1]) / (2.0*T[5]);
00109 }
00110 }
00111
00115 static void sampleQuinticSpline(Spline& s, double t,
00116 double& position, double& velocity, double& acceleration)
00117 {
00118 double T[6];
00119 generatePowers(5, t, T);
00120
00121 position = T[0]*s.coef[0] +
00122 T[1]*s.coef[1] +
00123 T[2]*s.coef[2] +
00124 T[3]*s.coef[3] +
00125 T[4]*s.coef[4] +
00126 T[5]*s.coef[5];
00127
00128 velocity = T[0]*s.coef[1] +
00129 2.0*T[1]*s.coef[2] +
00130 3.0*T[2]*s.coef[3] +
00131 4.0*T[3]*s.coef[4] +
00132 5.0*T[4]*s.coef[5];
00133
00134 acceleration = 2.0*T[0]*s.coef[2] +
00135 6.0*T[1]*s.coef[3] +
00136 12.0*T[2]*s.coef[4] +
00137 20.0*T[3]*s.coef[5];
00138 }
00139
00149 static void CubicSpline(double p0, double v0, double p1, double v1, double t, Spline& s)
00150 {
00151 if (t == 0.0)
00152 {
00153 s.coef[0] = p1;
00154 s.coef[1] = v1;
00155 s.coef[2] = 0.0;
00156 s.coef[3] = 0.0;
00157 }
00158 else
00159 {
00160 double T[4];
00161 generatePowers(3, t, T);
00162
00163 s.coef[0] = p0;
00164 s.coef[1] = v0;
00165 s.coef[2] = (3.0 * p1 - 3.0 * p0 - 2.0 *v0*T[1] - v1*T[1]) / T[2];
00166 s.coef[3] = (-2.0 * p1 + 2.0 * p0 + v0*T[1] + v1*T[1]) / T[3];
00167 }
00168 }
00169
00173 static void sampleCubicSpline(Spline s, double t, double& position, double& velocity)
00174 {
00175 double T[4];
00176 generatePowers(3, t, T);
00177
00178 position = T[0]*s.coef[0] +
00179 T[1]*s.coef[1] +
00180 T[2]*s.coef[2] +
00181 T[3]*s.coef[3];
00182
00183 velocity = T[0]*s.coef[1] +
00184 2.0*T[1]*s.coef[2] +
00185 3.0*T[2]*s.coef[3];
00186 }
00187
00188 static void LinearSpline(double p0, double p1, double t, Spline& s)
00189 {
00190 s.coef[0] = p0;
00191 s.coef[1] = p1 - p0;
00192 s.coef[2] = t;
00193 }
00194
00195 static void sampleLinearSpline(Spline& s, double t, double& position)
00196 {
00197 position = s.coef[0] + (s.coef[1] * t/s.coef[2]);
00198 }
00199
00203 class SplineTrajectorySampler : public TrajectorySampler
00204 {
00205 struct Segment
00206 {
00207 double start_time;
00208 double end_time;
00209 int type;
00210 std::vector<Spline> splines;
00211 };
00212
00213 public:
00215 SplineTrajectorySampler(const Trajectory& trajectory) :
00216 trajectory_(trajectory)
00217 {
00218
00219 if (trajectory.size() == 0)
00220 {
00221 throw 0;
00222 }
00223
00224
00225 size_t num_joints = trajectory.points[0].q.size();
00226
00227
00228 if (trajectory.size() == 1)
00229 {
00230 segments_.resize(1);
00231 segments_[0].start_time = segments_[0].end_time = trajectory.points[0].time;
00232
00233
00234 segments_[0].splines.resize(num_joints);
00235 for (size_t j = 0; j < num_joints; ++j)
00236 {
00237 LinearSpline(trajectory.points[0].q[j],
00238 trajectory.points[0].q[j],
00239 0.0,
00240 segments_[0].splines[j]);
00241 }
00242 segments_[0].type = LINEAR;
00243 result.q.resize(num_joints);
00244 }
00245 else
00246 {
00247
00248 segments_.resize(trajectory.size()-1);
00249
00250
00251 for (size_t p = 0; p < segments_.size(); ++p)
00252 {
00253
00254 segments_[p].start_time = trajectory.points[p].time;
00255 segments_[p].end_time = trajectory.points[p+1].time;
00256
00257
00258 segments_[p].splines.resize(num_joints);
00259 if (trajectory.points[p].qdd.size() == trajectory.points[p].q.size())
00260 {
00261 result.q.resize(num_joints);
00262 result.qd.resize(num_joints);
00263 result.qdd.resize(num_joints);
00264
00265
00266 for (size_t j = 0; j < num_joints; ++j)
00267 {
00268 QuinticSpline(trajectory.points[p].q[j],
00269 trajectory.points[p].qd[j],
00270 trajectory.points[p].qdd[j],
00271 trajectory.points[p+1].q[j],
00272 trajectory.points[p+1].qd[j],
00273 trajectory.points[p+1].qdd[j],
00274 segments_[p].end_time - segments_[p].start_time,
00275 segments_[p].splines[j]);
00276 }
00277 segments_[p].type = QUINTIC;
00278 }
00279 else if (trajectory.points[p].qd.size() == trajectory.points[p].q.size())
00280 {
00281 result.q.resize(num_joints);
00282 result.qd.resize(num_joints);
00283
00284
00285 for (size_t j = 0; j < num_joints; ++j)
00286 {
00287 CubicSpline(trajectory.points[p].q[j],
00288 trajectory.points[p].qd[j],
00289 trajectory.points[p+1].q[j],
00290 trajectory.points[p+1].qd[j],
00291 segments_[p].end_time - segments_[p].start_time,
00292 segments_[p].splines[j]);
00293 }
00294 segments_[p].type = CUBIC;
00295 }
00296 else
00297 {
00298 result.q.resize(num_joints);
00299
00300
00301 for (size_t j = 0; j < num_joints; ++j)
00302 {
00303 LinearSpline(trajectory.points[p].q[j],
00304 trajectory.points[p+1].q[j],
00305 segments_[p].end_time - segments_[p].start_time,
00306 segments_[p].splines[j]);
00307 }
00308 segments_[p].type = LINEAR;
00309 }
00310 }
00311 }
00312 seg_ = -1;
00313 }
00314
00316 virtual TrajectoryPoint sample(double time)
00317 {
00318
00319 while ((seg_ + 1 < int(segments_.size())) &&
00320 (segments_[seg_ + 1].start_time < time))
00321 {
00322 ++seg_;
00323 }
00324
00325
00326 if (seg_ == -1)
00327 return TrajectoryPoint();
00328
00329
00330 if (time > end_time())
00331 time = end_time();
00332
00333
00334 for (size_t i = 0; i < segments_[seg_].splines.size(); ++i)
00335 {
00336 if (segments_[seg_].type == QUINTIC)
00337 {
00338 sampleQuinticSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
00339 result.q[i], result.qd[i], result.qdd[i]);
00340 }
00341 else if(segments_[seg_].type == CUBIC)
00342 {
00343 sampleCubicSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
00344 result.q[i], result.qd[i]);
00345 }
00346 else
00347 {
00348 sampleLinearSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
00349 result.q[i]);
00350 }
00351 }
00352
00353 result.time = time;
00354 return result;
00355 }
00356
00358 virtual double end_time()
00359 {
00360 return segments_[segments_.size()-1].end_time;
00361 }
00362
00364 virtual Trajectory getTrajectory()
00365 {
00366 return trajectory_;
00367 }
00368
00369 private:
00370 std::vector<Segment> segments_;
00371 Trajectory trajectory_;
00372 TrajectoryPoint result;
00373 int seg_;
00374 };
00375
00376 }
00377
00378 #endif // ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_