diff --git a/include/hpp/fcl/traversal/traversal_node_bvhs.h b/include/hpp/fcl/traversal/traversal_node_bvhs.h
index 82a7dfef85893b3bea481bc27295acd8614371fe..71dafc1f86dd815c74867631b3ba357c2db73c02 100644
--- a/include/hpp/fcl/traversal/traversal_node_bvhs.h
+++ b/include/hpp/fcl/traversal/traversal_node_bvhs.h
@@ -59,6 +59,10 @@ namespace hpp
 {
 namespace fcl
 {
+enum {
+  RelativeTransformationIsIdentity = 1
+};
+
 /// @brief Traversal node for collision between BVH models
 template<typename BV>
 class BVHCollisionTraversalNode : public CollisionTraversalNodeBase
@@ -124,24 +128,6 @@ public:
   {
     return model2->getBV(b).rightChild();
   }
-
-  /// @brief BV culling test in one BVTT node
-  bool BVTesting(int b1, int b2) const
-  {
-    if(enable_statistics) num_bv_tests++;
-    return !model1->getBV(b1).overlap(model2->getBV(b2));
-  }
-  
-  /// BV test between b1 and b2
-  /// \param b1, b2 Bounding volumes to test,
-  /// \retval sqrDistLowerBound square of a lower bound of the minimal
-  ///         distance between bounding volumes.
-  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const
-  {
-    if(enable_statistics) num_bv_tests++;
-    return !model1->getBV(b1).overlap(model2->getBV(b2), request,
-                                      sqrDistLowerBound);
-  }
   
   /// @brief The first BVH model
   const BVHModel<BV>* model1;
@@ -154,12 +140,38 @@ public:
   mutable FCL_REAL query_time_seconds;
 };
 
+namespace details
+{
+  template <bool enabled>
+  struct RelativeTransformation
+  {
+    RelativeTransformation () : R (Matrix3f::Identity()) {}
+
+    const Matrix3f& _R () const { return R; }
+    const Vec3f   & _T () const { return T; }
+
+    Matrix3f R;
+    Vec3f T;
+  };
+
+  template <>
+  struct RelativeTransformation <false>
+  {
+    static const Matrix3f& _R () { throw std::logic_error ("should never reach this point"); }
+    static const Vec3f   & _T () { throw std::logic_error ("should never reach this point"); }
+  };
+} // namespace details
 
 /// @brief Traversal node for collision between two meshes
-template<typename BV>
+template<typename BV, int _Options = RelativeTransformationIsIdentity>
 class MeshCollisionTraversalNode : public BVHCollisionTraversalNode<BV>
 {
 public:
+  enum {
+    Options = _Options,
+    RTIsIdentity = _Options & RelativeTransformationIsIdentity
+  };
+
   MeshCollisionTraversalNode(const CollisionRequest& request) :
   BVHCollisionTraversalNode<BV> (request)
   {
@@ -169,6 +181,36 @@ public:
     tri_indices2 = NULL;
   }
 
+  /// @brief BV culling test in one BVTT node
+  bool BVTesting(int b1, int b2) const
+  {
+    if(this->enable_statistics) this->num_bv_tests++;
+    if (RTIsIdentity)
+      return !this->model1->getBV(b1).overlap(this->model2->getBV(b2));
+    else
+      return !overlap(RT._R(), RT._T(),
+          this->model1->getBV(b1).bv, this->model2->getBV(b2).bv);
+  }
+  
+  /// BV test between b1 and b2
+  /// \param b1, b2 Bounding volumes to test,
+  /// \retval sqrDistLowerBound square of a lower bound of the minimal
+  ///         distance between bounding volumes.
+  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const
+  {
+    if(this->enable_statistics) this->num_bv_tests++;
+    if (RTIsIdentity)
+      return !this->model1->getBV(b1).overlap(this->model2->getBV(b2),
+          this->request, sqrDistLowerBound);
+    else {
+      bool res = !overlap(RT._R(), RT._T(),
+          this->model1->getBV(b1).bv, this->model2->getBV(b2).bv,
+          this->request, sqrDistLowerBound);
+      assert (!res || sqrDistLowerBound > 0);
+      return res;
+    }
+  }
+
   /// Intersection testing between leaves (two triangles)
   ///
   /// \param b1, b2 id of primitive in bounding volume hierarchy
@@ -242,61 +284,16 @@ public:
 
   Triangle* tri_indices1;
   Triangle* tri_indices2;
-};
-
-
-/// @brief Traversal node for collision between two meshes if their underlying BVH node is oriented node (OBB, RSS, OBBRSS, kIOS)
-class MeshCollisionTraversalNodeOBB : public MeshCollisionTraversalNode<OBB>
-{
-public:
-  MeshCollisionTraversalNodeOBB (const CollisionRequest& request);
-
-  bool BVTesting(int b1, int b2) const;
-
-  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const;
 
-  Matrix3f R;
-  Vec3f T;
+  details::RelativeTransformation<!bool(RTIsIdentity)> RT;
 };
 
-class MeshCollisionTraversalNodeRSS : public MeshCollisionTraversalNode<RSS>
-{
-public:
-  MeshCollisionTraversalNodeRSS (const CollisionRequest& request);
-
-  bool BVTesting(int b1, int b2) const;
 
-  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const;
-
-  Matrix3f R;
-  Vec3f T;
-};
-
-class MeshCollisionTraversalNodekIOS : public MeshCollisionTraversalNode<kIOS>
-{
-public:
-  MeshCollisionTraversalNodekIOS (const CollisionRequest& request);
- 
-  bool BVTesting(int b1, int b2) const;
-
-  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const;
-
-  Matrix3f R;
-  Vec3f T;
-};
-
-class MeshCollisionTraversalNodeOBBRSS : public MeshCollisionTraversalNode<OBBRSS>
-{
-public:
-  MeshCollisionTraversalNodeOBBRSS (const CollisionRequest& request);
- 
-  bool BVTesting(int b1, int b2) const;
-
-  bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const;
-
-  Matrix3f R;
-  Vec3f T;
-};
+/// @brief Traversal node for collision between two meshes if their underlying BVH node is oriented node (OBB, RSS, OBBRSS, kIOS)
+typedef MeshCollisionTraversalNode<OBB   , 0> MeshCollisionTraversalNodeOBB   ;
+typedef MeshCollisionTraversalNode<RSS   , 0> MeshCollisionTraversalNodeRSS   ;
+typedef MeshCollisionTraversalNode<kIOS  , 0> MeshCollisionTraversalNodekIOS  ;
+typedef MeshCollisionTraversalNode<OBBRSS, 0> MeshCollisionTraversalNodeOBBRSS;
 
 namespace details
 {
diff --git a/src/traversal/traversal_node_bvhs.cpp b/src/traversal/traversal_node_bvhs.cpp
index d241780e58bd83bf0a4ecc8fe6832dbdb5f8480a..5fe97fa5a0eaf8b892e77971b24ca2854e8b02d2 100644
--- a/src/traversal/traversal_node_bvhs.cpp
+++ b/src/traversal/traversal_node_bvhs.cpp
@@ -86,92 +86,6 @@ static inline void meshDistanceOrientedNodeLeafTesting(int b1, int b2,
 }
 } // namespace details
 
-MeshCollisionTraversalNodeOBB::MeshCollisionTraversalNodeOBB
-(const CollisionRequest& request) :
-  MeshCollisionTraversalNode<OBB> (request)
-{
-  R.setIdentity();
-}
-
-bool MeshCollisionTraversalNodeOBB::BVTesting(int b1, int b2) const
-{
-  if(enable_statistics) num_bv_tests++;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-bool MeshCollisionTraversalNodeOBB::BVTesting
-(int b1, int b2, FCL_REAL& sqrDistLowerBound) const
-{
-  if(enable_statistics) num_bv_tests++;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv,
-                  request, sqrDistLowerBound);
-}
-
-MeshCollisionTraversalNodeRSS::MeshCollisionTraversalNodeRSS
-(const CollisionRequest& request) :
-  MeshCollisionTraversalNode<RSS> (request)
-{
-  R.setIdentity();
-}
-
-bool MeshCollisionTraversalNodeRSS::BVTesting(int b1, int b2) const
-{
-  if(enable_statistics) num_bv_tests++;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-bool MeshCollisionTraversalNodeRSS::BVTesting(int b1, int b2,
-                                              FCL_REAL& sqrDistLowerBound) const
-{
-  if(enable_statistics) num_bv_tests++;
-  sqrDistLowerBound = 0;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-MeshCollisionTraversalNodekIOS::MeshCollisionTraversalNodekIOS
-(const CollisionRequest& request) :
-  MeshCollisionTraversalNode<kIOS>(request)
-{
-  R.setIdentity();
-}
-
-bool MeshCollisionTraversalNodekIOS::BVTesting(int b1, int b2) const
-{
-  if(enable_statistics) num_bv_tests++;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-bool MeshCollisionTraversalNodekIOS::BVTesting
-(int b1, int b2, FCL_REAL& sqrDistLowerBound) const
-{
-  if(enable_statistics) num_bv_tests++;
-  sqrDistLowerBound = 0;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-MeshCollisionTraversalNodeOBBRSS::MeshCollisionTraversalNodeOBBRSS
-(const CollisionRequest& request) :
-  MeshCollisionTraversalNode<OBBRSS> (request)
-{
-  R.setIdentity();
-}
-
-bool MeshCollisionTraversalNodeOBBRSS::BVTesting(int b1, int b2) const
-{
-  if(enable_statistics) num_bv_tests++;
-  return !overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv);
-}
-
-  bool MeshCollisionTraversalNodeOBBRSS::BVTesting
-  (int b1, int b2, FCL_REAL& sqrDistLowerBound) const
-  {
-    if(enable_statistics) num_bv_tests++;
-    bool res (!overlap(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv,
-                       request, sqrDistLowerBound));
-    assert (!res || sqrDistLowerBound > 0);
-    return res;
-  }
-
 namespace details
 {
 
diff --git a/src/traversal/traversal_node_setup.cpp b/src/traversal/traversal_node_setup.cpp
index 321ca128f8f2b6028b7b14981f5b59c1288b8169..7275286062ab008bbba9dcb3abbb7f5d3053bb87 100644
--- a/src/traversal/traversal_node_setup.cpp
+++ b/src/traversal/traversal_node_setup.cpp
@@ -68,7 +68,7 @@ static inline bool setupMeshCollisionOrientedNode(OrientedNode& node,
 
   node.result = &result;
 
-  relativeTransform(tf1.getRotation(), tf1.getTranslation(), tf2.getRotation(), tf2.getTranslation(), node.R, node.T);
+  relativeTransform(tf1.getRotation(), tf1.getTranslation(), tf2.getRotation(), tf2.getTranslation(), node.RT.R, node.RT.T);
 
   return true;
 }