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
00038 #ifndef FCL_CCD_MOTION_H
00039 #define FCL_CCD_MOTION_H
00040
00041 #include "fcl/ccd/motion_base.h"
00042 #include "fcl/intersect.h"
00043 #include <iostream>
00044 #include <vector>
00045
00046 namespace fcl
00047 {
00048
00049
00050 template<typename BV>
00051 class SplineMotion : public MotionBase<BV>
00052 {
00053 public:
00055 SplineMotion(const Vec3f& Td0, const Vec3f& Td1, const Vec3f& Td2, const Vec3f& Td3,
00056 const Vec3f& Rd0, const Vec3f& Rd1, const Vec3f& Rd2, const Vec3f& Rd3)
00057 {
00058 Td[0] = Td0;
00059 Td[1] = Td1;
00060 Td[2] = Td2;
00061 Td[3] = Td3;
00062
00063 Rd[0] = Rd0;
00064 Rd[1] = Rd1;
00065 Rd[2] = Rd2;
00066 Rd[3] = Rd3;
00067
00068 Rd0Rd0 = Rd[0].dot(Rd[0]);
00069 Rd0Rd1 = Rd[0].dot(Rd[1]);
00070 Rd0Rd2 = Rd[0].dot(Rd[2]);
00071 Rd0Rd3 = Rd[0].dot(Rd[3]);
00072 Rd1Rd1 = Rd[1].dot(Rd[1]);
00073 Rd1Rd2 = Rd[1].dot(Rd[2]);
00074 Rd1Rd3 = Rd[1].dot(Rd[3]);
00075 Rd2Rd2 = Rd[2].dot(Rd[2]);
00076 Rd2Rd3 = Rd[2].dot(Rd[3]);
00077 Rd3Rd3 = Rd[3].dot(Rd[3]);
00078
00079 TA = Td[1] * 3 - Td[2] * 3 + Td[3] - Td[0];
00080 TB = (Td[0] - Td[1] * 2 + Td[2]) * 3;
00081 TC = (Td[2] - Td[0]) * 3;
00082
00083 RA = Rd[1] * 3 - Rd[2] * 3 + Rd[3] - Rd[0];
00084 RB = (Rd[0] - Rd[1] * 2 + Rd[2]) * 3;
00085 RC = (Rd[2] - Rd[0]) * 3;
00086
00087 integrate(0.0);
00088 }
00089
00093 bool integrate(double dt)
00094 {
00095 if(dt > 1) dt = 1;
00096
00097 Vec3f cur_T = Td[0] * getWeight0(dt) + Td[1] * getWeight1(dt) + Td[2] * getWeight2(dt) + Td[3] * getWeight3(dt);
00098 Vec3f cur_w = Rd[0] * getWeight0(dt) + Rd[1] * getWeight1(dt) + Rd[2] * getWeight2(dt) + Rd[3] * getWeight3(dt);
00099 FCL_REAL cur_angle = cur_w.length();
00100 cur_w.normalize();
00101
00102 Quaternion3f cur_q;
00103 cur_q.fromAxisAngle(cur_w, cur_angle);
00104
00105 tf.setTransform(cur_q, cur_T);
00106
00107 tf_t = dt;
00108
00109 return true;
00110 }
00111
00115 FCL_REAL computeMotionBound(const BV& bv, const Vec3f& n) const { return 0.0; }
00116
00117 FCL_REAL computeMotionBound(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& n) const
00118 {
00119 FCL_REAL T_bound = computeTBound(n);
00120
00121 FCL_REAL R_bound = fabs(a.dot(n)) + a.length() + (a.cross(n)).length();
00122 FCL_REAL R_bound_tmp = fabs(b.dot(n)) + b.length() + (b.cross(n)).length();
00123 if(R_bound_tmp > R_bound) R_bound = R_bound_tmp;
00124 R_bound_tmp = fabs(c.dot(n)) + c.length() + (c.cross(n)).length();
00125 if(R_bound_tmp > R_bound) R_bound = R_bound_tmp;
00126
00127 FCL_REAL dWdW_max = computeDWMax();
00128 FCL_REAL ratio = std::min(1 - tf_t, dWdW_max);
00129
00130 R_bound *= 2 * ratio;
00131
00132
00133
00134 return R_bound + T_bound;
00135 }
00136
00138 void getCurrentTransform(Matrix3f& R, Vec3f& T) const
00139 {
00140 R = tf.getRotation();
00141 T = tf.getTranslation();
00142 }
00143
00144 void getCurrentRotation(Matrix3f& R) const
00145 {
00146 R = tf.getRotation();
00147 }
00148
00149 void getCurrentTranslation(Vec3f& T) const
00150 {
00151 T = tf.getTranslation();
00152 }
00153
00154 void getCurrentTransform(Transform3f& tf_) const
00155 {
00156 tf_ = tf;
00157 }
00158
00159 protected:
00160 void computeSplineParameter()
00161 {
00162
00163 }
00164
00165 FCL_REAL getWeight0(FCL_REAL t) const
00166 {
00167 return (1 - 3 * t + 3 * t * t - t * t * t) / 6.0;
00168 }
00169
00170 FCL_REAL getWeight1(FCL_REAL t) const
00171 {
00172 return (4 - 6 * t * t + 3 * t * t * t) / 6.0;
00173 }
00174
00175 FCL_REAL getWeight2(FCL_REAL t) const
00176 {
00177 return (1 + 3 * t + 3 * t * t - 3 * t * t * t) / 6.0;
00178 }
00179
00180 FCL_REAL getWeight3(FCL_REAL t) const
00181 {
00182 return t * t * t / 6.0;
00183 }
00184
00185 FCL_REAL computeTBound(const Vec3f& n) const
00186 {
00187 FCL_REAL Ta = TA.dot(n);
00188 FCL_REAL Tb = TB.dot(n);
00189 FCL_REAL Tc = TC.dot(n);
00190
00191 std::vector<FCL_REAL> T_potential;
00192 T_potential.push_back(tf_t);
00193 T_potential.push_back(1);
00194 if(Tb * Tb - 3 * Ta * Tc >= 0)
00195 {
00196 if(Ta == 0)
00197 {
00198 if(Tb != 0)
00199 {
00200 FCL_REAL tmp = -Tc / (2 * Tb);
00201 if(tmp < 1 && tmp > tf_t)
00202 T_potential.push_back(tmp);
00203 }
00204 }
00205 else
00206 {
00207 FCL_REAL tmp_delta = sqrt(Tb * Tb - 3 * Ta * Tc);
00208 FCL_REAL tmp1 = (-Tb + tmp_delta) / (3 * Ta);
00209 FCL_REAL tmp2 = (-Tb - tmp_delta) / (3 * Ta);
00210 if(tmp1 < 1 && tmp1 > tf_t)
00211 T_potential.push_back(tmp1);
00212 if(tmp2 < 1 && tmp2 > tf_t)
00213 T_potential.push_back(tmp2);
00214 }
00215 }
00216
00217 FCL_REAL T_bound = Ta * T_potential[0] * T_potential[0] * T_potential[0] + Tb * T_potential[0] * T_potential[0] + Tc * T_potential[0];
00218 for(unsigned int i = 1; i < T_potential.size(); ++i)
00219 {
00220 FCL_REAL T_bound_tmp = Ta * T_potential[i] * T_potential[i] * T_potential[i] + Tb * T_potential[i] * T_potential[i] + Tc * T_potential[i];
00221 if(T_bound_tmp > T_bound) T_bound = T_bound_tmp;
00222 }
00223
00224
00225 FCL_REAL cur_delta = Ta * tf_t * tf_t * tf_t + Tb * tf_t * tf_t + Tc * tf_t;
00226
00227 T_bound -= cur_delta;
00228 T_bound /= 6.0;
00229
00230 return T_bound;
00231 }
00232
00233 FCL_REAL computeDWMax() const
00234 {
00235
00236 int a00[5] = {1,-4,6,-4,1};
00237 int a01[5] = {-3,10,-11,4,0};
00238 int a02[5] = {3,-8,6,0,-1};
00239 int a03[5] = {-1,2,-1,0,0};
00240 int a11[5] = {9,-24,16,0,0};
00241 int a12[5] = {-9,18,-5,-4,0};
00242 int a13[5] = {3,-4,0,0,0};
00243 int a22[5] = {9,-12,-2,4,1};
00244 int a23[5] = {-3,2,1,0,0};
00245 int a33[5] = {1,0,0,0,0};
00246
00247 FCL_REAL a[5];
00248
00249 for(int i = 0; i < 5; ++i)
00250 {
00251 a[i] = Rd0Rd0 * a00[i] + Rd0Rd1 * a01[i] + Rd0Rd2 * a02[i] + Rd0Rd3 * a03[i]
00252 + Rd0Rd1 * a01[i] + Rd1Rd1 * a11[i] + Rd1Rd2 * a12[i] + Rd1Rd3 * a13[i]
00253 + Rd0Rd2 * a02[i] + Rd1Rd2 * a12[i] + Rd2Rd2 * a22[i] + Rd2Rd3 * a23[i]
00254 + Rd0Rd3 * a03[i] + Rd1Rd3 * a13[i] + Rd2Rd3 * a23[i] + Rd3Rd3 * a33[i];
00255 a[i] /= 4.0;
00256 }
00257
00258
00259 int da00[4] = {4,-12,12,-4};
00260 int da01[4] = {-12,30,-22,4};
00261 int da02[4] = {12,-24,12,0};
00262 int da03[4] = {-4,6,-2,0};
00263 int da11[4] = {36,-72,32,0};
00264 int da12[4] = {-36,54,-10,-4};
00265 int da13[4] = {12,-12,0,0};
00266 int da22[4] = {36,-36,-4,4};
00267 int da23[4] = {-12,6,2,0};
00268 int da33[4] = {4,0,0,0};
00269
00270 FCL_REAL da[4];
00271 for(int i = 0; i < 4; ++i)
00272 {
00273 da[i] = Rd0Rd0 * da00[i] + Rd0Rd1 * da01[i] + Rd0Rd2 * da02[i] + Rd0Rd3 * da03[i]
00274 + Rd0Rd1 * da01[i] + Rd1Rd1 * da11[i] + Rd1Rd2 * da12[i] + Rd1Rd3 * da13[i]
00275 + Rd0Rd2 * da02[i] + Rd1Rd2 * da12[i] + Rd2Rd2 * da22[i] + Rd2Rd3 * da23[i]
00276 + Rd0Rd3 * da03[i] + Rd1Rd3 * da13[i] + Rd2Rd3 * da23[i] + Rd3Rd3 * da33[i];
00277 da[i] /= 4.0;
00278 }
00279
00280 FCL_REAL roots[3];
00281
00282 int root_num = PolySolver::solveCubic(da, roots);
00283
00284 FCL_REAL dWdW_max = a[0] * tf_t * tf_t * tf_t + a[1] * tf_t * tf_t * tf_t + a[2] * tf_t * tf_t + a[3] * tf_t + a[4];
00285 FCL_REAL dWdW_1 = a[0] + a[1] + a[2] + a[3] + a[4];
00286 if(dWdW_max < dWdW_1) dWdW_max = dWdW_1;
00287 for(int i = 0; i < root_num; ++i)
00288 {
00289 FCL_REAL v = roots[i];
00290
00291 if(v >= tf_t && v <= 1)
00292 {
00293 FCL_REAL value = a[0] * v * v * v * v + a[1] * v * v * v + a[2] * v * v + a[3] * v + a[4];
00294 if(value > dWdW_max) dWdW_max = value;
00295 }
00296 }
00297
00298 return sqrt(dWdW_max);
00299 }
00300
00301 Vec3f Td[4];
00302 Vec3f Rd[4];
00303
00304 Vec3f TA, TB, TC;
00305 Vec3f RA, RB, RC;
00306
00307 FCL_REAL Rd0Rd0, Rd0Rd1, Rd0Rd2, Rd0Rd3, Rd1Rd1, Rd1Rd2, Rd1Rd3, Rd2Rd2, Rd2Rd3, Rd3Rd3;
00309 Transform3f tf;
00310
00312 FCL_REAL tf_t;
00313 };
00314
00315 template<typename BV>
00316 class ScrewMotion : public MotionBase<BV>
00317 {
00318 public:
00320 ScrewMotion()
00321 {
00323 axis.setValue(1, 0, 0);
00324 angular_vel = 0;
00325
00329 linear_vel = 0;
00330 }
00331
00333 ScrewMotion(const Matrix3f& R1, const Vec3f& T1,
00334 const Matrix3f& R2, const Vec3f& T2) : tf1(R1, T1),
00335 tf2(R2, T2),
00336 tf(tf1)
00337 {
00338 computeScrewParameter();
00339 }
00340
00342 ScrewMotion(const Transform3f& tf1_,
00343 const Transform3f& tf2_) : tf1(tf1_),
00344 tf2(tf2_),
00345 tf(tf1)
00346 {
00347 computeScrewParameter();
00348 }
00349
00353 bool integrate(double dt)
00354 {
00355 if(dt > 1) dt = 1;
00356
00357 tf.setQuatRotation(absoluteRotation(dt));
00358
00359 Quaternion3f delta_rot = deltaRotation(dt);
00360 tf.setTranslation(p + axis * (dt * linear_vel) + delta_rot.transform(tf1.getTranslation() - p));
00361
00362 return true;
00363 }
00364
00368 FCL_REAL computeMotionBound(const BV& bv, const Vec3f& n) const { return 0.0; }
00369
00370 FCL_REAL computeMotionBound(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& n) const
00371 {
00372 FCL_REAL proj_max = ((tf.getQuatRotation().transform(a) + tf.getTranslation() - p).cross(axis)).sqrLength();
00373 FCL_REAL tmp;
00374 tmp = ((tf.getQuatRotation().transform(b) + tf.getTranslation() - p).cross(axis)).sqrLength();
00375 if(tmp > proj_max) proj_max = tmp;
00376 tmp = ((tf.getQuatRotation().transform(c) + tf.getTranslation() - p).cross(axis)).sqrLength();
00377 if(tmp > proj_max) proj_max = tmp;
00378
00379 proj_max = sqrt(proj_max);
00380
00381 FCL_REAL v_dot_n = axis.dot(n) * linear_vel;
00382 FCL_REAL w_cross_n = (axis.cross(n)).length() * angular_vel;
00383 FCL_REAL mu = v_dot_n + w_cross_n * proj_max;
00384
00385 return mu;
00386 }
00387
00389 void getCurrentTransform(Matrix3f& R, Vec3f& T) const
00390 {
00391 R = tf.getRotation();
00392 T = tf.getTranslation();
00393 }
00394
00395 void getCurrentRotation(Matrix3f& R) const
00396 {
00397 R = tf.getRotation();
00398 }
00399
00400 void getCurrentTranslation(Vec3f& T) const
00401 {
00402 T = tf.getTranslation();
00403 }
00404
00405 void getCurrentTransform(Transform3f& tf_) const
00406 {
00407 tf_ = tf;
00408 }
00409
00410 protected:
00411 void computeScrewParameter()
00412 {
00413 Quaternion3f deltaq = tf2.getQuatRotation() * inverse(tf1.getQuatRotation());
00414 deltaq.toAxisAngle(axis, angular_vel);
00415 if(angular_vel < 0)
00416 {
00417 angular_vel = -angular_vel;
00418 axis = -axis;
00419 }
00420
00421 if(angular_vel < 1e-10)
00422 {
00423 angular_vel = 0;
00424 axis = tf2.getTranslation() - tf1.getTranslation();
00425 linear_vel = axis.length();
00426 p = tf1.getTranslation();
00427 }
00428 else
00429 {
00430 Vec3f o = tf2.getTranslation() - tf1.getTranslation();
00431 p = (tf1.getTranslation() + tf2.getTranslation() + axis.cross(o) * (1.0 / tan(angular_vel / 2.0))) * 0.5;
00432 linear_vel = o.dot(axis);
00433 }
00434 }
00435
00436 Quaternion3f deltaRotation(FCL_REAL dt) const
00437 {
00438 Quaternion3f res;
00439 res.fromAxisAngle(axis, (FCL_REAL)(dt * angular_vel));
00440 return res;
00441 }
00442
00443 Quaternion3f absoluteRotation(FCL_REAL dt) const
00444 {
00445 Quaternion3f delta_t = deltaRotation(dt);
00446 return delta_t * tf1.getQuatRotation();
00447 }
00448
00450 Transform3f tf1;
00451
00453 Transform3f tf2;
00454
00456 Transform3f tf;
00457
00459 Vec3f axis;
00460
00462 Vec3f p;
00463
00465 FCL_REAL linear_vel;
00466
00468 FCL_REAL angular_vel;
00469 };
00470
00471
00477 template<>
00478 FCL_REAL ScrewMotion<RSS>::computeMotionBound(const RSS& bv, const Vec3f& n) const;
00479
00480
00488 template<typename BV>
00489 class InterpMotion : public MotionBase<BV>
00490 {
00491 public:
00493 InterpMotion()
00494 {
00496 angular_axis.setValue(1, 0, 0);
00497 angular_vel = 0;
00498
00502 }
00503
00505 InterpMotion(const Matrix3f& R1, const Vec3f& T1,
00506 const Matrix3f& R2, const Vec3f& T2) : tf1(R1, T1),
00507 tf2(R2, T2),
00508 tf(tf1)
00509 {
00511 computeVelocity();
00512 }
00513
00514
00515 InterpMotion(const Transform3f& tf1_, const Transform3f& tf2_) : tf1(tf1_),
00516 tf2(tf2_),
00517 tf(tf1)
00518 {
00520 computeVelocity();
00521 }
00522
00525 InterpMotion(const Matrix3f& R1, const Vec3f& T1,
00526 const Matrix3f& R2, const Vec3f& T2,
00527 const Vec3f& O) : tf1(R1, T1),
00528 tf2(R2, T2),
00529 tf(tf1),
00530 reference_p(O)
00531 {
00533 computeVelocity();
00534 }
00535
00536 InterpMotion(const Transform3f& tf1_, const Transform3f& tf2_, const Vec3f& O) : tf1(tf1_),
00537 tf2(tf2_),
00538 tf(tf1),
00539 reference_p(O)
00540 {
00541 }
00542
00543
00547 bool integrate(double dt)
00548 {
00549 if(dt > 1) dt = 1;
00550
00551 tf.setQuatRotation(absoluteRotation(dt));
00552 tf.setTranslation(linear_vel * dt + tf1.transform(reference_p) - tf.getQuatRotation().transform(reference_p));
00553
00554 return true;
00555 }
00556
00560 FCL_REAL computeMotionBound(const BV& bv, const Vec3f& n) const { return 0.0; }
00561
00567 FCL_REAL computeMotionBound(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& n) const
00568 {
00569 FCL_REAL proj_max = ((tf.getQuatRotation().transform(a - reference_p)).cross(angular_axis)).sqrLength();
00570 FCL_REAL tmp;
00571 tmp = ((tf.getQuatRotation().transform(b - reference_p)).cross(angular_axis)).sqrLength();
00572 if(tmp > proj_max) proj_max = tmp;
00573 tmp = ((tf.getQuatRotation().transform(c - reference_p)).cross(angular_axis)).sqrLength();
00574 if(tmp > proj_max) proj_max = tmp;
00575
00576 proj_max = sqrt(proj_max);
00577
00578 FCL_REAL v_dot_n = linear_vel.dot(n);
00579 FCL_REAL w_cross_n = (angular_axis.cross(n)).length() * angular_vel;
00580 FCL_REAL mu = v_dot_n + w_cross_n * proj_max;
00581
00582 return mu;
00583 }
00584
00586 void getCurrentTransform(Matrix3f& R, Vec3f& T) const
00587 {
00588 R = tf.getRotation();
00589 T = tf.getTranslation();
00590 }
00591
00592 void getCurrentRotation(Matrix3f& R) const
00593 {
00594 R = tf.getRotation();
00595 }
00596
00597 void getCurrentTranslation(Vec3f& T) const
00598 {
00599 T = tf.getTranslation();
00600 }
00601
00602 void getCurrentTransform(Transform3f& tf_) const
00603 {
00604 tf_ = tf;
00605 }
00606
00607 protected:
00608
00609 void computeVelocity()
00610 {
00611 linear_vel = tf2.transform(reference_p) - tf1.transform(reference_p);
00612 Quaternion3f deltaq = tf2.getQuatRotation() * inverse(tf1.getQuatRotation());
00613 deltaq.toAxisAngle(angular_axis, angular_vel);
00614 if(angular_vel < 0)
00615 {
00616 angular_vel = -angular_vel;
00617 angular_axis = -angular_axis;
00618 }
00619 }
00620
00621
00622 Quaternion3f deltaRotation(FCL_REAL dt) const
00623 {
00624 Quaternion3f res;
00625 res.fromAxisAngle(angular_axis, (FCL_REAL)(dt * angular_vel));
00626 return res;
00627 }
00628
00629 Quaternion3f absoluteRotation(FCL_REAL dt) const
00630 {
00631 Quaternion3f delta_t = deltaRotation(dt);
00632 return delta_t * tf1.getQuatRotation();
00633 }
00634
00636 Transform3f tf1;
00637
00639 Transform3f tf2;
00640
00642 Transform3f tf;
00643
00645 Vec3f linear_vel;
00646
00648 FCL_REAL angular_vel;
00649
00651 Vec3f angular_axis;
00652
00654 Vec3f reference_p;
00655 };
00656
00657
00663 template<>
00664 FCL_REAL InterpMotion<RSS>::computeMotionBound(const RSS& bv, const Vec3f& n) const;
00665
00666
00667 }
00668
00669 #endif