From 1711279068bdd4d3732170919d2952a204bb7ef5 Mon Sep 17 00:00:00 2001
From: jpan <jpan@253336fb-580f-4252-a368-f3cef5a2a82b>
Date: Wed, 28 Sep 2011 06:20:10 +0000
Subject: [PATCH] This line, and those below, will be ignored--

M    fcl/test/test_core_utility.h
M    fcl/test/test_core_distance.cpp
M    fcl/test/test_core_continuous_collision.cpp
M    fcl/include/fcl/traversal_node_bvhs.h
M    fcl/include/fcl/motion_base.h
M    fcl/include/fcl/simple_setup.h
M    fcl/include/fcl/motion.h
M    fcl/include/fcl/transform.h
M    fcl/manifest.xml
M    fcl/src/motion.cpp
M    fcl/src/traversal_node_bvhs.cpp
M    fcl/CMakeLists.txt


git-svn-id: https://kforge.ros.org/fcl/fcl_ros@35 253336fb-580f-4252-a368-f3cef5a2a82b
---
 trunk/fcl/CMakeLists.txt                      | 10 ++-
 trunk/fcl/include/fcl/motion.h                | 57 ++++++++++------
 trunk/fcl/include/fcl/motion_base.h           |  2 +-
 trunk/fcl/include/fcl/simple_setup.h          |  6 --
 trunk/fcl/include/fcl/transform.h             |  2 +-
 trunk/fcl/include/fcl/traversal_node_bvhs.h   | 43 ++++++------
 trunk/fcl/manifest.xml                        |  1 +
 trunk/fcl/src/motion.cpp                      |  8 +--
 trunk/fcl/src/traversal_node_bvhs.cpp         | 48 +++++++-------
 .../test/test_core_continuous_collision.cpp   | 61 ++++++++++++++++-
 trunk/fcl/test/test_core_distance.cpp         | 65 +++++++++++++++++++
 trunk/fcl/test/test_core_utility.h            |  1 +
 12 files changed, 221 insertions(+), 83 deletions(-)

diff --git a/trunk/fcl/CMakeLists.txt b/trunk/fcl/CMakeLists.txt
index 5fae2c40..67bff808 100644
--- a/trunk/fcl/CMakeLists.txt
+++ b/trunk/fcl/CMakeLists.txt
@@ -32,7 +32,7 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
 add_definitions(-DUSE_PQP=0)
 add_definitions(-DUSE_SVMLIGHT=0)
 
-rosbuild_add_library(${PROJECT_NAME} src/AABB.cpp src/OBB.cpp src/RSS.cpp src/vec_3f.cpp src/traversal_node_base.cpp src/traversal_node_bvhs.cpp src/intersect.cpp src/motion.cpp src/BV_fitter.cpp src/BV_splitter.cpp src/BVH_model.cpp src/BVH_utility.cpp src/transform.cpp src/simple_setup.cpp src/geometric_shapes.cpp src/geometric_shapes_utility.cpp src/geometric_shapes_intersect.cpp src/collision_node.cpp src/traversal_recurse.cpp src/broad_phase_collision.cpp src/collision.cpp src/collision_func_matrix.cpp src/interval_tree.cpp)
+rosbuild_add_library(${PROJECT_NAME} src/AABB.cpp src/OBB.cpp src/RSS.cpp src/vec_3f.cpp src/traversal_node_base.cpp src/traversal_node_bvhs.cpp src/intersect.cpp src/motion.cpp src/BV_fitter.cpp src/BV_splitter.cpp src/BVH_model.cpp src/BVH_utility.cpp src/transform.cpp src/simple_setup.cpp src/geometric_shapes.cpp src/geometric_shapes_utility.cpp src/geometric_shapes_intersect.cpp src/collision_node.cpp src/traversal_recurse.cpp src/broad_phase_collision.cpp src/collision.cpp src/collision_func_matrix.cpp src/interval_tree.cpp src/conservative_advancement.cpp)
 
 rosbuild_add_gtest(test_core_collision test/test_core_collision.cpp)
 target_link_libraries(test_core_collision fcl)
@@ -56,4 +56,10 @@ rosbuild_add_gtest(test_core_front_list test/test_core_front_list.cpp)
 target_link_libraries(test_core_front_list fcl)
 
 rosbuild_add_gtest(test_core_continuous_collision test/test_core_continuous_collision.cpp)
-target_link_libraries(test_core_continuous_collision fcl)
\ No newline at end of file
+target_link_libraries(test_core_continuous_collision fcl)
+
+rosbuild_add_executable(test_core_deformable_object test/test_core_deformable_object.cpp)
+target_link_libraries(test_core_deformable_object fcl)
+
+rosbuild_add_executable(test_core_conservative_advancement test/test_core_conservative_advancement.cpp)
+target_link_libraries(test_core_conservative_advancement fcl)
\ No newline at end of file
diff --git a/trunk/fcl/include/fcl/motion.h b/trunk/fcl/include/fcl/motion.h
index fb0e2790..c457ab5a 100644
--- a/trunk/fcl/include/fcl/motion.h
+++ b/trunk/fcl/include/fcl/motion.h
@@ -48,6 +48,10 @@ namespace fcl
 
 /** \brief Linear interpolation motion
  * Each Motion is assumed to have constant linear velocity and angular velocity
+ * The motion is R(t)(p - p_ref) + p_ref + T(t)
+ * Therefore, R(0) = R0, R(1) = R1
+ *            T(0) = T0 + R0 p_ref - p_ref
+ *            T(1) = T1 + R1 p_ref - p_ref
  */
 template<typename BV>
 class InterpMotion : public MotionBase<BV>
@@ -60,6 +64,8 @@ public:
     angular_axis = Vec3f(1, 0, 0);
     angular_vel = 0;
 
+    /** Default reference point is local zero point */
+
     /** Default linear velocity is zero */
   }
 
@@ -73,6 +79,8 @@ public:
     /** Current time is zero, so the transformation is t1 */
     t = t1;
 
+    /** Default reference point is local zero point */
+
     /** Compute the velocities for the motion */
     computeVelocity();
   }
@@ -87,6 +95,8 @@ public:
     t2 = SimpleTransform(R2, T2 - matMulVec(R2, O));
     t = t1;
 
+    reference_p = O;
+
     /** Compute the velocities for the motion */
     computeVelocity();
   }
@@ -99,33 +109,29 @@ public:
   {
     if(dt > 1) dt = 1;
 
-    t.T = t1.T + linear_vel * dt;
-
-    t.q = absoluteRotation(dt);
-    t.q.toRotation(t.R);
+    t.setQuatRotation(absoluteRotation(dt));
+    t.setTranslation(linear_vel * dt + t1.transform(reference_p) - t.getQuatRotation().transform(reference_p));
 
     return true;
   }
 
-  /** \brief Compute the motion bound for a bounding volume, given the closest direction n between two query objects
-   * according to mu < |v * n| + ||w x n||(r + max(||ci*||)) where ||ci*|| = ||ci x w||. w is the angular axis (normalized)
-   * and ci are the endpoints of the generator primitives of RSS.
-   * 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)
+  /** \brief Compute the motion bound for a bounding volume along a given direction n
+   * For general BV, not implemented so return trivial 0
    */
   BVH_REAL computeMotionBound(const BV& bv, const Vec3f& n) const { return 0.0; }
 
-  /** \brief Compute the motion bound for a triangle, given the closest direction n between two query objects
-   * according to mu < |v * | + ||w x n||(max||ci*||) where ||ci*|| = ||ci x w||. w is the angular axis (normalized)
+  /** \brief Compute the motion bound for a triangle along a given direction n
+   * according to mu < |v * n| + ||w x n||(max||ci*||) where ||ci*|| = ||ci x w||. w is the angular axis (normalized)
    * and ci are the triangle vertex coordinates.
    * 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)
    */
   BVH_REAL computeMotionBound(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& n) const
   {
-    BVH_REAL c_proj_max = (a.cross(angular_axis)).sqrLength();
+    BVH_REAL c_proj_max = ((a - reference_p).cross(angular_axis)).sqrLength();
     BVH_REAL tmp;
-    tmp = (b.cross(angular_axis)).sqrLength();
+    tmp = ((b - reference_p).cross(angular_axis)).sqrLength();
     if(tmp > c_proj_max) c_proj_max = tmp;
-    tmp = (c.cross(angular_axis)).sqrLength();
+    tmp = ((c - reference_p).cross(angular_axis)).sqrLength();
     if(tmp > c_proj_max) c_proj_max = tmp;
 
     c_proj_max = sqrt(c_proj_max);
@@ -138,33 +144,33 @@ public:
   }
 
   /** \brief Get the rotation and translation in current step */
-  void getCurrentTransformation(Vec3f R[3], Vec3f& T) const
+  void getCurrentTransform(Vec3f R[3], Vec3f& T) const
   {
     for(int i = 0; i < 3; ++i)
     {
-      R[i] = t.R[i];
+      R[i] = t.getRotation()[i];
     }
 
-    T = t.T;
+    T = t.getTranslation();
   }
 
   void getCurrentRotation(Vec3f R[3]) const
   {
     for(int i = 0; i < 3; ++i)
-      R[i] = t.R[i];
+      R[i] = t.getRotation()[i];
   }
 
   void getCurrentTranslation(Vec3f& T) const
   {
-    T = t.T;
+    T = t.getTranslation();
   }
 
 protected:
 
   void computeVelocity()
   {
-    linear_vel = t2.T - t1.T;
-    SimpleQuaternion deltaq = t2.q * t1.q.inverse();
+    linear_vel = t2.transform(reference_p) - t1.transform(reference_p);
+    SimpleQuaternion deltaq = t2.getQuatRotation() * t1.getQuatRotation().inverse();
     deltaq.toAxisAngle(angular_axis, angular_vel);
   }
 
@@ -179,7 +185,7 @@ protected:
   SimpleQuaternion absoluteRotation(BVH_REAL t) const
   {
     SimpleQuaternion delta_t = deltaRotation(t);
-    return delta_t * t1.q;
+    return delta_t * t1.getQuatRotation();
   }
 
   /** \brief The transformation at time 0 */
@@ -199,8 +205,17 @@ protected:
 
   /** \brief Angular velocity axis */
   Vec3f angular_axis;
+
+  /** \brief Reference point for the motion (in the object's local frame) */
+  Vec3f reference_p;
 };
 
+
+/** \brief Compute the motion bound for a bounding volume along a given direction n
+ * according to mu < |v * n| + ||w x n||(r + max(||ci*||)) where ||ci*|| = ||ci x w||. w is the angular axis (normalized)
+ * and ci are the endpoints of the generator primitives of RSS.
+ * 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)
+ */
 template<>
 BVH_REAL InterpMotion<RSS>::computeMotionBound(const RSS& bv, const Vec3f& n) const;
 
diff --git a/trunk/fcl/include/fcl/motion_base.h b/trunk/fcl/include/fcl/motion_base.h
index 0771dbd5..005a3d74 100644
--- a/trunk/fcl/include/fcl/motion_base.h
+++ b/trunk/fcl/include/fcl/motion_base.h
@@ -59,7 +59,7 @@ public:
   virtual BVH_REAL computeMotionBound(const Vec3f& a, const Vec3f& b, const Vec3f& c, const Vec3f& n) const = 0;
 
   /** \brief Get the rotation and translation in current step */
-  virtual void getCurrentTransformation(Vec3f R[3], Vec3f& T) const = 0;
+  virtual void getCurrentTransform(Vec3f R[3], Vec3f& T) const = 0;
 
   virtual void getCurrentRotation(Vec3f R[3]) const = 0;
 
diff --git a/trunk/fcl/include/fcl/simple_setup.h b/trunk/fcl/include/fcl/simple_setup.h
index f08bf14b..6ac27527 100644
--- a/trunk/fcl/include/fcl/simple_setup.h
+++ b/trunk/fcl/include/fcl/simple_setup.h
@@ -616,10 +616,6 @@ bool initialize(MeshConservativeAdvancementTraversalNode<BV>& node, BVHModel<BV>
 
   node.w = w;
 
-  //HOW?
-  //node.motion1 = new InterpMotion<BV>
-  //node.motion2 = new InterpMotion<BV>
-
   return true;
 }
 
@@ -644,8 +640,6 @@ inline bool initialize(MeshConservativeAdvancementTraversalNodeRSS& node, const
 
   relativeTransform(R1, T1, R2, T2, node.R, node.T);
 
-
-
   return true;
 }
 
diff --git a/trunk/fcl/include/fcl/transform.h b/trunk/fcl/include/fcl/transform.h
index c4f307fc..2db81c9f 100644
--- a/trunk/fcl/include/fcl/transform.h
+++ b/trunk/fcl/include/fcl/transform.h
@@ -207,7 +207,7 @@ public:
 
   bool isIdentity() const
   {
-    return (R[0][0] == 1) && (R[0][1] == 0) && (R[0][2] == 0) && (R[1][0] == 0) && (R[1][1] == 1) && (R[1][2] == 1) && (R[2][0] == 0) && (R[2][1] == 0) && (R[2][2] == 1)
+    return (R[0][0] == 1) && (R[0][1] == 0) && (R[0][2] == 0) && (R[1][0] == 0) && (R[1][1] == 1) && (R[1][2] == 0) && (R[2][0] == 0) && (R[2][1] == 0) && (R[2][2] == 1)
         && (T[0] == 0) && (T[1] == 0) && (T[2] == 0);
   }
 
diff --git a/trunk/fcl/include/fcl/traversal_node_bvhs.h b/trunk/fcl/include/fcl/traversal_node_bvhs.h
index 9ab9265c..fa1f4d2b 100644
--- a/trunk/fcl/include/fcl/traversal_node_bvhs.h
+++ b/trunk/fcl/include/fcl/traversal_node_bvhs.h
@@ -1038,6 +1038,19 @@ public:
   Vec3f T;
 };
 
+
+
+struct ConservativeAdvancementStackData
+{
+  ConservativeAdvancementStackData(const Vec3f& P1_, const Vec3f& P2_, int c1_, int c2_, BVH_REAL d_) : P1(P1_), P2(P2_), c1(c1_), c2(c2_), d(d_) {}
+
+  Vec3f P1;
+  Vec3f P2;
+  int c1;
+  int c2;
+  BVH_REAL d;
+};
+
 // when using this default version, must refit the BVH in current configuration (R_t, T_t) into default configuration
 template<typename BV>
 class MeshConservativeAdvancementTraversalNode : public MeshDistanceTraversalNode<BV>
@@ -1061,7 +1074,7 @@ public:
     Vec3f P1, P2;
     BVH_REAL d = this->model1->getBV(b1).distance(this->model2->getBV(b2), &P1, &P2);
 
-    stack.push_back(StackData(P1, P2, b1, b2, d));
+    stack.push_back(ConservativeAdvancementStackData(P1, P2, b1, b2, d));
 
     return d;
   }
@@ -1105,11 +1118,9 @@ public:
     }
 
 
-    /** n is the local frame of object 1 */
+    // n is the local frame of object 1
     Vec3f n = P2 - P1;
-    /** turn n into the global frame
-     * nothing is done here because in this case we assume the body is in original configuration (I, 0)
-     */
+    // here n is already in global frame as we assume the body is in original configuration (I, 0) for general BVH
     BVH_REAL bound1 = motion1->computeMotionBound(p1, p2, p3, n);
     BVH_REAL bound2 = motion2->computeMotionBound(q1, q2, q3, n);
 
@@ -1124,14 +1135,14 @@ public:
   {
     if((c >= w * (this->min_distance - this->abs_err)) && (c * (1 + this->rel_err) >= w * this->min_distance))
     {
-      const StackData& data = stack.back();
+      const ConservativeAdvancementStackData& data = stack.back();
       BVH_REAL d = data.d;
       Vec3f n;
       int c1, c2;
 
       if(d > c)
       {
-        const StackData& data2 = stack[stack.size() - 2];
+        const ConservativeAdvancementStackData& data2 = stack[stack.size() - 2];
         d = data2.d;
         n = data2.P2 - data2.P1;
         c1 = data2.c1;
@@ -1147,9 +1158,6 @@ public:
 
       if(c != d) std::cout << "there is some problem here" << std::endl;
 
-
-      // (this->tree1 + c1)->bv.axis[0] * n[0] + (this->tree1 + c1)->bv.axis[1] * n[1] + (this->tree1 + c1)->bv.axis[2] * n[2];
-
       BVH_REAL bound1 = motion1->computeMotionBound((this->tree1 + c1)->bv, n);
       BVH_REAL bound2 = motion2->computeMotionBound((this->tree2 + c2)->bv, n);
 
@@ -1163,7 +1171,7 @@ public:
     }
     else
     {
-      const StackData& data = stack.back();
+      const ConservativeAdvancementStackData& data = stack.back();
       BVH_REAL d = data.d;
 
       if(d > c)
@@ -1190,18 +1198,7 @@ public:
   MotionBase<BV>* motion1;
   MotionBase<BV>* motion2;
 
-  struct StackData
-  {
-    StackData(const Vec3f& P1_, const Vec3f& P2_, int c1_, int c2_, BVH_REAL d_) : P1(P1_), P2(P2_), c1(c1_), c2(c2_), d(d_) {}
-
-    Vec3f P1;
-    Vec3f P2;
-    int c1;
-    int c2;
-    BVH_REAL d;
-  };
-
-  mutable std::vector<StackData> stack;
+  mutable std::vector<ConservativeAdvancementStackData> stack;
 };
 
 
diff --git a/trunk/fcl/manifest.xml b/trunk/fcl/manifest.xml
index 370fb5d3..8d4c2ba2 100644
--- a/trunk/fcl/manifest.xml
+++ b/trunk/fcl/manifest.xml
@@ -10,6 +10,7 @@
   <url>http://ros.org/wiki/fcl</url>
   <depend package="libccd"/>
   <depend package="ann"/>
+  <depend package="assimp"/>
   <!-- <depend package="PQP"/> -->
   <!-- <depend package="svm_light"/> -->
   <export>
diff --git a/trunk/fcl/src/motion.cpp b/trunk/fcl/src/motion.cpp
index 3f2c9568..cc20b258 100644
--- a/trunk/fcl/src/motion.cpp
+++ b/trunk/fcl/src/motion.cpp
@@ -43,13 +43,13 @@ namespace fcl
 template<>
 BVH_REAL InterpMotion<RSS>::computeMotionBound(const RSS& bv, const Vec3f& n) const
 {
-  BVH_REAL c_proj_max = (bv.Tr.cross(angular_axis)).sqrLength();
+  BVH_REAL c_proj_max = ((bv.Tr - reference_p).cross(angular_axis)).sqrLength();
   BVH_REAL tmp;
-  tmp = ((bv.Tr + bv.axis[0] * bv.l[0]).cross(angular_axis)).sqrLength();
+  tmp = ((bv.Tr + bv.axis[0] * bv.l[0] - reference_p).cross(angular_axis)).sqrLength();
   if(tmp > c_proj_max) c_proj_max = tmp;
-  tmp = ((bv.Tr + bv.axis[1] * bv.l[1]).cross(angular_axis)).sqrLength();
+  tmp = ((bv.Tr + bv.axis[1] * bv.l[1] - reference_p).cross(angular_axis)).sqrLength();
   if(tmp > c_proj_max) c_proj_max = tmp;
-  tmp = ((bv.Tr + bv.axis[0] * bv.l[0] + bv.axis[1] * bv.l[1]).cross(angular_axis)).sqrLength();
+  tmp = ((bv.Tr + bv.axis[0] * bv.l[0] + bv.axis[1] * bv.l[1] - reference_p).cross(angular_axis)).sqrLength();
   if(tmp > c_proj_max) c_proj_max = tmp;
 
   c_proj_max = sqrt(c_proj_max);
diff --git a/trunk/fcl/src/traversal_node_bvhs.cpp b/trunk/fcl/src/traversal_node_bvhs.cpp
index 8fb13f5f..0abc9322 100644
--- a/trunk/fcl/src/traversal_node_bvhs.cpp
+++ b/trunk/fcl/src/traversal_node_bvhs.cpp
@@ -393,14 +393,14 @@ bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(BVH_REAL c) const
 {
   if((c >= w * (this->min_distance - this->abs_err)) && (c * (1 + this->rel_err) >= w * this->min_distance))
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
     Vec3f n;
     int c1, c2;
 
     if(d > c)
     {
-      const StackData& data2 = stack[stack.size() - 2];
+      const ConservativeAdvancementStackData& data2 = stack[stack.size() - 2];
       d = data2.d;
       n = data2.P2 - data2.P1;
       c1 = data2.c1;
@@ -431,7 +431,7 @@ bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(BVH_REAL c) const
   }
   else
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
 
     if(d > c)
@@ -448,14 +448,14 @@ bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(BVH_REAL c) const
 {
   if((c >= w * (this->min_distance - this->abs_err)) && (c * (1 + this->rel_err) >= w * this->min_distance))
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
     Vec3f n;
     int c1, c2;
 
     if(d > c)
     {
-      const StackData& data2 = stack[stack.size() - 2];
+      const ConservativeAdvancementStackData& data2 = stack[stack.size() - 2];
       d = data2.d;
       n = data2.P2 - data2.P1;
       c1 = data2.c1;
@@ -486,7 +486,7 @@ bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(BVH_REAL c) const
   }
   else
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
 
     if(d > c)
@@ -514,7 +514,7 @@ BVH_REAL MeshConservativeAdvancementTraversalNodeRSS::BVTesting(int b1, int b2)
   Vec3f P1, P2;
   BVH_REAL d = distance(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv, &P1, &P2);
 
-  stack.push_back(StackData(P1, P2, b1, b2, d));
+  stack.push_back(ConservativeAdvancementStackData(P1, P2, b1, b2, d));
 
   return d;
 }
@@ -560,17 +560,20 @@ void MeshConservativeAdvancementTraversalNodeRSS::leafTesting(int b1, int b2) co
   }
 
 
-  /** n is the local frame of object 1 */
+  /** n is the local frame of object 1, pointing from object 1 to object2 */
   Vec3f n = P2 - P1;
-  /** turn n into the global frame */
-  Vec3f R[3];
-  motion1->getCurrentRotation(R);
-  Vec3f n_transformed = matMulVec(R, n);
+  /** turn n into the global frame, pointing from object 1 to object 2 */
+  Vec3f R0[3];
+  motion1->getCurrentRotation(R0);
+  Vec3f n_transformed = matMulVec(R0, n);
   n_transformed.normalize();
   BVH_REAL bound1 = motion1->computeMotionBound(t11, t12, t13, n_transformed);
-  BVH_REAL bound2 = motion2->computeMotionBound(t21, t22, t23, n_transformed);
+  BVH_REAL bound2 = motion2->computeMotionBound(t21, t22, t23, -n_transformed);
 
-  BVH_REAL cur_delta_t = d / (bound1 + bound2);
+  BVH_REAL bound = bound1 + bound2;
+  if(bound < d) bound = d;
+
+  BVH_REAL cur_delta_t = d / bound;
 
   if(cur_delta_t < delta_t)
     delta_t = cur_delta_t;
@@ -580,14 +583,14 @@ bool MeshConservativeAdvancementTraversalNodeRSS::canStop(BVH_REAL c) const
 {
   if((c >= w * (min_distance - abs_err)) && (c * (1 + rel_err) >= w * min_distance))
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
     Vec3f n;
     int c1, c2;
 
     if(d > c)
     {
-      const StackData& data2 = stack[stack.size() - 2];
+      const ConservativeAdvancementStackData& data2 = stack[stack.size() - 2];
       d = data2.d;
       n = data2.P2 - data2.P1;
       c1 = data2.c1;
@@ -603,16 +606,15 @@ bool MeshConservativeAdvancementTraversalNodeRSS::canStop(BVH_REAL c) const
 
     if(c != d) std::cout << "there is some problem here" << std::endl;
 
-    /** n is in local frame of RSS c1 */
-    /** turn n into the global frame */
+    // n is in local frame of RSS c1, so we need to turn n into the global frame
     Vec3f n_transformed = model1->getBV(c1).bv.axis[0] * n[0] + model1->getBV(c1).bv.axis[1] * n[2] + model1->getBV(c1).bv.axis[2] * n[2];
-    Vec3f R[3];
-    motion1->getCurrentRotation(R);
-    n_transformed = matMulVec(R, n_transformed);
+    Vec3f R0[3];
+    motion1->getCurrentRotation(R0);
+    n_transformed = matMulVec(R0, n_transformed);
     n_transformed.normalize();
 
     BVH_REAL bound1 = motion1->computeMotionBound(model1->getBV(c1).bv, n_transformed);
-    BVH_REAL bound2 = motion2->computeMotionBound(model2->getBV(c2).bv, n_transformed);
+    BVH_REAL bound2 = motion2->computeMotionBound(model2->getBV(c2).bv, -n_transformed);
 
     BVH_REAL cur_delta_t = c / (bound1 + bound2);
     if(cur_delta_t < delta_t)
@@ -624,7 +626,7 @@ bool MeshConservativeAdvancementTraversalNodeRSS::canStop(BVH_REAL c) const
   }
   else
   {
-    const StackData& data = stack.back();
+    const ConservativeAdvancementStackData& data = stack.back();
     BVH_REAL d = data.d;
 
     if(d > c)
diff --git a/trunk/fcl/test/test_core_continuous_collision.cpp b/trunk/fcl/test/test_core_continuous_collision.cpp
index 8fd1bd53..e8f536d7 100644
--- a/trunk/fcl/test/test_core_continuous_collision.cpp
+++ b/trunk/fcl/test/test_core_continuous_collision.cpp
@@ -39,6 +39,7 @@
 #include "fcl/simple_setup.h"
 #include "test_core_utility.h"
 #include <gtest/gtest.h>
+#include <boost/timer.hpp>
 
 using namespace fcl;
 
@@ -62,8 +63,13 @@ bool exhaustive = true;
 bool enable_contact = true;
 unsigned int n_dcd_samples = 10;
 
-TEST(ccd_test, mesh_mesh)
+
+
+TEST(ccd_test, mesh_mesh_bottomup)
 {
+  double t_ccd = 0;
+  double t_dcd = 0;
+
   std::vector<Vec3f> p1, p2;
   std::vector<Triangle> t1, t2;
   loadOBJFile("test/env.obj", p1, t1);
@@ -73,7 +79,7 @@ TEST(ccd_test, mesh_mesh)
   std::vector<Transform> transforms2; // t1
   BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000};
   BVH_REAL delta_trans[] = {10, 10, 10};
-  int n = 1000;
+  int n = 100;
   bool verbose = false;
 
   generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n);
@@ -82,8 +88,13 @@ TEST(ccd_test, mesh_mesh)
 
   for(unsigned int i = 0; i < transforms.size(); ++i)
   {
+    boost::timer timer1;
     res = discrete_continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, verbose);
+    t_dcd += timer1.elapsed();
+
+    boost::timer timer2;
     res2 = continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, true, verbose);
+    t_ccd += timer2.elapsed();
     if(res)
       ASSERT_TRUE(res == res2);
     else
@@ -93,8 +104,54 @@ TEST(ccd_test, mesh_mesh)
     }
   }
 
+  std::cout << "dcd timing: " << t_dcd << " sec" << std::endl;
+  std::cout << "ccd timing: " << t_ccd << " sec" << std::endl;
 }
 
+
+TEST(ccd_test, mesh_mesh_topdown)
+{
+  double t_ccd = 0;
+  double t_dcd = 0;
+
+  std::vector<Vec3f> p1, p2;
+  std::vector<Triangle> t1, t2;
+  loadOBJFile("test/env.obj", p1, t1);
+  loadOBJFile("test/rob.obj", p2, t2);
+
+  std::vector<Transform> transforms; // t0
+  std::vector<Transform> transforms2; // t1
+  BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000};
+  BVH_REAL delta_trans[] = {10, 10, 10};
+  int n = 100;
+  bool verbose = false;
+
+  generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n);
+
+  bool res, res2;
+
+  for(unsigned int i = 0; i < transforms.size(); ++i)
+  {
+    boost::timer timer1;
+    res = discrete_continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, verbose);
+    t_dcd += timer1.elapsed();
+
+    boost::timer timer2;
+    res2 = continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose);
+    t_ccd += timer2.elapsed();
+    if(res)
+      ASSERT_TRUE(res == res2);
+    else
+    {
+      if(res2)
+        std::cout << "CCD detects collision missed in DCD" << std::endl;
+    }
+  }
+  std::cout << "dcd timing: " << t_dcd << " sec" << std::endl;
+  std::cout << "ccd timing: " << t_ccd << " sec" << std::endl;
+}
+
+
 int main(int argc, char **argv)
 {
   testing::InitGoogleTest(&argc, argv);
diff --git a/trunk/fcl/test/test_core_distance.cpp b/trunk/fcl/test/test_core_distance.cpp
index a63898fb..add5b593 100644
--- a/trunk/fcl/test/test_core_distance.cpp
+++ b/trunk/fcl/test/test_core_distance.cpp
@@ -40,6 +40,7 @@
 #include "fcl/simple_setup.h"
 #include "test_core_utility.h"
 #include <gtest/gtest.h>
+#include <boost/timer.hpp>
 
 
 #if USE_PQP
@@ -64,6 +65,11 @@ void distance_Test2(const Transform& tf,
                     DistanceRes& distance_result,
                     bool verbose = true);
 
+bool collide_Test_OBB(const Transform& tf,
+                      const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1,
+                      const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose);
+
+
 bool verbose = false;
 BVH_REAL DELTA = 0.001;
 
@@ -92,9 +98,16 @@ TEST(collision_core, mesh_distance)
 
   generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n);
 
+  double dis_time = 0;
+  double col_time = 0;
+
   DistanceRes res, res_now;
   for(unsigned int i = 0; i < transforms.size(); ++i)
   {
+    boost::timer timer_col;
+    collide_Test_OBB(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose);
+    col_time += timer_col.elapsed();
+
 #if USE_PQP
     distance_PQP(transforms[i], p1, t1, p2, t2, res, verbose);
 
@@ -104,6 +117,7 @@ TEST(collision_core, mesh_distance)
     ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2)));
 #endif
 
+    boost::timer timer_dist;
 #if USE_PQP
     distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 2, res_now, verbose);
     ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA);
@@ -111,6 +125,7 @@ TEST(collision_core, mesh_distance)
 #else
     distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 2, res, verbose);
 #endif
+    dis_time += timer_dist.elapsed();
 
     distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, 2, res_now, verbose);
 
@@ -167,11 +182,16 @@ TEST(collision_core, mesh_distance)
     ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA);
     ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2)));
   }
+
+  std::cout << "distance timing: " << dis_time << " sec" << std::endl;
+  std::cout << "collision timing: " << col_time << " sec" << std::endl;
+
 }
 
 
 int main(int argc, char **argv)
 {
+  srand(time(NULL));
   testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
 }
@@ -287,3 +307,48 @@ void distance_Test2(const Transform& tf,
     std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl;
   }
 }
+
+
+bool collide_Test_OBB(const Transform& tf,
+                      const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1,
+                      const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose)
+{
+  BVHModel<OBB> m1;
+  BVHModel<OBB> m2;
+  m1.bv_splitter.reset(new BVSplitter<OBB>(split_method));
+  m2.bv_splitter.reset(new BVSplitter<OBB>(split_method));
+
+  m1.beginModel();
+  m1.addSubModel(vertices1, triangles1);
+  m1.endModel();
+
+  m2.beginModel();
+  m2.addSubModel(vertices2, triangles2);
+  m2.endModel();
+
+  Vec3f R2[3];
+  R2[0] = Vec3f(1, 0, 0);
+  R2[1] = Vec3f(0, 1, 0);
+  R2[2] = Vec3f(0, 0, 1);
+  Vec3f T2;
+
+  m1.setTransform(tf.R, tf.T);
+  m2.setTransform(R2, T2);
+
+  MeshCollisionTraversalNodeOBB node;
+  if(!initialize(node, (const BVHModel<OBB>&)m1, (const BVHModel<OBB>&)m2))
+    std::cout << "initialize error" << std::endl;
+
+  node.enable_statistics = verbose;
+  node.num_max_contacts = 1;
+  node.exhaustive = false;
+  node.enable_contact = false;
+
+  collide(&node);
+
+  if(node.pairs.size() > 0)
+    return true;
+  else
+    return false;
+}
+
diff --git a/trunk/fcl/test/test_core_utility.h b/trunk/fcl/test/test_core_utility.h
index 4a098af6..3fb04a29 100644
--- a/trunk/fcl/test/test_core_utility.h
+++ b/trunk/fcl/test/test_core_utility.h
@@ -43,6 +43,7 @@
 #include <cstdio>
 #include <vector>
 #include <iostream>
+#include <string.h>
 using namespace fcl;
 
 #if USE_PQP
-- 
GitLab