1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011-2014, Willow Garage, Inc.
5 * Copyright (c) 2014-2016, Open Source Robotics Foundation
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of Open Source Robotics Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /** \author Jia Pan */
37
38
39 #include "fcl/ccd/motion.h"
40
41 namespace fcl
42 {
43
44 template<>
visit(const SplineMotion & motion) const45 FCL_REAL TBVMotionBoundVisitor<RSS>::visit(const SplineMotion& motion) const
46 {
47 FCL_REAL T_bound = motion.computeTBound(n);
48 FCL_REAL tf_t = motion.getCurrentTime();
49
50 Vec3f c1 = bv.Tr;
51 Vec3f c2 = bv.Tr + bv.axis[0] * bv.l[0];
52 Vec3f c3 = bv.Tr + bv.axis[1] * bv.l[1];
53 Vec3f c4 = bv.Tr + bv.axis[0] * bv.l[0] + bv.axis[1] * bv.l[1];
54
55 FCL_REAL tmp;
56 // max_i |c_i * n|
57 FCL_REAL cn_max = std::abs(c1.dot(n));
58 tmp = std::abs(c2.dot(n));
59 if(tmp > cn_max) cn_max = tmp;
60 tmp = std::abs(c3.dot(n));
61 if(tmp > cn_max) cn_max = tmp;
62 tmp = std::abs(c4.dot(n));
63 if(tmp > cn_max) cn_max = tmp;
64
65 // max_i ||c_i||
66 FCL_REAL cmax = c1.sqrLength();
67 tmp = c2.sqrLength();
68 if(tmp > cmax) cmax = tmp;
69 tmp = c3.sqrLength();
70 if(tmp > cmax) cmax = tmp;
71 tmp = c4.sqrLength();
72 if(tmp > cmax) cmax = tmp;
73 cmax = sqrt(cmax);
74
75 // max_i ||c_i x n||
76 FCL_REAL cxn_max = (c1.cross(n)).sqrLength();
77 tmp = (c2.cross(n)).sqrLength();
78 if(tmp > cxn_max) cxn_max = tmp;
79 tmp = (c3.cross(n)).sqrLength();
80 if(tmp > cxn_max) cxn_max = tmp;
81 tmp = (c4.cross(n)).sqrLength();
82 if(tmp > cxn_max) cxn_max = tmp;
83 cxn_max = sqrt(cxn_max);
84
85 FCL_REAL dWdW_max = motion.computeDWMax();
86 FCL_REAL ratio = std::min(1 - tf_t, dWdW_max);
87
88 FCL_REAL R_bound = 2 * (cn_max + cmax + cxn_max + 3 * bv.r) * ratio;
89
90
91 // std::cout << R_bound << " " << T_bound << std::endl;
92
93 return R_bound + T_bound;
94 }
95
96
visit(const SplineMotion & motion) const97 FCL_REAL TriangleMotionBoundVisitor::visit(const SplineMotion& motion) const
98 {
99 FCL_REAL T_bound = motion.computeTBound(n);
100 FCL_REAL tf_t = motion.getCurrentTime();
101
102 FCL_REAL R_bound = std::abs(a.dot(n)) + a.length() + (a.cross(n)).length();
103 FCL_REAL R_bound_tmp = std::abs(b.dot(n)) + b.length() + (b.cross(n)).length();
104 if(R_bound_tmp > R_bound) R_bound = R_bound_tmp;
105 R_bound_tmp = std::abs(c.dot(n)) + c.length() + (c.cross(n)).length();
106 if(R_bound_tmp > R_bound) R_bound = R_bound_tmp;
107
108 FCL_REAL dWdW_max = motion.computeDWMax();
109 FCL_REAL ratio = std::min(1 - tf_t, dWdW_max);
110
111 R_bound *= 2 * ratio;
112
113 // std::cout << R_bound << " " << T_bound << std::endl;
114
115 return R_bound + T_bound;
116 }
117
SplineMotion(const Vec3f & Td0,const Vec3f & Td1,const Vec3f & Td2,const Vec3f & Td3,const Vec3f & Rd0,const Vec3f & Rd1,const Vec3f & Rd2,const Vec3f & Rd3)118 SplineMotion::SplineMotion(const Vec3f& Td0, const Vec3f& Td1, const Vec3f& Td2, const Vec3f& Td3,
119 const Vec3f& Rd0, const Vec3f& Rd1, const Vec3f& Rd2, const Vec3f& Rd3) : MotionBase()
120 {
121 Td[0] = Td0;
122 Td[1] = Td1;
123 Td[2] = Td2;
124 Td[3] = Td3;
125
126 Rd[0] = Rd0;
127 Rd[1] = Rd1;
128 Rd[2] = Rd2;
129 Rd[3] = Rd3;
130
131 Rd0Rd0 = Rd[0].dot(Rd[0]);
132 Rd0Rd1 = Rd[0].dot(Rd[1]);
133 Rd0Rd2 = Rd[0].dot(Rd[2]);
134 Rd0Rd3 = Rd[0].dot(Rd[3]);
135 Rd1Rd1 = Rd[1].dot(Rd[1]);
136 Rd1Rd2 = Rd[1].dot(Rd[2]);
137 Rd1Rd3 = Rd[1].dot(Rd[3]);
138 Rd2Rd2 = Rd[2].dot(Rd[2]);
139 Rd2Rd3 = Rd[2].dot(Rd[3]);
140 Rd3Rd3 = Rd[3].dot(Rd[3]);
141
142 TA = Td[1] * 3 - Td[2] * 3 + Td[3] - Td[0];
143 TB = (Td[0] - Td[1] * 2 + Td[2]) * 3;
144 TC = (Td[2] - Td[0]) * 3;
145
146 RA = Rd[1] * 3 - Rd[2] * 3 + Rd[3] - Rd[0];
147 RB = (Rd[0] - Rd[1] * 2 + Rd[2]) * 3;
148 RC = (Rd[2] - Rd[0]) * 3;
149
150 integrate(0.0);
151 }
152
integrate(double dt) const153 bool SplineMotion::integrate(double dt) const
154 {
155 if(dt > 1) dt = 1;
156
157 Vec3f cur_T = Td[0] * getWeight0(dt) + Td[1] * getWeight1(dt) + Td[2] * getWeight2(dt) + Td[3] * getWeight3(dt);
158 Vec3f cur_w = Rd[0] * getWeight0(dt) + Rd[1] * getWeight1(dt) + Rd[2] * getWeight2(dt) + Rd[3] * getWeight3(dt);
159 FCL_REAL cur_angle = cur_w.length();
160 cur_w.normalize();
161
162 Quaternion3f cur_q;
163 cur_q.fromAxisAngle(cur_w, cur_angle);
164
165 tf.setTransform(cur_q, cur_T);
166
167 tf_t = dt;
168
169 return true;
170 }
171
172
computeTBound(const Vec3f & n) const173 FCL_REAL SplineMotion::computeTBound(const Vec3f& n) const
174 {
175 FCL_REAL Ta = TA.dot(n);
176 FCL_REAL Tb = TB.dot(n);
177 FCL_REAL Tc = TC.dot(n);
178
179 std::vector<FCL_REAL> T_potential;
180 T_potential.push_back(tf_t);
181 T_potential.push_back(1);
182 if(Tb * Tb - 3 * Ta * Tc >= 0)
183 {
184 if(Ta == 0)
185 {
186 if(Tb != 0)
187 {
188 FCL_REAL tmp = -Tc / (2 * Tb);
189 if(tmp < 1 && tmp > tf_t)
190 T_potential.push_back(tmp);
191 }
192 }
193 else
194 {
195 FCL_REAL tmp_delta = sqrt(Tb * Tb - 3 * Ta * Tc);
196 FCL_REAL tmp1 = (-Tb + tmp_delta) / (3 * Ta);
197 FCL_REAL tmp2 = (-Tb - tmp_delta) / (3 * Ta);
198 if(tmp1 < 1 && tmp1 > tf_t)
199 T_potential.push_back(tmp1);
200 if(tmp2 < 1 && tmp2 > tf_t)
201 T_potential.push_back(tmp2);
202 }
203 }
204
205 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];
206 for(unsigned int i = 1; i < T_potential.size(); ++i)
207 {
208 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];
209 if(T_bound_tmp > T_bound) T_bound = T_bound_tmp;
210 }
211
212
213 FCL_REAL cur_delta = Ta * tf_t * tf_t * tf_t + Tb * tf_t * tf_t + Tc * tf_t;
214
215 T_bound -= cur_delta;
216 T_bound /= 6.0;
217
218 return T_bound;
219 }
220
221
computeDWMax() const222 FCL_REAL SplineMotion::computeDWMax() const
223 {
224 // first compute ||w'||
225 int a00[5] = {1,-4,6,-4,1};
226 int a01[5] = {-3,10,-11,4,0};
227 int a02[5] = {3,-8,6,0,-1};
228 int a03[5] = {-1,2,-1,0,0};
229 int a11[5] = {9,-24,16,0,0};
230 int a12[5] = {-9,18,-5,-4,0};
231 int a13[5] = {3,-4,0,0,0};
232 int a22[5] = {9,-12,-2,4,1};
233 int a23[5] = {-3,2,1,0,0};
234 int a33[5] = {1,0,0,0,0};
235
236 FCL_REAL a[5];
237
238 for(int i = 0; i < 5; ++i)
239 {
240 a[i] = Rd0Rd0 * a00[i] + Rd0Rd1 * a01[i] + Rd0Rd2 * a02[i] + Rd0Rd3 * a03[i]
241 + Rd0Rd1 * a01[i] + Rd1Rd1 * a11[i] + Rd1Rd2 * a12[i] + Rd1Rd3 * a13[i]
242 + Rd0Rd2 * a02[i] + Rd1Rd2 * a12[i] + Rd2Rd2 * a22[i] + Rd2Rd3 * a23[i]
243 + Rd0Rd3 * a03[i] + Rd1Rd3 * a13[i] + Rd2Rd3 * a23[i] + Rd3Rd3 * a33[i];
244 a[i] /= 4.0;
245 }
246
247 // compute polynomial for ||w'||'
248 int da00[4] = {4,-12,12,-4};
249 int da01[4] = {-12,30,-22,4};
250 int da02[4] = {12,-24,12,0};
251 int da03[4] = {-4,6,-2,0};
252 int da11[4] = {36,-72,32,0};
253 int da12[4] = {-36,54,-10,-4};
254 int da13[4] = {12,-12,0,0};
255 int da22[4] = {36,-36,-4,4};
256 int da23[4] = {-12,6,2,0};
257 int da33[4] = {4,0,0,0};
258
259 FCL_REAL da[4];
260 for(int i = 0; i < 4; ++i)
261 {
262 da[i] = Rd0Rd0 * da00[i] + Rd0Rd1 * da01[i] + Rd0Rd2 * da02[i] + Rd0Rd3 * da03[i]
263 + Rd0Rd1 * da01[i] + Rd1Rd1 * da11[i] + Rd1Rd2 * da12[i] + Rd1Rd3 * da13[i]
264 + Rd0Rd2 * da02[i] + Rd1Rd2 * da12[i] + Rd2Rd2 * da22[i] + Rd2Rd3 * da23[i]
265 + Rd0Rd3 * da03[i] + Rd1Rd3 * da13[i] + Rd2Rd3 * da23[i] + Rd3Rd3 * da33[i];
266 da[i] /= 4.0;
267 }
268
269 FCL_REAL roots[3];
270
271 int root_num = PolySolver::solveCubic(da, roots);
272
273 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];
274 FCL_REAL dWdW_1 = a[0] + a[1] + a[2] + a[3] + a[4];
275 if(dWdW_max < dWdW_1) dWdW_max = dWdW_1;
276 for(int i = 0; i < root_num; ++i)
277 {
278 FCL_REAL v = roots[i];
279
280 if(v >= tf_t && v <= 1)
281 {
282 FCL_REAL value = a[0] * v * v * v * v + a[1] * v * v * v + a[2] * v * v + a[3] * v + a[4];
283 if(value > dWdW_max) dWdW_max = value;
284 }
285 }
286
287 return sqrt(dWdW_max);
288 }
289
getWeight0(FCL_REAL t) const290 FCL_REAL SplineMotion::getWeight0(FCL_REAL t) const
291 {
292 return (1 - 3 * t + 3 * t * t - t * t * t) / 6.0;
293 }
294
getWeight1(FCL_REAL t) const295 FCL_REAL SplineMotion::getWeight1(FCL_REAL t) const
296 {
297 return (4 - 6 * t * t + 3 * t * t * t) / 6.0;
298 }
299
getWeight2(FCL_REAL t) const300 FCL_REAL SplineMotion::getWeight2(FCL_REAL t) const
301 {
302 return (1 + 3 * t + 3 * t * t - 3 * t * t * t) / 6.0;
303 }
304
getWeight3(FCL_REAL t) const305 FCL_REAL SplineMotion::getWeight3(FCL_REAL t) const
306 {
307 return t * t * t / 6.0;
308 }
309
310
311
312
313 /// @brief Compute the motion bound for a bounding volume along a given direction n
314 /// according to mu < |v * n| + ||w x n||(r + max(||ci*||)) where ||ci*|| = ||R0(ci) x w||. w is the angular axis (normalized)
315 /// and ci are the endpoints of the generator primitives of RSS.
316 /// Notice that all bv parameters are in the local frame of the object, but n should be in the global frame (the reason is that the motion (t1, t2 and t) is in global frame)
317 template<>
visit(const ScrewMotion & motion) const318 FCL_REAL TBVMotionBoundVisitor<RSS>::visit(const ScrewMotion& motion) const
319 {
320 Transform3f tf;
321 motion.getCurrentTransform(tf);
322
323 const Vec3f& axis = motion.getAxis();
324 FCL_REAL linear_vel = motion.getLinearVelocity();
325 FCL_REAL angular_vel = motion.getAngularVelocity();
326 const Vec3f& p = motion.getAxisOrigin();
327
328 FCL_REAL c_proj_max = ((tf.getQuatRotation().transform(bv.Tr)).cross(axis)).sqrLength();
329 FCL_REAL tmp;
330 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[0] * bv.l[0])).cross(axis)).sqrLength();
331 if(tmp > c_proj_max) c_proj_max = tmp;
332 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[1] * bv.l[1])).cross(axis)).sqrLength();
333 if(tmp > c_proj_max) c_proj_max = tmp;
334 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[0] * bv.l[0] + bv.axis[1] * bv.l[1])).cross(axis)).sqrLength();
335 if(tmp > c_proj_max) c_proj_max = tmp;
336
337 c_proj_max = sqrt(c_proj_max);
338
339 FCL_REAL v_dot_n = axis.dot(n) * linear_vel;
340 FCL_REAL w_cross_n = (axis.cross(n)).length() * angular_vel;
341 FCL_REAL origin_proj = ((tf.getTranslation() - p).cross(axis)).length();
342
343 FCL_REAL mu = v_dot_n + w_cross_n * (c_proj_max + bv.r + origin_proj);
344
345 return mu;
346 }
347
visit(const ScrewMotion & motion) const348 FCL_REAL TriangleMotionBoundVisitor::visit(const ScrewMotion& motion) const
349 {
350 Transform3f tf;
351 motion.getCurrentTransform(tf);
352
353 const Vec3f& axis = motion.getAxis();
354 FCL_REAL linear_vel = motion.getLinearVelocity();
355 FCL_REAL angular_vel = motion.getAngularVelocity();
356 const Vec3f& p = motion.getAxisOrigin();
357
358 FCL_REAL proj_max = ((tf.getQuatRotation().transform(a) + tf.getTranslation() - p).cross(axis)).sqrLength();
359 FCL_REAL tmp;
360 tmp = ((tf.getQuatRotation().transform(b) + tf.getTranslation() - p).cross(axis)).sqrLength();
361 if(tmp > proj_max) proj_max = tmp;
362 tmp = ((tf.getQuatRotation().transform(c) + tf.getTranslation() - p).cross(axis)).sqrLength();
363 if(tmp > proj_max) proj_max = tmp;
364
365 proj_max = std::sqrt(proj_max);
366
367 FCL_REAL v_dot_n = axis.dot(n) * linear_vel;
368 FCL_REAL w_cross_n = (axis.cross(n)).length() * angular_vel;
369 FCL_REAL mu = v_dot_n + w_cross_n * proj_max;
370
371 return mu;
372 }
373
374
375
376
377
378 /// @brief Compute the motion bound for a bounding volume along a given direction n
379 /// according to mu < |v * n| + ||w x n||(r + max(||ci*||)) where ||ci*|| = ||R0(ci) x w||. w is the angular axis (normalized)
380 /// and ci are the endpoints of the generator primitives of RSS.
381 /// Notice that all bv parameters are in the local frame of the object, but n should be in the global frame (the reason is that the motion (t1, t2 and t) is in global frame)
382 template<>
visit(const InterpMotion & motion) const383 FCL_REAL TBVMotionBoundVisitor<RSS>::visit(const InterpMotion& motion) const
384 {
385 Transform3f tf;
386 motion.getCurrentTransform(tf);
387
388 const Vec3f& reference_p = motion.getReferencePoint();
389 const Vec3f& angular_axis = motion.getAngularAxis();
390 FCL_REAL angular_vel = motion.getAngularVelocity();
391 const Vec3f& linear_vel = motion.getLinearVelocity();
392
393 FCL_REAL c_proj_max = ((tf.getQuatRotation().transform(bv.Tr - reference_p)).cross(angular_axis)).sqrLength();
394 FCL_REAL tmp;
395 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[0] * bv.l[0] - reference_p)).cross(angular_axis)).sqrLength();
396 if(tmp > c_proj_max) c_proj_max = tmp;
397 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[1] * bv.l[1] - reference_p)).cross(angular_axis)).sqrLength();
398 if(tmp > c_proj_max) c_proj_max = tmp;
399 tmp = ((tf.getQuatRotation().transform(bv.Tr + bv.axis[0] * bv.l[0] + bv.axis[1] * bv.l[1] - reference_p)).cross(angular_axis)).sqrLength();
400 if(tmp > c_proj_max) c_proj_max = tmp;
401
402 c_proj_max = std::sqrt(c_proj_max);
403
404 FCL_REAL v_dot_n = linear_vel.dot(n);
405 FCL_REAL w_cross_n = (angular_axis.cross(n)).length() * angular_vel;
406 FCL_REAL mu = v_dot_n + w_cross_n * (bv.r + c_proj_max);
407
408 return mu;
409 }
410
411 /// @brief Compute the motion bound for a triangle along a given direction n
412 /// according to mu < |v * n| + ||w x n||(max||ci*||) where ||ci*|| = ||R0(ci) x w|| / \|w\|. w is the angular velocity
413 /// and ci are the triangle vertex coordinates.
414 /// Notice that the triangle is in the local frame of the object, but n should be in the global frame (the reason is that the motion (t1, t2 and t) is in global frame)
visit(const InterpMotion & motion) const415 FCL_REAL TriangleMotionBoundVisitor::visit(const InterpMotion& motion) const
416 {
417 Transform3f tf;
418 motion.getCurrentTransform(tf);
419
420 const Vec3f& reference_p = motion.getReferencePoint();
421 const Vec3f& angular_axis = motion.getAngularAxis();
422 FCL_REAL angular_vel = motion.getAngularVelocity();
423 const Vec3f& linear_vel = motion.getLinearVelocity();
424
425 FCL_REAL proj_max = ((tf.getQuatRotation().transform(a - reference_p)).cross(angular_axis)).sqrLength();
426 FCL_REAL tmp;
427 tmp = ((tf.getQuatRotation().transform(b - reference_p)).cross(angular_axis)).sqrLength();
428 if(tmp > proj_max) proj_max = tmp;
429 tmp = ((tf.getQuatRotation().transform(c - reference_p)).cross(angular_axis)).sqrLength();
430 if(tmp > proj_max) proj_max = tmp;
431
432 proj_max = std::sqrt(proj_max);
433
434 FCL_REAL v_dot_n = linear_vel.dot(n);
435 FCL_REAL w_cross_n = (angular_axis.cross(n)).length() * angular_vel;
436 FCL_REAL mu = v_dot_n + w_cross_n * proj_max;
437
438 return mu;
439 }
440
InterpMotion()441 InterpMotion::InterpMotion() : MotionBase()
442 {
443 // Default angular velocity is zero
444 angular_axis.setValue(1, 0, 0);
445 angular_vel = 0;
446
447 // Default reference point is local zero point
448
449 // Default linear velocity is zero
450 }
451
InterpMotion(const Matrix3f & R1,const Vec3f & T1,const Matrix3f & R2,const Vec3f & T2)452 InterpMotion::InterpMotion(const Matrix3f& R1, const Vec3f& T1,
453 const Matrix3f& R2, const Vec3f& T2) : MotionBase(),
454 tf1(R1, T1),
455 tf2(R2, T2),
456 tf(tf1)
457 {
458 // Compute the velocities for the motion
459 computeVelocity();
460 }
461
462
InterpMotion(const Transform3f & tf1_,const Transform3f & tf2_)463 InterpMotion::InterpMotion(const Transform3f& tf1_, const Transform3f& tf2_) : MotionBase(),
464 tf1(tf1_),
465 tf2(tf2_),
466 tf(tf1)
467 {
468 // Compute the velocities for the motion
469 computeVelocity();
470 }
471
InterpMotion(const Matrix3f & R1,const Vec3f & T1,const Matrix3f & R2,const Vec3f & T2,const Vec3f & O)472 InterpMotion::InterpMotion(const Matrix3f& R1, const Vec3f& T1,
473 const Matrix3f& R2, const Vec3f& T2,
474 const Vec3f& O) : MotionBase(),
475 tf1(R1, T1),
476 tf2(R2, T2),
477 tf(tf1),
478 reference_p(O)
479 {
480 // Compute the velocities for the motion
481 computeVelocity();
482 }
483
InterpMotion(const Transform3f & tf1_,const Transform3f & tf2_,const Vec3f & O)484 InterpMotion::InterpMotion(const Transform3f& tf1_, const Transform3f& tf2_, const Vec3f& O) : MotionBase(),
485 tf1(tf1_),
486 tf2(tf2_),
487 tf(tf1),
488 reference_p(O)
489 {
490 }
491
integrate(double dt) const492 bool InterpMotion::integrate(double dt) const
493 {
494 if(dt > 1) dt = 1;
495
496 tf.setQuatRotation(absoluteRotation(dt));
497 tf.setTranslation(linear_vel * dt + tf1.transform(reference_p) - tf.getQuatRotation().transform(reference_p));
498
499 return true;
500 }
501
502
computeVelocity()503 void InterpMotion::computeVelocity()
504 {
505 linear_vel = tf2.transform(reference_p) - tf1.transform(reference_p);
506 Quaternion3f deltaq = tf2.getQuatRotation() * inverse(tf1.getQuatRotation());
507 deltaq.toAxisAngle(angular_axis, angular_vel);
508 if(angular_vel < 0)
509 {
510 angular_vel = -angular_vel;
511 angular_axis = -angular_axis;
512 }
513 }
514
515
deltaRotation(FCL_REAL dt) const516 Quaternion3f InterpMotion::deltaRotation(FCL_REAL dt) const
517 {
518 Quaternion3f res;
519 res.fromAxisAngle(angular_axis, (FCL_REAL)(dt * angular_vel));
520 return res;
521 }
522
absoluteRotation(FCL_REAL dt) const523 Quaternion3f InterpMotion::absoluteRotation(FCL_REAL dt) const
524 {
525 Quaternion3f delta_t = deltaRotation(dt);
526 return delta_t * tf1.getQuatRotation();
527 }
528
529
530 /// @brief Compute the motion bound for a bounding volume along a given direction n
531 template<>
visit(const TranslationMotion & motion) const532 FCL_REAL TBVMotionBoundVisitor<RSS>::visit(const TranslationMotion& motion) const
533 {
534 return motion.getVelocity().dot(n);
535 }
536
537 /// @brief Compute the motion bound for a triangle along a given direction n
visit(const TranslationMotion & motion) const538 FCL_REAL TriangleMotionBoundVisitor::visit(const TranslationMotion& motion) const
539 {
540 return motion.getVelocity().dot(n);
541 }
542
543 template class TBVMotionBoundVisitor<RSS>;
544
545 }
546