diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b5bcd4caa77057a20c21a2a8b1ed7ff7966559e..274b8217be96a1ba7241d9f488db6f79a0441b72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,6 +48,7 @@ ENDIF(WIN32)
 OPTION (BUILD_BENCHMARK "Build the benchmarks" OFF)
 OPTION (BUILD_UTILS "Build the utils" OFF)
 OPTION (INITIALIZE_WITH_NAN "Initialize Eigen entries with NaN" OFF)
+OPTION (BUILD_TESTS_WITH_HPP "Build geom tests and benchmarks with hpp to do comparisons" OFF)
 
 IF (INITIALIZE_WITH_NAN)
   MESSAGE (STATUS "Initialize with NaN all the Eigen entries")
@@ -62,8 +63,12 @@ ADD_OPTIONAL_DEPENDENCY("eigenpy >= 1.2.0")
 ADD_OPTIONAL_DEPENDENCY("metapod >= 1.0.7")
 ADD_OPTIONAL_DEPENDENCY("urdfdom >= 0.2.10")
 ADD_OPTIONAL_DEPENDENCY("lua5.1")
+ADD_OPTIONAL_DEPENDENCY("hpp-fcl")
+IF(HPP_FCL_FOUND AND URDFDOM_FOUND)
+  ADD_REQUIRED_DEPENDENCY("assimp")
+ENDIF(HPP_FCL_FOUND AND URDFDOM_FOUND)
 
-SET(BOOST_COMPONENTS filesystem unit_test_framework)
+SET(BOOST_COMPONENTS filesystem unit_test_framework system)
 SEARCH_FOR_BOOST()
 # Path to boost headers
 INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
@@ -157,44 +162,68 @@ SET(${PROJECT_NAME}_PYTHON_HEADERS
   python/explog.hpp
   )
 
-SET(HEADERS
-  ${${PROJECT_NAME}_MATH_HEADERS}
-  ${${PROJECT_NAME}_TOOLS_HEADERS}
-  ${${PROJECT_NAME}_SPATIAL_HEADERS}
-  ${${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS}
-  ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
-  ${${PROJECT_NAME}_MULTIBODY_HEADERS}
-  ${${PROJECT_NAME}_ALGORITHM_HEADERS}
-  ${${PROJECT_NAME}_SIMULATION_HEADERS}
-  ${${PROJECT_NAME}_PYTHON_HEADERS}
-  exception.hpp
-  assert.hpp
- )
+IF(HPP_FCL_FOUND)
+  LIST(APPEND ${PROJECT_NAME}_PYTHON_HEADERS
+      python/geometry-model.hpp
+      python/geometry-data.hpp
+    )
+ENDIF(HPP_FCL_FOUND)
 
 IF(URDFDOM_FOUND)
-  SET(${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS
-    ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
+  LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS
     multibody/parser/urdf.hpp
     multibody/parser/urdf.hxx
     )
-  LIST(APPEND HEADERS
-    ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
-    )
+  
+  IF(HPP_FCL_FOUND )
+    LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS
+      multibody/parser/from-collada-to-fcl.hpp
+      multibody/parser/urdf-with-geometry.hpp
+      multibody/parser/urdf-with-geometry.hxx
+      )
+  ENDIF(HPP_FCL_FOUND)
+
   ADD_DEFINITIONS(-DWITH_URDFDOM)
 ENDIF(URDFDOM_FOUND)
 
+IF(HPP_FCL_FOUND)
+  LIST(APPEND ${PROJECT_NAME}_SPATIAL_HEADERS
+    spatial/fcl-pinocchio-conversions.hpp
+    )
+  LIST(APPEND ${PROJECT_NAME}_MULTIBODY_HEADERS
+    multibody/geometry.hpp
+    multibody/geometry.hxx
+    )
+  LIST(APPEND ${PROJECT_NAME}_ALGORITHM_HEADERS
+    algorithm/collisions.hpp
+    )
+ENDIF(HPP_FCL_FOUND)
+
 IF(LUA5_1_FOUND)
-  SET(${PROJECT_NAME}_MULTIBODY_PARSER_LUA_HEADERS
+  LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS
     multibody/parser/lua.hpp
     multibody/parser/lua/lua_tables.hpp
     )
 
-  LIST(APPEND HEADERS 
-    ${${PROJECT_NAME}_MULTIBODY_PARSER_LUA_HEADERS}
-    )
   ADD_DEFINITIONS(-DWITH_LUA)
 ENDIF(LUA5_1_FOUND)
 
+
+SET(HEADERS
+  ${${PROJECT_NAME}_MATH_HEADERS}
+  ${${PROJECT_NAME}_TOOLS_HEADERS}
+  ${${PROJECT_NAME}_SPATIAL_HEADERS}
+  ${${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS}
+  ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
+  ${${PROJECT_NAME}_MULTIBODY_HEADERS}
+  ${${PROJECT_NAME}_ALGORITHM_HEADERS}
+  ${${PROJECT_NAME}_SIMULATION_HEADERS}
+  ${${PROJECT_NAME}_PYTHON_HEADERS}
+  exception.hpp
+  assert.hpp
+ )
+LIST(REMOVE_DUPLICATES HEADERS)
+
 PKG_CONFIG_APPEND_LIBS (${PROJECT_NAME})
 
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio")
@@ -209,6 +238,7 @@ MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/algorithm")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/simulation")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/python")
 
+
 FOREACH(header ${HEADERS})
   GET_FILENAME_COMPONENT(headerName ${header} NAME)
   GET_FILENAME_COMPONENT(headerPath ${header} PATH)
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 8f12a1de669a79c4659a5a731f08ad4d00babe94..e7026c372eef46bdb976739e9bbe951f83f8c8c9 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -1,10 +1,39 @@
 # ----------------------------------------------------
 # --- BENCHMARK --------------------------------------
 # ----------------------------------------------------
+MACRO(ADD_TEST_CFLAGS target flag)
+  SET_PROPERTY(TARGET ${target} APPEND_STRING PROPERTY COMPILE_FLAGS " ${flag}")
+ENDMACRO(ADD_TEST_CFLAGS)
 
+
+# timings
+# 
 ADD_EXECUTABLE(timings timings.cpp)
 PKG_CONFIG_USE_DEPENDENCY(timings eigen3)
-PKG_CONFIG_USE_DEPENDENCY(timings urdfdom)
-TARGET_LINK_LIBRARIES(timings ${PROJECT_NAME})
-
+IF(URDFDOM_FOUND)
+  PKG_CONFIG_USE_DEPENDENCY(timings urdfdom)
+ENDIF(URDFDOM_FOUND)
+TARGET_LINK_LIBRARIES (timings ${Boost_LIBRARIES} ${PROJECT_NAME})
 SET_TARGET_PROPERTIES (timings PROPERTIES COMPILE_DEFINITIONS PINOCCHIO_SOURCE_DIR="${${PROJECT_NAME}_SOURCE_DIR}")
+
+# geomTimings
+# 
+IF(URDFDOM_FOUND AND HPP_FCL_FOUND)
+  ADD_EXECUTABLE(geomTimings timings-geometry.cpp)
+  PKG_CONFIG_USE_DEPENDENCY(geomTimings eigen3)
+  PKG_CONFIG_USE_DEPENDENCY(geomTimings urdfdom)
+  PKG_CONFIG_USE_DEPENDENCY(geomTimings assimp)
+  PKG_CONFIG_USE_DEPENDENCY(geomTimings hpp-fcl)
+  ADD_TEST_CFLAGS(geomTimings "-DWITH_HPP_FCL")
+  IF(BUILD_TESTS_WITH_HPP)
+    ADD_OPTIONAL_DEPENDENCY("hpp-model-urdf")
+    IF(HPP_MODEL_URDF_FOUND)
+      PKG_CONFIG_USE_DEPENDENCY(geomTimings hpp-model-urdf)
+      ADD_TEST_CFLAGS(geomTimings "-DWITH_HPP_MODEL_URDF")
+    ENDIF(HPP_MODEL_URDF_FOUND)
+  ENDIF(BUILD_TESTS_WITH_HPP)
+  TARGET_LINK_LIBRARIES (geomTimings ${Boost_LIBRARIES} ${PROJECT_NAME})
+  SET_TARGET_PROPERTIES (geomTimings PROPERTIES COMPILE_DEFINITIONS PINOCCHIO_SOURCE_DIR="${${PROJECT_NAME}_SOURCE_DIR}")
+ENDIF(URDFDOM_FOUND AND HPP_FCL_FOUND)
+
+
diff --git a/benchmark/timings-geometry.cpp b/benchmark/timings-geometry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..061692b4cf716b5a46a184cb7b6e0176f2944c13
--- /dev/null
+++ b/benchmark/timings-geometry.cpp
@@ -0,0 +1,282 @@
+//
+// Copyright (c) 2015 - 2016 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include "pinocchio/spatial/fwd.hpp"
+#include "pinocchio/spatial/se3.hpp"
+#include "pinocchio/multibody/joint.hpp"
+#include "pinocchio/multibody/visitor.hpp"
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/algorithm/crba.hpp"
+#include "pinocchio/algorithm/rnea.hpp"
+#include "pinocchio/algorithm/non-linear-effects.hpp"
+#include "pinocchio/algorithm/cholesky.hpp"
+#include "pinocchio/algorithm/jacobian.hpp"
+#include "pinocchio/algorithm/center-of-mass.hpp"
+#include "pinocchio/simulation/compute-all-terms.hpp"
+#include "pinocchio/algorithm/kinematics.hpp"
+#include "pinocchio/algorithm/collisions.hpp"
+#include "pinocchio/multibody/parser/urdf.hpp"
+#include "pinocchio/multibody/parser/sample-models.hpp"
+
+
+#include "pinocchio/multibody/geometry.hpp"
+#include "pinocchio/multibody/parser/urdf-with-geometry.hpp"
+#ifdef WITH_HPP_MODEL_URDF
+  #include <hpp/util/debug.hh>
+  #include <hpp/model/device.hh>
+  #include <hpp/model/body.hh>
+  #include <hpp/model/collision-object.hh>
+  #include <hpp/model/joint.hh>
+  #include <hpp/model/urdf/util.hh>
+#endif
+
+#include <iostream>
+
+#include "pinocchio/tools/timer.hpp"
+
+#include <Eigen/StdVector>
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::VectorXd)
+
+int main()
+{
+  using namespace Eigen;
+  using namespace se3;
+
+  StackTicToc timer(StackTicToc::US);
+  #ifdef NDEBUG
+  const unsigned int NBT = 1000*100;
+  const unsigned int NBD = 1000; // for heavy tests, like computeDistances()
+  #else
+    const unsigned int NBT = 1;
+    const unsigned int NBD = 1;
+    std::cout << "(the time score in debug mode is not relevant) " << std::endl;
+  #endif
+    
+
+
+  std::string romeo_filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string romeo_meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  std::pair < Model, GeometryModel > romeo = se3::urdf::buildModelAndGeom(romeo_filename, romeo_meshDir, se3::JointModelFreeFlyer());
+  se3::Model romeo_model = romeo.first;
+  se3::GeometryModel romeo_model_geom = romeo.second;
+  Data romeo_data(romeo_model);
+  GeometryData romeo_data_geom(romeo_data, romeo_model_geom);
+
+
+  std::vector<VectorXd> qs_romeo     (NBT);
+  std::vector<VectorXd> qdots_romeo  (NBT);
+  std::vector<VectorXd> qddots_romeo (NBT);
+  for(size_t i=0;i<NBT;++i)
+  {
+    qs_romeo[i]     = Eigen::VectorXd::Random(romeo_model.nq);
+    qs_romeo[i].segment<4>(3) /= qs_romeo[i].segment<4>(3).norm();
+    qdots_romeo[i]  = Eigen::VectorXd::Random(romeo_model.nv);
+    qddots_romeo[i] = Eigen::VectorXd::Random(romeo_model.nv);
+  }
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    geometry(romeo_model,romeo_data,qs_romeo[_smooth]);
+  }
+  double geom_time = timer.toc(StackTicToc::US)/NBT;
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    updateCollisionGeometry(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo[_smooth], true);
+  }
+  double update_col_time = timer.toc(StackTicToc::US)/NBT - geom_time;
+  std::cout << "Update Collision Geometry < false > = \t" << update_col_time << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    updateCollisionGeometry(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo[_smooth], true);
+    for (std::vector<se3::GeometryData::CollisionPair_t>::iterator it = romeo_data_geom.collision_pairs.begin(); it != romeo_data_geom.collision_pairs.end(); ++it)
+    {
+      romeo_data_geom.collide(it->first, it->second);
+    }
+  }
+  double collideTime = timer.toc(StackTicToc::US)/NBT - (update_col_time + geom_time);
+  std::cout << "Collision test between two geometry objects (mean time) = \t" << collideTime / romeo_data_geom.nCollisionPairs
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeCollisions(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo[_smooth], true);
+  }
+  double is_colliding_time = timer.toc(StackTicToc::US)/NBT - (update_col_time + geom_time);
+  std::cout << "Collision Test : robot in collision? = \t" << is_colliding_time
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeDistances(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo[_smooth]);
+  }
+  double computeDistancesTime = timer.toc(StackTicToc::US)/NBT - (update_col_time + geom_time);
+  std::cout << "Compute distance between two geometry objects (mean time) = \t" << computeDistancesTime / romeo_data_geom.nCollisionPairs
+            << " " << StackTicToc::unitName(StackTicToc::US) << " " << romeo_data_geom.nCollisionPairs << " col pairs" << std::endl;
+
+
+
+#ifdef WITH_HPP_MODEL_URDF
+
+
+
+  std::vector<VectorXd> qs_romeo_pino     (NBT); 
+  std::vector<VectorXd> qdots_romeo_pino  (NBT); 
+  std::vector<VectorXd> qddots_romeo_pino (NBT); 
+  for(size_t i=0;i<NBT;++i)
+  {
+    qs_romeo_pino[i]     = Eigen::VectorXd::Random(romeo_model.nq);
+    qs_romeo_pino[i].segment<4>(3) /= qs_romeo_pino[i].segment<4>(3).norm();
+    qdots_romeo_pino[i]  = Eigen::VectorXd::Random(romeo_model.nv);
+    qddots_romeo_pino[i] = Eigen::VectorXd::Random(romeo_model.nv);
+  }
+  std::vector<VectorXd> qs_romeo_hpp     (qs_romeo_pino);
+  std::vector<VectorXd> qdots_romeo_hpp  (qdots_romeo_pino);
+  std::vector<VectorXd> qddots_romeo_hpp (qddots_romeo_pino);
+
+  for (size_t i = 0; i < NBT; ++i)
+  {
+    Vector4d quaternion;
+    quaternion <<  qs_romeo_pino[i][6], qs_romeo_pino[i][3], qs_romeo_pino[i][4], qs_romeo_pino[i][5];
+    qs_romeo_hpp[i].segment<4>(3) = quaternion ;
+  }
+
+
+
+
+//   /// *************  HPP  ************* /// 
+//   /// ********************************* ///
+
+
+hpp::model::HumanoidRobotPtr_t humanoidRobot =
+    hpp::model::HumanoidRobot::create ("romeo");
+  hpp::model::urdf::loadHumanoidModel(humanoidRobot, "freeflyer",
+              "romeo_pinocchio", "romeo",
+              "", "");
+
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    updateCollisionGeometry(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo_pino[_smooth], true);
+  }
+  double compute_forward_kinematics_time = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "Update Collision Geometry < true > (K) = \t" << compute_forward_kinematics_time << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    humanoidRobot->currentConfiguration (qs_romeo_hpp[_smooth]);
+    humanoidRobot->computeForwardKinematics ();
+  }
+  double compute_forward_kinematics_time_hpp = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "HPP - Compute Forward Kinematics (K) = \t" << compute_forward_kinematics_time_hpp
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+  
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeCollisions(romeo_data_geom, true);
+  }
+  double is_romeo_colliding_time_pino = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "Pinocchio - Collision Test : robot in collision? (G) = \t" << is_romeo_colliding_time_pino
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    humanoidRobot->collisionTest();
+  }
+  double is_romeo_colliding_time_hpp = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "HPP - Collision Test : robot in collision? (G)= \t" << is_romeo_colliding_time_hpp
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+  
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeCollisions(romeo_model,romeo_data,romeo_model_geom,romeo_data_geom,qs_romeo_pino[_smooth], true);
+  }
+  is_romeo_colliding_time_pino = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "Pinocchio - Collision Test : update + robot in collision? (K+G)= \t" << is_romeo_colliding_time_pino
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    humanoidRobot->currentConfiguration (qs_romeo_hpp[_smooth]);
+    humanoidRobot->computeForwardKinematics ();
+    humanoidRobot->collisionTest();
+  }
+  is_romeo_colliding_time_hpp = timer.toc(StackTicToc::US)/NBT;
+  std::cout << "HPP - Collision Test : update + robot in collision? (K+G) = \t" << is_romeo_colliding_time_hpp
+            << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeDistances(romeo_data_geom);
+  }
+  computeDistancesTime = timer.toc(StackTicToc::US)/NBT ;
+  std::cout << "Pinocchio - Compute distances (D) " << romeo_data_geom.nCollisionPairs << " col pairs\t" << computeDistancesTime 
+            << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    humanoidRobot->computeDistances ();
+  }
+  double hpp_compute_distances = timer.toc(StackTicToc::US)/NBT ;
+  std::cout << "HPP - Compute distances (D) " << humanoidRobot->distanceResults().size() << " col pairs\t" << hpp_compute_distances 
+            << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+  
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    computeDistances(romeo_model, romeo_data, romeo_model_geom, romeo_data_geom, qs_romeo_pino[_smooth]);
+  }
+  computeDistancesTime = timer.toc(StackTicToc::US)/NBT ;
+  std::cout << "Pinocchio - Update + Compute distances (K+D) " << romeo_data_geom.nCollisionPairs << " col pairs\t" << computeDistancesTime 
+            << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+
+  timer.tic();
+  SMOOTH(NBT)
+  {
+    humanoidRobot->currentConfiguration (qs_romeo_hpp[_smooth]);
+    humanoidRobot->computeForwardKinematics ();
+    humanoidRobot->computeDistances ();
+  }
+  hpp_compute_distances = timer.toc(StackTicToc::US)/NBT ;
+  std::cout << "HPP - Update + Compute distances (K+D) " << humanoidRobot->distanceResults().size() << " col pairs\t" << hpp_compute_distances 
+            << " " << StackTicToc::unitName(StackTicToc::US) << std::endl;
+
+#endif
+
+  return 0;
+}
diff --git a/benchmark/timings.cpp b/benchmark/timings.cpp
index 4acf2a2b401486f7b763d0050e6554ced3a036f1..e6cf7557bf0302cdc56bf6396680ff05b9931391 100644
--- a/benchmark/timings.cpp
+++ b/benchmark/timings.cpp
@@ -1,3 +1,20 @@
+//
+// Copyright (c) 2015 - 2016 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
 #include "pinocchio/spatial/fwd.hpp"
 #include "pinocchio/spatial/se3.hpp"
 #include "pinocchio/multibody/joint.hpp"
@@ -14,6 +31,7 @@
 #include "pinocchio/multibody/parser/urdf.hpp"
 #include "pinocchio/multibody/parser/sample-models.hpp"
 
+
 #include <iostream>
 
 #include "pinocchio/tools/timer.hpp"
@@ -137,6 +155,7 @@ int main(int argc, const char ** argv)
   }
   std::cout << "Geometry = \t"; timer.toc(std::cout,NBT);
 
+
   timer.tic();
   SMOOTH(NBT)
   {
diff --git a/models/romeo.urdf b/models/romeo.urdf
index 1760f0483d1117b149b31d3d66e2ff79e7a7a17c..88a3da6a70d2373165f6365fb443e57f543612bb 100644
--- a/models/romeo.urdf
+++ b/models/romeo.urdf
@@ -6,6 +6,12 @@
 <!-- Aldebaran file comes from                                                               --> 
 <!-- https://github.com/ros-aldebaran/romeo_robot/blob/master/romeo_description/urdf/romeoV1_generated_urdf/romeo.urdf -->
 <robot name="romeoH37V1" xmlns:xacro="http://www.ros.org/wiki/xacro">
+  <link name="base_link"/>
+  <joint name="waist" type="fixed">
+    <parent link="base_link"/>
+    <child link="body"/>
+    <origin rpy="0 0 0" xyz="0 0 0"/>
+  </joint>
   <joint name="NeckYaw" type="revolute">
     <parent link="torso"/>
     <child link="NeckYawLink"/>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 68bc30d4f7719fb51cb9d7303e69b85f90d5a282..3b12df4f8d666fe5812911da91ae49026c75d772 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -67,6 +67,18 @@ IF (UNIX)
 		SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
       PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} eigen3)
 
+    IF(URDFDOM_FOUND)
+      PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} urdfdom)
+      IF(HPP_FCL_FOUND)
+        PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} assimp)
+      ENDIF(HPP_FCL_FOUND)
+    ENDIF(URDFDOM_FOUND)
+
+    IF(HPP_FCL_FOUND)
+      PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} hpp-fcl)
+      ADD_TARGET_CFLAGS (${PROJECT_NAME} "-DWITH_HPP_FCL")
+    ENDIF(HPP_FCL_FOUND)
+
     IF(LUA5_1_FOUND)
       PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} lua5.1)
     ENDIF(LUA5_1_FOUND)
@@ -91,7 +103,14 @@ IF(EIGENPY_FOUND)
   PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} eigenpy)
   IF(URDFDOM_FOUND)
     PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} urdfdom)
+    IF(HPP_FCL_FOUND)
+      PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} assimp)
+    ENDIF(HPP_FCL_FOUND)
   ENDIF(URDFDOM_FOUND)
+  IF(HPP_FCL_FOUND)
+    PKG_CONFIG_USE_DEPENDENCY(${PYWRAP}  hpp-fcl)
+    ADD_TARGET_CFLAGS (${PYWRAP}  "-DWITH_HPP_FCL")
+  ENDIF(HPP_FCL_FOUND)
   IF(LUA5_1_FOUND)
     PKG_CONFIG_USE_DEPENDENCY(${PYWRAP} lua5.1)
   ENDIF(LUA5_1_FOUND)
diff --git a/src/algorithm/collisions.hpp b/src/algorithm/collisions.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fc4f9df8c6393e908d274c95acec37ca4ddd49b5
--- /dev/null
+++ b/src/algorithm/collisions.hpp
@@ -0,0 +1,151 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_collisions_hpp__
+#define __se3_collisions_hpp__
+
+#include "pinocchio/multibody/visitor.hpp"
+#include "pinocchio/multibody/model.hpp"
+
+#include "pinocchio/algorithm/kinematics.hpp"
+#include "pinocchio/multibody/geometry.hpp"
+
+namespace se3
+{
+
+
+  inline void updateCollisionGeometry(const Model & model,
+                                      Data & data,
+                                      const GeometryModel& geom,
+                                      GeometryData& data_geom,
+                                      const Eigen::VectorXd & q,
+                                      const bool computeGeometry = false
+                                      );
+
+  inline bool computeCollisions(const Model & model,
+                                Data & data,
+                                const GeometryModel & model_geom,
+                                GeometryData & data_geom,
+                                const Eigen::VectorXd & q,
+                                const bool stopAtFirstCollision = false
+                                );
+
+  inline bool computeCollisions(GeometryData & data_geom,
+                                const bool stopAtFirstCollision = false
+                                );
+
+  inline void computeDistances(GeometryData & data_geom);
+
+  inline void computeDistances(const Model & model,
+                              Data & data,
+                              const GeometryModel & model_geom,
+                              GeometryData & data_geom,
+                              const Eigen::VectorXd & q
+                              );
+
+} // namespace se3 
+
+/* --- Details -------------------------------------------------------------------- */
+namespace se3 
+{
+  
+  
+inline void  updateCollisionGeometry(const Model & model,
+                                     Data & data,
+                                     const GeometryModel & model_geom,
+                                     GeometryData & data_geom,
+                                     const Eigen::VectorXd & q,
+                                     const bool computeGeometry
+                                     )
+{
+  using namespace se3;
+
+  if (computeGeometry) geometry(model, data, q);
+  for (GeometryData::Index i=0; i < (GeometryData::Index) data_geom.model_geom.ngeom; ++i)
+  {
+    const Model::Index & parent = model_geom.geom_parents[i];
+    data_geom.oMg[i] =  (data.oMi[parent] * model_geom.geometryPlacement[i]);
+    data_geom.oMg_fcl[i] =  toFclTransform3f(data_geom.oMg[i]);
+  }
+}
+
+inline bool computeCollisions(GeometryData & data_geom,
+                              const bool stopAtFirstCollision
+                              )
+{
+  using namespace se3;
+
+  bool isColliding = false;
+
+  for (std::size_t cpt = 0; cpt < data_geom.collision_pairs.size(); ++cpt)
+  {
+    data_geom.collisions[cpt] = data_geom.collide(data_geom.collision_pairs[cpt].first, data_geom.collision_pairs[cpt].second);
+    isColliding = data_geom.collisions[cpt];
+    if(isColliding && stopAtFirstCollision)
+    {
+      return true;
+    }
+  }
+  return isColliding;
+}
+
+// WARNING, if stopAtFirstcollision = true, then the collisions vector will not be fulfilled.
+inline bool computeCollisions(const Model & model,
+                              Data & data,
+                              const GeometryModel & model_geom,
+                              GeometryData & data_geom,
+                              const Eigen::VectorXd & q,
+                              const bool stopAtFirstCollision
+                              )
+{
+  using namespace se3;
+
+
+  updateCollisionGeometry (model, data, model_geom, data_geom, q, true);
+
+  
+  return computeCollisions(data_geom, stopAtFirstCollision);
+
+}
+
+
+inline void computeDistances(GeometryData & data_geom)
+{
+  for (std::size_t cpt = 0; cpt < data_geom.collision_pairs.size(); ++cpt)
+  {
+    data_geom.distances[cpt] = DistanceResult(data_geom.computeDistance(data_geom.collision_pairs[cpt].first, data_geom.collision_pairs[cpt].second),
+                                              data_geom.collision_pairs[cpt].first,
+                                              data_geom.collision_pairs[cpt].second
+                                              );
+  }
+}
+
+inline void computeDistances(const Model & model,
+                            Data & data,
+                            const GeometryModel & model_geom,
+                            GeometryData & data_geom,
+                            const Eigen::VectorXd & q
+                            )
+{
+  updateCollisionGeometry (model, data, model_geom, data_geom, q, true);
+
+  computeDistances(data_geom);
+}
+} // namespace se3
+
+#endif // ifndef __se3_collisions_hpp__
+
diff --git a/src/algorithm/kinematics.hpp b/src/algorithm/kinematics.hpp
index 77a59ceec3e6f89f497501805afa8c296b6db6fc..3181e00fb62966fa5896d2f89bec9288dac23163 100644
--- a/src/algorithm/kinematics.hpp
+++ b/src/algorithm/kinematics.hpp
@@ -20,13 +20,15 @@
 
 #include "pinocchio/multibody/visitor.hpp"
 #include "pinocchio/multibody/model.hpp"
-  
+
 namespace se3
 {
   inline void geometry(const Model & model,
                        Data & data,
                        const Eigen::VectorXd & q);
 
+
+
   inline void kinematics(const Model & model,
                          Data & data,
                          const Eigen::VectorXd & q,
@@ -90,6 +92,7 @@ namespace se3
     }
   }
 
+
   struct KinematicsStep : public fusion::JointVisitor<KinematicsStep>
   {
     typedef boost::fusion::vector< const se3::Model&,
diff --git a/src/multibody/geometry.hpp b/src/multibody/geometry.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..886209e3166b65f4b9a241f77d43730d85dad456
--- /dev/null
+++ b/src/multibody/geometry.hpp
@@ -0,0 +1,201 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_geom_hpp__
+#define __se3_geom_hpp__
+
+
+#include "pinocchio/spatial/fwd.hpp"
+#include "pinocchio/spatial/se3.hpp"
+#include "pinocchio/spatial/force.hpp"
+#include "pinocchio/spatial/motion.hpp"
+#include "pinocchio/spatial/inertia.hpp"
+#include "pinocchio/spatial/fcl-pinocchio-conversions.hpp"
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/multibody/joint/joint-variant.hpp"
+#include <iostream>
+
+#include <hpp/fcl/collision_object.h>
+#include <hpp/fcl/collision.h>
+#include <hpp/fcl/distance.h>
+#include <map>
+#include <list>
+#include <utility>
+
+
+namespace se3
+{
+  class IsSameCollisionPair
+  {
+  typedef Model::Index Index;
+  typedef std::pair < Index, Index > CollisionPair_t;
+  public:
+  IsSameCollisionPair( CollisionPair_t pair): _pair(pair) {}
+
+  bool operator()(CollisionPair_t pair) const
+  {
+    return (pair == _pair);
+  }
+  private:
+  CollisionPair_t _pair;
+  };
+
+  // Result of distance computation between two CollisionObject.
+  struct DistanceResult
+  {
+    typedef Model::Index Index;
+
+    DistanceResult(fcl::DistanceResult dist_fcl, Index o1, Index o2)
+    : fcl_distance_result(dist_fcl), object1(o1), object2(o2)
+    {}
+
+    // Get distance between objects
+    double distance () const { return fcl_distance_result.min_distance; }
+
+    // Get closest point on inner object in global frame,
+    Eigen::Vector3d closestPointInner () const { return toVector3d(fcl_distance_result.nearest_points [0]); }
+    
+    // Get closest point on outer object in global frame,
+    Eigen::Vector3d closestPointOuter () const { return toVector3d(fcl_distance_result.nearest_points [1]); }
+    
+    bool operator == (const DistanceResult & other) const
+    {
+      return (distance() == other.distance()
+        && closestPointInner() == other.closestPointInner()
+        && closestPointOuter() == other.closestPointOuter()
+        && object1 == other.object1
+        && object2 == other.object2);
+    }
+    fcl::DistanceResult fcl_distance_result;
+    std::size_t object1;
+    std::size_t object2;
+  }; // struct DistanceResult 
+  
+  class GeometryModel
+  {
+  public:
+    typedef Model::Index Index;
+
+    Index ngeom;
+    std::vector<fcl::CollisionObject> collision_objects;
+    std::vector<std::string> geom_names;
+    std::vector<Index> geom_parents;                          // Joint parent of body <i>, denoted <li> (li==parents[i])
+    std::vector<SE3> geometryPlacement;                       // Position of geometry object in parent joint's frame
+    
+    std::map < Index, std::list<Index> >  innerObjects;       // Associate a list of CollisionObjects to a given joint Id 
+    std::map < Index, std::list<Index> >  outerObjects;       // Associate a list of CollisionObjects to a given joint Id 
+
+    GeometryModel()
+      : ngeom(0)
+      , collision_objects()
+      , geom_names(0)
+      , geom_parents(0)
+      , geometryPlacement(0)
+      , innerObjects()
+      , outerObjects()
+    {
+    }
+
+    ~GeometryModel() {};
+
+    Index addGeomObject(  Index parent,const fcl::CollisionObject & co, const SE3 & placement, const std::string & geoName = "");
+    Index getGeomId( const std::string & name ) const;
+    bool existGeomName( const std::string & name ) const;
+    const std::string& getGeomName( Index index ) const;
+
+    void addInnerObject(Index joint, Index inner_object);
+    void addOutterObject(Index joint, Index outer_object);
+
+    friend std::ostream& operator<<(std::ostream& os, const GeometryModel& model_geom);
+
+  private:
+    
+  };
+
+  class GeometryData
+  {
+  public:
+    typedef Model::Index Index;
+    typedef std::pair < Index, Index > CollisionPair_t;
+
+    Data& data_ref;
+    GeometryModel& model_geom;
+
+    std::vector<se3::SE3> oMg;
+    std::vector<fcl::Transform3f> oMg_fcl;
+
+    std::vector < CollisionPair_t > collision_pairs;
+    Index nCollisionPairs;
+
+    std::vector < DistanceResult > distances;
+    std::vector < bool > collisions;
+
+    GeometryData(Data& data, GeometryModel& model_geom)
+        : data_ref(data)
+        , model_geom(model_geom)
+        , oMg(model_geom.ngeom)
+        , oMg_fcl(model_geom.ngeom)
+        , collision_pairs()
+        , nCollisionPairs(0)
+        , distances()
+        , collisions()
+    {
+      initializeListOfCollisionPairs();
+      distances.resize(nCollisionPairs, DistanceResult( fcl::DistanceResult(), 0, 0) );
+      collisions.resize(nCollisionPairs, false );
+
+    }
+
+    ~GeometryData() {};
+
+    void addCollisionPair (Index co1, Index co2);
+    void addCollisionPair (const CollisionPair_t& pair);
+    void removeCollisionPair (Index co1, Index co2);
+    void removeCollisionPair (const CollisionPair_t& pair);
+    bool isCollisionPair (Index co1, Index co2) const ;
+    bool isCollisionPair (const CollisionPair_t& pair) const;
+    void fillAllPairsAsCollisions();
+    void desactivateCollisionPairs();
+    void initializeListOfCollisionPairs();
+
+    bool collide(Index co1, Index co2) const;
+
+    fcl::DistanceResult computeDistance(Index co1, Index co2) const;
+    void resetDistances();
+
+    std::vector < DistanceResult > distanceResults(); //TODO : to keep or not depending of public or not for distances
+
+    void displayCollisionPairs() const
+    {
+      for (std::vector<CollisionPair_t>::const_iterator it = collision_pairs.begin(); it != collision_pairs.end(); ++it)
+      {
+        std::cout << it-> first << "\t" << it->second << std::endl;
+      }
+    }
+    friend std::ostream& operator<<(std::ostream& os, const GeometryData& data_geom);
+  private:
+    
+  };
+
+} // namespace se3
+
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+#include "pinocchio/multibody/geometry.hxx"
+
+#endif // ifndef __se3_geom_hpp__
diff --git a/src/multibody/geometry.hxx b/src/multibody/geometry.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..c509baa367a9bbc3505ed860476fb06e44d35e4e
--- /dev/null
+++ b/src/multibody/geometry.hxx
@@ -0,0 +1,223 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_geom_hxx__
+#define __se3_geom_hxx__
+
+
+#include "pinocchio/spatial/fwd.hpp"
+#include "pinocchio/spatial/se3.hpp"
+#include "pinocchio/spatial/force.hpp"
+#include "pinocchio/spatial/motion.hpp"
+#include "pinocchio/spatial/inertia.hpp"
+#include "pinocchio/spatial/fcl-pinocchio-conversions.hpp"
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/multibody/joint/joint-variant.hpp"
+#include <iostream>
+
+#include <hpp/fcl/collision_object.h>
+#include <hpp/fcl/collision.h>
+#include <hpp/fcl/distance.h>
+#include <map>
+#include <list>
+#include <utility>
+
+
+namespace se3
+{
+
+  inline GeometryModel::Index GeometryModel::addGeomObject(  Index parent,const fcl::CollisionObject & co, const SE3 & placement, const std::string & geoName )
+  {
+
+    Index idx = (Index) (ngeom ++);
+
+
+    collision_objects    .push_back(co);
+    geom_parents         .push_back(parent);
+    geometryPlacement                  .push_back(placement);
+    geom_names           .push_back( (geoName!="")?geoName:random(8));
+
+    return idx;
+  }
+
+  inline GeometryModel::Index GeometryModel::getGeomId( const std::string & name ) const
+  {
+    std::vector<std::string>::iterator::difference_type
+      res = std::find(geom_names.begin(),geom_names.end(),name) - geom_names.begin();
+    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
+    assert( (res>=0)&&(res<(long)collision_objects.size())&&"The joint name you asked do not exist" );
+    return Index(res);
+  }
+
+  inline bool GeometryModel::existGeomName( const std::string & name ) const
+  {
+    return (geom_names.end() != std::find(geom_names.begin(),geom_names.end(),name));
+  }
+  
+  inline const std::string& GeometryModel::getGeomName( Index index ) const
+  {
+    assert( index < (Index)collision_objects.size() );
+    return geom_names[index];
+  }
+
+  inline void GeometryModel::addInnerObject(Index joint, Index inner_object)
+  {
+    if (std::find(innerObjects[joint].begin(), innerObjects[joint].end(),inner_object)==innerObjects[joint].end())
+      innerObjects[joint].push_back(inner_object);
+    else
+      std::cout << "inner object already added" << std::endl;
+  }
+
+  inline void GeometryModel::addOutterObject(Index joint, Index outer_object)
+  {
+    if (std::find(outerObjects[joint].begin(), outerObjects[joint].end(),outer_object)==outerObjects[joint].end())
+      outerObjects[joint].push_back(outer_object);
+    else
+      std::cout << "outer object already added" << std::endl;
+  }
+
+  inline std::ostream& operator<<(std::ostream& os, const GeometryModel& model_geom)
+  {
+    os << "Nb collision objects = " << model_geom.ngeom << std::endl;
+    
+    for(GeometryModel::Index i=0;i<(GeometryModel::Index)(model_geom.ngeom);++i)
+    {
+      os  << "Object n " << i << " : " << model_geom.geom_names[i] << ": attached to joint = " << model_geom.geom_parents[i]
+          << "\nwith offset \n" << model_geom.geometryPlacement[i] <<std::endl;
+    }
+
+    return os;
+  }
+
+  inline std::ostream& operator<<(std::ostream& os, const GeometryData& data_geom)
+  {
+
+    for(GeometryData::Index i=0;i<(GeometryData::Index)(data_geom.model_geom.ngeom);++i)
+    {
+      os << "collision object oMi " << data_geom.oMg[i] << std::endl;
+    }
+
+    return os;
+  }
+
+  inline void GeometryData::addCollisionPair (Index co1, Index co2)
+  {
+    assert ( co1 < co2);
+    assert ( co2 < model_geom.ngeom);
+    CollisionPair_t pair(co1, co2);
+    
+    addCollisionPair(pair);
+  }
+
+  inline void GeometryData::addCollisionPair (const CollisionPair_t& pair)
+  {
+    assert(pair.first < pair.second);
+    assert(pair.second < model_geom.ngeom);
+    collision_pairs.push_back(pair);
+    nCollisionPairs++;
+  }
+
+  inline void GeometryData::removeCollisionPair (Index co1, Index co2)
+  {
+    assert(co1 < co2);
+    assert(co2 < model_geom.ngeom);
+    assert(isCollisionPair(co1,co2));
+
+    removeCollisionPair (CollisionPair_t(co1,co2));
+  }
+
+  inline void GeometryData::removeCollisionPair (const CollisionPair_t& pair)
+  {
+    assert(pair.first < pair.second);
+    assert(pair.second < model_geom.ngeom);
+    assert(isCollisionPair(pair));
+
+    collision_pairs.erase(std::remove(collision_pairs.begin(), collision_pairs.end(), pair), collision_pairs.end());
+    nCollisionPairs--;
+  }
+
+  inline bool GeometryData::isCollisionPair (Index co1, Index co2) const
+  {
+    return isCollisionPair(CollisionPair_t(co1,co2));
+  }
+
+  inline bool GeometryData::isCollisionPair (const CollisionPair_t& pair) const
+  {
+    return (std::find_if (  collision_pairs.begin(), collision_pairs.end(),
+                            IsSameCollisionPair(pair)) != collision_pairs.end());
+
+  }
+
+  inline void GeometryData::fillAllPairsAsCollisions()
+  {
+    for (Index i = 0; i < model_geom.ngeom; ++i)
+    {
+      for (Index j = i+1; j < model_geom.ngeom; ++j)
+      {
+        addCollisionPair(i,j);
+      }
+    }
+  }
+
+  // TODO :  give a srdf file as argument, read it, and remove corresponding
+  // pairs from list collision_pairs
+  inline void GeometryData::desactivateCollisionPairs()
+  {
+
+  }
+
+  inline void GeometryData::initializeListOfCollisionPairs()
+  {
+    fillAllPairsAsCollisions();
+    desactivateCollisionPairs();
+    assert(nCollisionPairs == collision_pairs.size());
+  }
+
+  inline bool GeometryData::collide(Index co1, Index co2) const
+  {
+    fcl::CollisionRequest collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP);
+    fcl::CollisionResult collisionResult;
+
+    if (fcl::collide (model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
+                      model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
+                      collisionRequest, collisionResult) != 0)
+    {
+      return true;
+    }
+    return false;
+  }
+
+
+  inline fcl::DistanceResult GeometryData::computeDistance(Index co1, Index co2) const
+  {
+    fcl::DistanceRequest distanceRequest (true, 0, 0, fcl::GST_INDEP);
+    fcl::DistanceResult result;
+    fcl::distance ( model_geom.collision_objects[co1].collisionGeometry().get(), oMg_fcl[co1],
+                    model_geom.collision_objects[co2].collisionGeometry().get(), oMg_fcl[co2],
+                    distanceRequest, result);
+    return result;
+  }
+
+  inline void GeometryData::resetDistances()
+  {
+    std::fill(distances.begin(), distances.end(), DistanceResult( fcl::DistanceResult(), 0, 0) );
+  }
+
+
+} // namespace se3
+
+#endif // ifndef __se3_geom_hxx__
diff --git a/src/multibody/parser/from-collada-to-fcl.hpp b/src/multibody/parser/from-collada-to-fcl.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..75938acb549fd34b43da4a859c2e8c0f9d4697d8
--- /dev/null
+++ b/src/multibody/parser/from-collada-to-fcl.hpp
@@ -0,0 +1,207 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio and is mainly inspired
+// by software hpp-model-urdf
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_collada_to_fcl_hpp__
+#define __se3_collada_to_fcl_hpp__
+
+#include <limits>
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+
+#include <assimp/DefaultLogger.h>
+
+#include <assimp/assimp.hpp>
+#include <assimp/aiScene.h>
+#include <assimp/aiPostProcess.h>
+#include <assimp/IOStream.h>
+#include <assimp/IOSystem.h>
+
+
+#include <hpp/fcl/BV/OBBRSS.h>
+#include <hpp/fcl/BVH/BVH_model.h>
+
+typedef fcl::BVHModel< fcl::OBBRSS > PolyhedronType;
+typedef boost::shared_ptr <PolyhedronType> PolyhedronPtrType;
+
+struct TriangleAndVertices
+{
+  void clear()
+  {
+    vertices_.clear ();
+    triangles_.clear ();
+  }
+  std::vector <fcl::Vec3f> vertices_;
+  std::vector <fcl::Triangle> triangles_;
+};
+
+
+/**
+ * @brief      Recursive procedure for building a mesh
+ *
+ * @param[in]  scale           Scale to apply when reading the ressource
+ * @param[in]  scene           Pointer to the assimp scene
+ * @param[in]  node            Current node of the scene
+ * @param      subMeshIndexes  Submesh triangles indexes interval
+ * @param[in]  mesh            The mesh that must be built
+ * @param      tv              Triangles and Vertices of the mesh submodels
+ */
+inline void buildMesh (const ::urdf::Vector3& scale, const aiScene* scene, const aiNode* node,
+                        std::vector<unsigned>& subMeshIndexes, const PolyhedronPtrType& mesh,
+                        TriangleAndVertices& tv)
+{
+  if (!node) return;
+
+  aiMatrix4x4 transform = node->mTransformation;
+  aiNode *pnode = node->mParent;
+  while (pnode)
+  {
+    // Don't convert to y-up orientation, which is what the root node in
+    // Assimp does
+    if (pnode->mParent != NULL)
+    {
+      transform = pnode->mTransformation * transform;
+    }
+    pnode = pnode->mParent;
+  }
+
+  for (uint32_t i = 0; i < node->mNumMeshes; i++)
+  {
+    aiMesh* input_mesh = scene->mMeshes[node->mMeshes[i]];
+
+    unsigned oldNbPoints = mesh->num_vertices;
+    unsigned oldNbTriangles = mesh->num_tris;
+
+    // Add the vertices
+    for (uint32_t j = 0; j < input_mesh->mNumVertices; j++)
+    {
+      aiVector3D p = input_mesh->mVertices[j];
+      p *= transform;
+      tv.vertices_.push_back (fcl::Vec3f (p.x * scale.x,
+                                       p.y * scale.y,
+                                       p.z * scale.z));
+    }
+
+    // add the indices
+    for (uint32_t j = 0; j < input_mesh->mNumFaces; j++)
+    {
+      aiFace& face = input_mesh->mFaces[j];
+      // FIXME: can add only triangular faces.
+      tv.triangles_.push_back (fcl::Triangle( oldNbPoints + face.mIndices[0],
+                                           oldNbPoints + face.mIndices[1],
+                                           oldNbPoints + face.mIndices[2]));
+    }
+
+    // Save submesh triangles indexes interval.
+    if (subMeshIndexes.size () == 0)
+    {
+      subMeshIndexes.push_back (0);
+    }
+
+    subMeshIndexes.push_back (oldNbTriangles + input_mesh->mNumFaces);
+  }
+
+  for (uint32_t i=0; i < node->mNumChildren; ++i)
+  {
+    buildMesh(scale, scene, node->mChildren[i], subMeshIndexes, mesh, tv);
+  }
+}
+
+
+
+/**
+ * @brief      Convert an assimp scene to a mesh
+ *
+ * @param[in]  name   File (ressource) transformed into an assimp scene in loa
+ * @param[in]  scale  Scale to apply when reading the ressource
+ * @param[in]  scene  Pointer to the assimp scene
+ * @param[in]  mesh   The mesh that must be built
+ */
+inline void meshFromAssimpScene (const std::string& name, const ::urdf::Vector3& scale,
+                                    const aiScene* scene,const PolyhedronPtrType& mesh)
+  {
+    TriangleAndVertices tv;
+
+    if (!scene->HasMeshes())
+    {
+      throw std::runtime_error (std::string ("No meshes found in file ")+
+        name);
+    }
+
+    std::vector<unsigned> subMeshIndexes;
+    int res = mesh->beginModel ();
+
+    if (res != fcl::BVH_OK)
+    {
+      std::ostringstream error;
+      error << "fcl BVHReturnCode = " << res;
+      throw std::runtime_error (error.str ());
+    }
+
+    tv.clear();
+
+    buildMesh (scale, scene, scene->mRootNode, subMeshIndexes, mesh, tv);
+    mesh->addSubModel (tv.vertices_, tv.triangles_);
+
+    mesh->endModel ();
+  }
+
+
+/**
+ * @brief      Read a mesh file and convert it to a polyhedral mesh
+ *
+ * @param[in]  resource_path  Path to the ressource mesh file to be read
+ * @param[in]  scale          Scale to apply when reading the ressource
+ * @param[in]  polyhedron     The resulted polyhedron
+ */
+inline void loadPolyhedronFromResource ( const std::string& resource_path, const ::urdf::Vector3& scale,
+                                          const PolyhedronPtrType& polyhedron)
+{
+  Assimp::Importer importer;
+  const aiScene* scene = importer.ReadFile(resource_path.c_str(), aiProcess_SortByPType| aiProcess_GenNormals|
+                                                          aiProcess_Triangulate|aiProcess_GenUVCoords|
+                                                          aiProcess_FlipUVs);
+  if (!scene)
+  {
+    throw std::runtime_error (std::string ("Could not load resource ") + resource_path + std::string ("\n") +
+                              importer.GetErrorString ());
+  }
+
+  meshFromAssimpScene (resource_path, scale, scene, polyhedron);
+}
+
+
+/**
+ * @brief      Transform a cURL readable path (package://..) to an absolute path for urdf collision path
+ *
+ * @param      urdf_mesh_path  The path given in the urdf file (package://..)
+ * @param[in]  meshRootDir     Root path to the directory where meshes are located
+ *
+ * @return     The absolute path to the mesh file
+ */
+inline std::string fromURDFMeshPathToAbsolutePath(std::string & urdf_mesh_path, std::string meshRootDir)
+{ 
+
+  std::string absolutePath = std::string(meshRootDir +  
+                              urdf_mesh_path.substr(10, urdf_mesh_path.size()));
+
+  return absolutePath;
+}
+
+#endif // __se3_collada_to_fcl_hpp__
diff --git a/src/multibody/parser/sample-models.cpp b/src/multibody/parser/sample-models.cpp
index fefdc1ad643486eb5650d31ee08b838a9560debc..9cdc2d4f960b90c7fcf8817eec0e7b63bea6b2ba 100644
--- a/src/multibody/parser/sample-models.cpp
+++ b/src/multibody/parser/sample-models.cpp
@@ -18,6 +18,10 @@
 
 #include "pinocchio/multibody/parser/sample-models.hpp"
 
+#ifdef WITH_HPP_FCL
+#include <hpp/fcl/shape/geometric_shapes.h>
+#endif
+
 namespace se3
 {
   namespace buildModels
@@ -193,5 +197,24 @@ namespace se3
                     "larm6_joint", "larm6_body");
     }
 
+    #ifdef WITH_HPP_FCL
+    void collisionModel( Model& model, GeometryModel& model_geom)
+    {
+      model.addBody(model.getBodyId("universe"),JointModelPlanar(),SE3::Identity(),Inertia::Random(),
+                    "planar1_joint", "planar1_body");
+      model.addBody(model.getBodyId("universe"),JointModelPlanar(),SE3::Identity(),Inertia::Random(),
+                    "planar2_joint", "planar2_body");
+
+      boost::shared_ptr<fcl::Box> Sample(new fcl::Box(1));
+      fcl::CollisionObject box1(Sample, fcl::Transform3f());
+      model_geom.addGeomObject(model.getJointId("planar1_joint"),box1, SE3::Identity(),  "ff1_collision_object"); 
+
+      boost::shared_ptr<fcl::Box> Sample2(new fcl::Box(1));
+      fcl::CollisionObject box2(Sample, fcl::Transform3f());
+      model_geom.addGeomObject(model.getJointId("planar2_joint"),box2, SE3::Identity(),  "ff2_collision_object");
+
+    }
+    #endif
+
   } // namespace buildModels
 } // namespace se3
diff --git a/src/multibody/parser/sample-models.hpp b/src/multibody/parser/sample-models.hpp
index e618bc16f482fbd78227afa46efde4f5fd6d0cfa..405379545033479a684ca5c12a2c03ea5cb4f954 100644
--- a/src/multibody/parser/sample-models.hpp
+++ b/src/multibody/parser/sample-models.hpp
@@ -21,6 +21,10 @@
 
 #include "pinocchio/multibody/model.hpp"
 
+#ifdef WITH_HPP_FCL
+#include "pinocchio/multibody/geometry.hpp"
+#endif
+
 namespace se3
 {
   namespace buildModels
@@ -30,6 +34,10 @@ namespace se3
 
     void humanoidSimple(Model& model, bool usingFF = true);
 
+    #ifdef WITH_HPP_FCL
+    void collisionModel( Model& model, GeometryModel& geom);
+    #endif
+
   } // namespace buildModels
 } // namespace se3
 
diff --git a/src/multibody/parser/urdf-with-geometry.hpp b/src/multibody/parser/urdf-with-geometry.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a5a26032f596298144a804c1ec383e6234c39b23
--- /dev/null
+++ b/src/multibody/parser/urdf-with-geometry.hpp
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_urdf_geom_hpp__
+#define __se3_urdf_geom_hpp__
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+#include <iostream>
+#include <boost/foreach.hpp>
+#include "pinocchio/multibody/model.hpp"
+
+#include <hpp/fcl/collision_object.h>
+#include <hpp/fcl/collision.h>
+#include <hpp/fcl/shape/geometric_shapes.h>
+#include "pinocchio/multibody/parser/from-collada-to-fcl.hpp"
+
+#include <exception>
+
+namespace urdf
+{
+  typedef boost::shared_ptr<ModelInterface> ModelInterfacePtr;
+  typedef boost::shared_ptr<const Joint> JointConstPtr;
+  typedef boost::shared_ptr<const Link> LinkConstPtr;
+  typedef boost::shared_ptr<Link> LinkPtr;
+  typedef boost::shared_ptr<const Inertial> InertialConstPtr;
+}
+
+namespace se3
+{
+  namespace urdf
+  {
+
+
+    /**
+     * @brief      Get a CollisionObject from an urdf link, reading the
+     *             corresponding mesh
+     *
+     * @param[in]  link         The input urdf link
+     * @param[in]  meshRootDir  Root path to the directory where meshes are located
+     *
+     * @return     The mesh converted as a fcl::CollisionObject
+     */
+    inline fcl::CollisionObject retrieveCollisionGeometry (const ::urdf::LinkConstPtr & link, const std::string & meshRootDir);
+
+    
+    /**
+     * @brief      Recursive procedure for reading the URDF tree, looking for geometries
+     *             This function fill the geometric model whith geometry objects retrieved from the URDF tree
+     *
+     * @param[in]  link         The current URDF link
+     * @param      model        The model to which is the Geometry Model associated
+     * @param      model_geom   The Geometry Model where the Collision Objects must be added
+     * @param[in]  meshRootDir  Root path to the directory where meshes are located
+     */
+    inline void parseTreeForGeom( ::urdf::LinkConstPtr link, Model & model,GeometryModel & model_geom, const std::string & meshRootDir, const bool rootJointAdded) throw (std::invalid_argument);
+
+
+
+    /**
+     * @brief      Build The Model and GeometryModel from a URDF file with a particular joint as root of the model tree
+     *
+     * @param[in]  filename     The URDF complete file path
+     * @param[in]  meshRootDir  Root path to the directory where meshes are located
+     *
+     * @return     The pair <se3::Model, se3::GeometryModel> the Model tree and its geometric model associated
+     */
+    template <typename D>
+    std::pair<Model, GeometryModel > buildModelAndGeom( const std::string & filename, const std::string & meshRootDir, const JointModelBase<D> &  root_joint );
+
+
+    /**
+     * @brief      Build The Model and GeometryModel from a URDF file with no root joint added to the model tree
+     *
+     * @param[in]  filename     The URDF complete file path
+     * @param[in]  meshRootDir  Root path to the directory where meshes are located
+     *
+     * @return     The pair <se3::Model, se3::GeometryModel> the Model tree and its geometric model associated
+     */
+    inline std::pair<Model, GeometryModel > buildModelAndGeom( const std::string & filename, const std::string & meshRootDir);
+
+  } // namespace urdf
+} // namespace se3
+
+
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+#include "pinocchio/multibody/parser/urdf-with-geometry.hxx"
+
+#endif // ifndef __se3_urdf_geom_hpp__
+
diff --git a/src/multibody/parser/urdf-with-geometry.hxx b/src/multibody/parser/urdf-with-geometry.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..a5b0703e9a7f3cd706a9b16659d16990fddd96f7
--- /dev/null
+++ b/src/multibody/parser/urdf-with-geometry.hxx
@@ -0,0 +1,147 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_urdf_geom_hxx__
+#define __se3_urdf_geom_hxx__
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+#include <iostream>
+#include <boost/foreach.hpp>
+#include "pinocchio/multibody/model.hpp"
+
+#include <hpp/fcl/collision_object.h>
+#include <hpp/fcl/collision.h>
+#include <hpp/fcl/shape/geometric_shapes.h>
+#include "pinocchio/multibody/parser/from-collada-to-fcl.hpp"
+
+#include <exception>
+
+
+namespace se3
+{
+  namespace urdf
+  {
+
+
+    inline fcl::CollisionObject retrieveCollisionGeometry (const ::urdf::LinkConstPtr & link, const std::string & meshRootDir)
+    {
+      boost::shared_ptr < ::urdf::Collision> collision = link->collision;
+      boost::shared_ptr < fcl::CollisionGeometry > geometry;
+
+      // Handle the case where collision geometry is a mesh
+      if (collision->geometry->type == ::urdf::Geometry::MESH)
+      {
+        boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (collision->geometry);
+        std::string collisionFilename = collisionGeometry->filename;
+
+        std::string full_path = fromURDFMeshPathToAbsolutePath(collisionFilename, meshRootDir);
+
+        ::urdf::Vector3 scale = collisionGeometry->scale;
+
+        // Create FCL mesh by parsing Collada file.
+        PolyhedronPtrType  polyhedron (new PolyhedronType);
+
+        loadPolyhedronFromResource (full_path, scale, polyhedron);
+        geometry = polyhedron;
+      }
+
+      if (!geometry)
+      {
+        throw std::runtime_error(std::string("The polyhedron retrived is empty"));
+      }
+      fcl::CollisionObject collisionObject (geometry, fcl::Transform3f());
+
+      return collisionObject; // TO CHECK: what happens if geometry is empty ?
+    }
+
+
+    inline void parseTreeForGeom( ::urdf::LinkConstPtr link, Model & model,GeometryModel & model_geom, const std::string & meshRootDir, const bool rootJointAdded) throw (std::invalid_argument)
+    {
+
+      // start with first link that is not empty
+      if(link->inertial)
+      {
+        ::urdf::JointConstPtr joint = link->parent_joint;
+
+        if (joint == NULL && rootJointAdded )
+        {
+          
+          if (link->collision)
+          {
+            fcl::CollisionObject collision_object = retrieveCollisionGeometry(link, meshRootDir);
+            SE3 geomPlacement = convertFromUrdf(link->collision->origin);
+            std::string collision_object_name = link->name ;
+            model_geom.addGeomObject(model.getJointId("root_joint"), collision_object, geomPlacement, collision_object_name);
+          }
+        }
+
+        if(joint!=NULL)
+        {
+          assert(link->getParent()!=NULL);
+
+          if (link->collision)
+          {
+            fcl::CollisionObject collision_object = retrieveCollisionGeometry(link, meshRootDir);
+            SE3 geomPlacement = convertFromUrdf(link->collision->origin);
+            std::string collision_object_name = link->name ;
+            model_geom.addGeomObject(model.getJointId(joint->name), collision_object, geomPlacement, collision_object_name);
+          }      
+        }
+        else if (link->getParent() != NULL)
+        {
+          const std::string exception_message (link->name + " - joint information missing.");
+          throw std::invalid_argument(exception_message);
+        }
+
+      }
+      
+      BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
+      {
+        parseTreeForGeom(child, model, model_geom, meshRootDir, rootJointAdded);
+      }
+    }
+
+
+
+    template <typename D>
+    std::pair<Model, GeometryModel > buildModelAndGeom( const std::string & filename, const std::string & meshRootDir, const JointModelBase<D> &  root_joint )
+    {
+      Model model; GeometryModel model_geom;
+
+      ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
+      parseTree(urdfTree->getRoot(), model, SE3::Identity(), root_joint);
+      parseTreeForGeom(urdfTree->getRoot(), model, model_geom, meshRootDir, true);
+      return std::make_pair(model, model_geom);
+    }
+
+    inline std::pair<Model, GeometryModel > buildModelAndGeom( const std::string & filename, const std::string & meshRootDir)
+    {
+      Model model; GeometryModel model_geom;
+
+      ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
+      parseTree(urdfTree->getRoot(), model, SE3::Identity());
+      parseTreeForGeom(urdfTree->getRoot(), model, model_geom, meshRootDir, false);
+      return std::make_pair(model, model_geom);
+    }
+
+  } // namespace urdf
+} // namespace se3
+
+#endif // ifndef __se3_urdf_geom_hxx__
+
diff --git a/src/multibody/parser/urdf.hxx b/src/multibody/parser/urdf.hxx
index de5f9a2d4e01fcf9d0dcf19339d6d0345f0b2736..ebf258f2c8bb05057b6d439cae06f2b9383b90e1 100644
--- a/src/multibody/parser/urdf.hxx
+++ b/src/multibody/parser/urdf.hxx
@@ -389,23 +389,46 @@ namespace se3
   }
   
   
-            template <typename D>
+  template <typename D>
   void parseTree (::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, const JointModelBase<D> & root_joint, const bool verbose) throw (std::invalid_argument)
   {
     if (!link->inertial)
     {
-      const std::string exception_message (link->name + " - spatial inertia information missing.");
-      throw std::invalid_argument(exception_message);
-    }
-    
-    const Inertia & Y = convertFromUrdf(*link->inertial);
-    const bool has_visual = (link->visual) ? true : false;
-    model.addBody(0, root_joint, placementOffset, Y , "root_joint", link->name, has_visual);
+      // If the root link has only one child
+      if (link->child_links.size() == 1)
+      {
+        ::urdf::LinkPtr child_link = link->child_links[0];
+        const Inertia & Y = convertFromUrdf(*child_link->inertial);
+        const bool has_visual = (child_link->visual) ? true : false;
+        model.addBody(0, root_joint, placementOffset, Y, "root_joint", child_link->name, has_visual);
+      
+        // Change the name of the parent joint
+        child_link->parent_joint->name = "root_joint";
+      
+        BOOST_FOREACH(::urdf::LinkConstPtr child, child_link->child_links)
+        {
+          parseTree(child, model, SE3::Identity(), verbose);
+        }
+      }
+      else
+      {
+        const std::string exception_message (link->name + " - spatial inertial information missing with more than one child.");
+        throw std::invalid_argument(exception_message);
+      }
     
-    BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
+    }
+    else
     {
-      parseTree(child, model, SE3::Identity(), verbose);
+      const Inertia & Y = convertFromUrdf(*link->inertial);
+      const bool has_visual = (link->visual) ? true : false;
+      model.addBody(0, root_joint, placementOffset, Y , "root_joint", link->name, has_visual);
+    
+      BOOST_FOREACH(::urdf::LinkConstPtr child, link->child_links)
+      {
+        parseTree(child, model, SE3::Identity(), verbose);
+      }
     }
+  
   }
   
   
diff --git a/src/python/algorithms.hpp b/src/python/algorithms.hpp
index c971a6cc43fa58675342afa62627d5788a2be3d3..3c62c05fee19a3e2b4cdcae9e1ce25d0dfdde435 100644
--- a/src/python/algorithms.hpp
+++ b/src/python/algorithms.hpp
@@ -34,6 +34,13 @@
 
 #include "pinocchio/simulation/compute-all-terms.hpp"
 
+#ifdef WITH_HPP_FCL
+#include "pinocchio/multibody/geometry.hpp"
+#include "pinocchio/python/geometry-model.hpp"
+#include "pinocchio/python/geometry-data.hpp"
+#include "pinocchio/algorithm/collisions.hpp"
+#endif
+
 namespace se3
 {
   namespace python
@@ -147,6 +154,39 @@ namespace se3
         jointLimits(*model,*data,q);
       }
 
+#ifdef WITH_HPP_FCL
+      static bool computeCollisions_proxy(GeometryDataHandler & data_geom,
+                                          const bool stopAtFirstCollision)
+      {
+        return computeCollisions(*data_geom, stopAtFirstCollision);
+      }
+
+      static bool computeGeometryAndCollisions_proxy(const ModelHandler & model,
+                                    DataHandler & data,
+                                    const GeometryModelHandler & model_geom,
+                                    GeometryDataHandler & data_geom,
+                                    const VectorXd_fx & q,
+                                    const bool & stopAtFirstCollision)
+      {
+        return computeCollisions(*model,*data,*model_geom, *data_geom, q, stopAtFirstCollision);
+      }
+
+      static void computeDistances_proxy(GeometryDataHandler & data_geom)
+      {
+        computeDistances(*data_geom);
+      }
+
+      static void computeGeometryAndDistances_proxy( const ModelHandler & model,
+                                    DataHandler & data,
+                                    const GeometryModelHandler & model_geom,
+                                    GeometryDataHandler & data_geom,
+                                    const Eigen::VectorXd & q
+                                    )
+      {
+        computeDistances(*model, *data, *model_geom, *data_geom, q);
+      }
+
+#endif
 
 
       /* --- Expose --------------------------------------------------------- */
@@ -236,8 +276,32 @@ namespace se3
         "Configuration q (size Model::nq)"),
         "Compute the maximum limits of all the joints of the model "
         "and put the results in data.");
-      }
 
+#ifdef WITH_HPP_FCL
+  bp::def("computeCollisions",computeCollisions_proxy,
+    bp::args("GeometryData","bool"),
+        "Determine if collisions pairs are effectively in collision."
+        );
+
+  bp::def("computeGeometryAndCollisions",computeGeometryAndCollisions_proxy,
+    bp::args("Model","Data","GeometryModel","GeometryData","Configuration q (size Model::nq)", "bool"),
+        "Update the geometry for a given configuration and"
+        "determine if collision pars are effectively in collision"
+        );
+
+  bp::def("computeDistances",computeDistances_proxy,
+    bp::args("GeometryData"),
+        "Compute the distance between each collision pairs."
+        );
+
+  bp::def("computeGeometryAndDistances",computeGeometryAndDistances_proxy,
+    bp::args("Model","Data","GeometryModel","GeometryData","Configuration q (size Model::nq)"),
+        "Update the geometry for a given configuration and"
+        "compute the distance between each collision pairs"
+        );
+
+      }
+#endif
     };
     
   }} // namespace se3::python
diff --git a/src/python/geometry-data.hpp b/src/python/geometry-data.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cf4996195edd056d444afefe5c7790fe8304eb3
--- /dev/null
+++ b/src/python/geometry-data.hpp
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_python_geometry_data_hpp__
+#define __se3_python_geometry_data_hpp__
+
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <eigenpy/exception.hpp>
+#include <eigenpy/eigenpy.hpp>
+
+// #include "pinocchio/multibody/parser/sample-models.hpp"
+#include "pinocchio/python/se3.hpp"
+#include "pinocchio/python/eigen_container.hpp"
+#include "pinocchio/python/handler.hpp"
+
+#include "pinocchio/multibody/geometry.hpp"
+
+namespace se3
+{
+  namespace python
+  {
+    namespace bp = boost::python;
+
+    typedef Handler<GeometryData> GeometryDataHandler;
+
+    struct GeometryDataPythonVisitor
+      : public boost::python::def_visitor< GeometryDataPythonVisitor >
+    {
+    public:
+      typedef GeometryData::Index Index;
+      typedef GeometryData::CollisionPair_t CollisionPair_t;
+      typedef se3::DistanceResult DistanceResult;
+      typedef eigenpy::UnalignedEquivalent<SE3>::type SE3_fx;
+      
+    public:
+
+      /* --- Convert From C++ to Python ------------------------------------- */
+      // static PyObject* convert(Model const& modelConstRef)
+      // {
+      // 	Model * ptr = const_cast<Model*>(&modelConstRef);
+      // 	return boost::python::incref(boost::python::object(ModelHandler(ptr)).ptr());
+      // }
+      static PyObject* convert(GeometryDataHandler::SmartPtr_t const& ptr)
+      {
+        return boost::python::incref(boost::python::object(GeometryDataHandler(ptr)).ptr());
+      }
+
+      /* --- Exposing C++ API to python through the handler ----------------- */
+    template<class PyClass>
+      void visit(PyClass& cl) const 
+      {
+	cl
+    .add_property("nCollisionPairs", &GeometryDataPythonVisitor::nCollisionPairs)
+
+    .add_property("oMg",
+      bp::make_function(&GeometryDataPythonVisitor::oMg,
+            bp::return_internal_reference<>())  )
+    .add_property("collision_pairs",
+      bp::make_function(&GeometryDataPythonVisitor::collision_pairs,
+            bp::return_internal_reference<>())  )
+    .add_property("distances",
+      bp::make_function(&GeometryDataPythonVisitor::distances,
+            bp::return_internal_reference<>())  )
+    .add_property("collisions",
+      bp::make_function(&GeometryDataPythonVisitor::collisions,
+            bp::return_internal_reference<>())  )
+
+    .def("addCollisionPair",&GeometryDataPythonVisitor::isCollisionPair)
+    .def("removeCollisionPair",&GeometryDataPythonVisitor::isCollisionPair)
+    .def("isCollisionPair",&GeometryDataPythonVisitor::isCollisionPair)
+    .def("collide",&GeometryDataPythonVisitor::collide)
+
+    .def("__str__",&GeometryDataPythonVisitor::toString)
+
+
+	  ;
+      }
+
+      static GeometryModel::Index nCollisionPairs( GeometryDataHandler & m ) { return m->nCollisionPairs; }
+      
+      static std::vector<SE3> & oMg( GeometryDataHandler & m ) { return m->oMg; }
+      static std::vector<CollisionPair_t> & collision_pairs( GeometryDataHandler & m ) { return m->collision_pairs; }
+      static std::vector<DistanceResult> & distances( GeometryDataHandler & m ) { return m->distances; }
+      static std::vector<bool> & collisions( GeometryDataHandler & m ) { return m->collisions; }
+
+      static void addCollisionPair (GeometryDataHandler & m, Index co1, Index co2) { m -> addCollisionPair(co1, co2);}
+      static void removeCollisionPair (GeometryDataHandler & m, Index co1, Index co2) { m -> removeCollisionPair(co1, co2);}
+      static bool isCollisionPair (const GeometryDataHandler & m, Index co1, Index co2) { return m -> isCollisionPair(co1, co2);}
+
+      static bool collide(const GeometryDataHandler & m, Index co1, Index co2) { return m -> collide(co1, co2); };
+      
+ 
+
+      static std::string toString(const GeometryDataHandler& m) 
+      {	  std::ostringstream s; s << *m; return s.str();       }
+
+      /* --- Expose --------------------------------------------------------- */
+      static void expose()
+      {
+  
+  bp::class_<GeometryDataHandler>("GeometryData",
+         "Geometry data ",
+         bp::no_init)
+    .def(GeometryDataPythonVisitor());
+
+    bp::class_< std::vector<CollisionPair_t> >("StdVec_CollisionPair_t")
+          .def(bp::vector_indexing_suite< std::vector<CollisionPair_t> >());
+    bp::class_< std::vector<DistanceResult> >("StdVec_DistanceResult")
+          .def(bp::vector_indexing_suite< std::vector<DistanceResult> >());
+      
+	/* Not sure if it is a good idea to enable automatic
+	 * conversion. Prevent it for now */
+	//bp::to_python_converter< Model,GeometryDataPythonVisitor >();
+	bp::to_python_converter< GeometryDataHandler::SmartPtr_t,GeometryDataPythonVisitor >();
+      }
+
+
+    };
+    
+
+
+  }} // namespace se3::python
+
+#endif // ifndef __se3_python_geometry_data_hpp__
+
diff --git a/src/python/geometry-model.hpp b/src/python/geometry-model.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d7396ecc5e05960c394afd4d6df1bb94794a122
--- /dev/null
+++ b/src/python/geometry-model.hpp
@@ -0,0 +1,129 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_python_geometry_model_hpp__
+#define __se3_python_geometry_model_hpp__
+
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <eigenpy/exception.hpp>
+#include <eigenpy/eigenpy.hpp>
+
+// #include "pinocchio/multibody/parser/sample-models.hpp"
+#include "pinocchio/python/se3.hpp"
+#include "pinocchio/python/eigen_container.hpp"
+#include "pinocchio/python/handler.hpp"
+
+#include "pinocchio/multibody/geometry.hpp"
+
+namespace se3
+{
+  namespace python
+  {
+    namespace bp = boost::python;
+
+    typedef Handler<GeometryModel> GeometryModelHandler;
+
+    struct GeometryModelPythonVisitor
+      : public boost::python::def_visitor< GeometryModelPythonVisitor >
+    {
+    public:
+      typedef GeometryModel::Index Index;
+      typedef eigenpy::UnalignedEquivalent<SE3>::type SE3_fx;
+      
+    public:
+
+      /* --- Convert From C++ to Python ------------------------------------- */
+      // static PyObject* convert(Model const& modelConstRef)
+      // {
+      // 	Model * ptr = const_cast<Model*>(&modelConstRef);
+      // 	return boost::python::incref(boost::python::object(ModelHandler(ptr)).ptr());
+      // }
+      static PyObject* convert(GeometryModelHandler::SmartPtr_t const& ptr)
+      {
+        return boost::python::incref(boost::python::object(GeometryModelHandler(ptr)).ptr());
+      }
+
+      /* --- Exposing C++ API to python through the handler ----------------- */
+    template<class PyClass>
+      void visit(PyClass& cl) const 
+      {
+	cl
+    .add_property("ngeom", &GeometryModelPythonVisitor::ngeom)
+
+    .def("getGeomId",&GeometryModelPythonVisitor::getGeomId)
+
+    .add_property("geometryPlacement",
+      bp::make_function(&GeometryModelPythonVisitor::geometryPlacement,
+            bp::return_internal_reference<>())  )
+    .add_property("geom_parents", 
+      bp::make_function(&GeometryModelPythonVisitor::geom_parents,
+            bp::return_internal_reference<>())  )
+    .add_property("geom_names",
+      bp::make_function(&GeometryModelPythonVisitor::geom_names,
+            bp::return_internal_reference<>())  )
+
+    .def("__str__",&GeometryModelPythonVisitor::toString)
+
+	  .def("BuildEmptyGeometryModel",&GeometryModelPythonVisitor::maker_empty)
+	  .staticmethod("BuildEmptyGeometryModel")
+	  ;
+      }
+
+      static GeometryModel::Index ngeom( GeometryModelHandler & m ) { return m->ngeom; }
+
+      static Model::Index getGeomId( const GeometryModelHandler & gmodelPtr, const std::string & name )
+      { return  gmodelPtr->getGeomId(name); }
+      
+      static std::vector<SE3> & geometryPlacement( GeometryModelHandler & m ) { return m->geometryPlacement; }
+      static std::vector<Model::Index> & geom_parents( GeometryModelHandler & m ) { return m->geom_parents; }
+      static std::vector<std::string> & geom_names ( GeometryModelHandler & m ) { return m->geom_names; }
+
+      
+
+      static GeometryModelHandler maker_empty()
+      {
+	return GeometryModelHandler( new GeometryModel(),true );
+      }
+ 
+
+      static std::string toString(const GeometryModelHandler& m) 
+      {	  std::ostringstream s; s << *m; return s.str();       }
+
+      /* --- Expose --------------------------------------------------------- */
+      static void expose()
+      {
+  
+  bp::class_<GeometryModelHandler>("GeometryModel",
+         "Geometry model (const)",
+         bp::no_init)
+    .def(GeometryModelPythonVisitor());
+      
+	/* Not sure if it is a good idea to enable automatic
+	 * conversion. Prevent it for now */
+	//bp::to_python_converter< Model,GeometryModelPythonVisitor >();
+	bp::to_python_converter< GeometryModelHandler::SmartPtr_t,GeometryModelPythonVisitor >();
+      }
+
+
+    };
+    
+
+
+  }} // namespace se3::python
+
+#endif // ifndef __se3_python_geometry_model_hpp__
+
diff --git a/src/python/parsers.hpp b/src/python/parsers.hpp
index b408a54b644972cf125600fa2ab4671a01509a1a..550f47f25be070e579f105951db0d6820118d530 100644
--- a/src/python/parsers.hpp
+++ b/src/python/parsers.hpp
@@ -26,6 +26,11 @@
 
 #ifdef WITH_URDFDOM
   #include "pinocchio/multibody/parser/urdf.hpp"
+#ifdef WITH_HPP_FCL
+  #include "pinocchio/python/geometry-model.hpp"
+  #include "pinocchio/python/geometry-data.hpp"
+  #include "pinocchio/multibody/parser/urdf-with-geometry.hpp"
+#endif
 #endif
 
 #ifdef WITH_LUA
@@ -38,6 +43,14 @@ namespace se3
   {
     struct ParsersPythonVisitor
     {
+
+      template<class T1, class T2>
+      struct PairToTupleConverter {
+        static PyObject* convert(const std::pair<T1, T2>& pair) {
+          return boost::python::incref(boost::python::make_tuple(pair.first, pair.second).ptr());
+        }
+      };
+
       
 #ifdef WITH_URDFDOM
       struct build_model_visitor : public boost::static_visitor<ModelHandler>
@@ -68,6 +81,57 @@ namespace se3
 	*model = se3::urdf::buildModel(filename);
 	return ModelHandler(model,true);
       }
+
+
+#ifdef WITH_HPP_FCL
+      struct build_model_and_geom_visitor : public boost::static_visitor<std::pair<ModelHandler, GeometryModelHandler> >
+      {
+        const std::string& _filenameUrdf;
+        const std::string& _filenameMeshRootDir;
+
+        build_model_and_geom_visitor(const std::string& filenameUrdf,
+                                     const std::string& filenameMeshRootDir): _filenameUrdf(filenameUrdf)
+                                                                            , _filenameMeshRootDir(filenameMeshRootDir)
+        {}
+
+        template <typename T> std::pair<ModelHandler, GeometryModelHandler> operator()( T & operand ) const
+        {
+
+
+          Model * model = new Model();
+          GeometryModel * geometry_model = new GeometryModel();
+          std::pair < Model, GeometryModel > models = se3::urdf::buildModelAndGeom(_filenameUrdf, _filenameMeshRootDir, operand);
+          *model = models.first;
+          *geometry_model = models.second;
+          return std::pair<ModelHandler, GeometryModelHandler> ( ModelHandler(model, true),
+                                                                 GeometryModelHandler(geometry_model, true)
+                                                               );
+        }
+      };
+
+      static std::pair<ModelHandler, GeometryModelHandler> buildModelAndGeomFromUrdfWithRoot( const std::string & filenameUrdf,
+                                                      const std::string & filenameMeshRootDir,
+                                                      bp::object o
+                                                      )
+      {
+        JointModelVariant variant = bp::extract<JointModelVariant> (o);
+        return boost::apply_visitor(build_model_and_geom_visitor(filenameUrdf, filenameMeshRootDir), variant);
+      }
+
+      static std::pair<ModelHandler, GeometryModelHandler> buildModelAndGeomFromUrdf( const std::string & filenameUrdf,
+                                                                                      const std::string & filenameMeshRootDir)
+      {
+        Model * model = new Model();
+        GeometryModel * geometry_model = new GeometryModel();
+        std::pair < Model, GeometryModel > models = se3::urdf::buildModelAndGeom(filenameUrdf, filenameMeshRootDir);
+        *model = models.first;
+        *geometry_model = models.second;
+        return std::pair<ModelHandler, GeometryModelHandler> ( ModelHandler(model, true),
+                                                               GeometryModelHandler(geometry_model, true)
+                                                             );
+      }
+#endif
+
 #endif
 
 #ifdef WITH_LUA
@@ -85,17 +149,32 @@ namespace se3
       /* --- Expose --------------------------------------------------------- */
       static void expose()
       {
+#ifdef WITH_URDFDOM
         bp::def("buildModelFromUrdfWithRoot",buildModelFromUrdfWithRoot,
           bp::args("Filename (string)",
               "Root Joint Model"),
           "Parse the urdf file given in input and return a proper pinocchio model "
           "(remember to create the corresponding data structure).");
 
-#ifdef WITH_URDFDOM
 	bp::def("buildModelFromUrdf",buildModelFromUrdf,
 		bp::args("Filename (string)"),
 		"Parse the urdf file given in input and return a proper pinocchio model "
 		"(remember to create the corresponding data structure).");
+  #ifdef WITH_HPP_FCL
+
+      bp::to_python_converter<std::pair<ModelHandler, GeometryModelHandler>, PairToTupleConverter<ModelHandler, GeometryModelHandler> >();
+
+      bp::def("buildModelAndGeomFromUrdfWithRoot",buildModelAndGeomFromUrdfWithRoot,
+          bp::args("FilenameUrdf (string)", "FilenameMeshRootDirhRootDir string) ", 
+              "Root Joint Model"),
+          "Parse the urdf file given in input and return a proper pinocchio model starting with a given root joint and geometry model "
+          "(remember to create the corresponding data structures).");
+
+      bp::def("buildModelAndGeomFromUrdf",buildModelAndGeomFromUrdf,
+          bp::args("Filename (string)"), "FilenameMeshRootDirhRootDir string) ",
+          "Parse the urdf file given in input and return a proper pinocchio model and geometry model"
+          "(remember to create the corresponding data structures).");
+  #endif
 #endif
 
 #ifdef WITH_LUA
diff --git a/src/python/python.cpp b/src/python/python.cpp
index a95464632e37c956bf978d806e97ce4ae464d15a..eddca903957f9c6fcdbc6d933f3c858721a7c6bc 100644
--- a/src/python/python.cpp
+++ b/src/python/python.cpp
@@ -30,6 +30,11 @@
 #include "pinocchio/python/parsers.hpp"
 #include "pinocchio/python/explog.hpp"
 
+#ifdef WITH_HPP_FCL
+#include "pinocchio/python/geometry-model.hpp"
+#include "pinocchio/python/geometry-data.hpp"
+#endif
+
 namespace se3
 {
   namespace python
@@ -62,6 +67,10 @@ namespace se3
     {
       ModelPythonVisitor::expose();
       DataPythonVisitor::expose();
+#ifdef WITH_HPP_FCL      
+      GeometryModelPythonVisitor::expose();
+      GeometryDataPythonVisitor::expose();
+#endif      
     }
     void exposeAlgorithms()
     {
diff --git a/src/spatial/fcl-pinocchio-conversions.hpp b/src/spatial/fcl-pinocchio-conversions.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae11ac8bf726807e991912bfbab5e2ef2a32cc8b
--- /dev/null
+++ b/src/spatial/fcl-pinocchio-conversions.hpp
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_fcl_convertion_hpp__
+#define __se3_fcl_convertion_hpp__
+
+#include <Eigen/Geometry>
+
+#include "pinocchio/spatial/se3.hpp"
+# include <hpp/fcl/math/transform.h>
+
+namespace se3
+{
+
+  inline fcl::Matrix3f toFclMatrix3f(const Eigen::Matrix3d & mat)
+  {
+    return fcl::Matrix3f( mat(0,0),mat(0,1), mat(0,2),
+                          mat(1,0),mat(1,1), mat(1,2),
+                          mat(2,0),mat(2,1), mat(2,2));
+  }
+
+  inline Eigen::Matrix3d toMatrix3d(const fcl::Matrix3f & mat)
+  {
+    Eigen::Matrix3d res;
+
+    res <<  mat(0,0),mat(0,1), mat(0,2),
+            mat(1,0),mat(1,1), mat(1,2),
+            mat(2,0),mat(2,1), mat(2,2);
+    return res;
+  }
+
+  inline fcl::Vec3f toFclVec3f(const Eigen::Vector3d & vec)
+  {
+    return fcl::Vec3f( vec(0),vec(1), vec(2));
+  }
+
+  inline Eigen::Vector3d toVector3d(const fcl::Vec3f & vec)
+  {
+    Eigen::Vector3d res;
+    res << vec[0],vec[1], vec[2];
+    return res;
+  }
+
+  fcl::Transform3f toFclTransform3f(const se3::SE3 & m)
+  {
+    return fcl::Transform3f(toFclMatrix3f(m.rotation()), toFclVec3f(m.translation()));
+  }
+
+  se3::SE3 toPinocchioSE3(const fcl::Transform3f & tf)
+  {
+    return se3::SE3(toMatrix3d(tf.getRotation()), toVector3d(tf.getTranslation()));
+  }
+
+} // namespace se3
+
+#endif // ifndef __se3_fcl_convertion_hpp__
+
diff --git a/src/spatial/inertia.hpp b/src/spatial/inertia.hpp
index 7427c62cc345d9ab9e6082db607fdafdbd8ef8d7..715ef31f83c66c47be5a12a35f595cd7aa6529a5 100644
--- a/src/spatial/inertia.hpp
+++ b/src/spatial/inertia.hpp
@@ -55,7 +55,7 @@ namespace se3
 
 
     Derived_t& operator= (const Derived_t& clone){return derived().__equl__(clone);}
-    Derived_t& operator== (const Derived_t& other){return derived().isEqual(other);}
+    bool operator== (const Derived_t& other) const {return derived().isEqual(other);}
     Derived_t& operator+= (const Derived_t & Yb) { return derived().__pequ__(Yb); }
     Derived_t operator+(const Derived_t & Yb) const { return derived().__plus__(Yb); }
     Force operator*(const Motion & v) const    { return derived().__mult__(v); }
@@ -204,7 +204,7 @@ namespace se3
     }
 
     // Requiered by std::vector boost::python bindings. 
-    bool isEqual( const InertiaTpl& Y2 ) 
+    bool isEqual( const InertiaTpl& Y2 ) const
     { 
       return (m==Y2.m) && (c==Y2.c) && (I==Y2.I);
     }
diff --git a/src/spatial/se3.hpp b/src/spatial/se3.hpp
index 9743af0ce1f6fa3441285cd6d3d5fedce9ed791b..5d5b7cd430a276e75dc3325ff3598bc04497b905 100644
--- a/src/spatial/se3.hpp
+++ b/src/spatial/se3.hpp
@@ -78,6 +78,7 @@ namespace se3
       operator Matrix6() const { return toActionMatrix(); }
 
 
+
       void disp(std::ostream & os) const
       {
         static_cast<const Derived_t*>(this)->disp_impl(os);
@@ -102,6 +103,17 @@ namespace se3
       Derived_t act   (const Derived_t& m2) const { return derived().act_impl(m2); }
       Derived_t actInv(const Derived_t& m2) const { return derived().actInv_impl(m2); }
 
+
+      bool operator == (const Derived_t & other) const
+      {
+        return derived().__equal__(other);
+      }
+
+      bool isApprox (const Derived_t & other) const
+      {
+        return derived().isApprox_impl(other);
+      }
+
       friend std::ostream & operator << (std::ostream & os,const SE3Base<Derived> & X)
       { 
         X.disp(os);
@@ -153,12 +165,19 @@ namespace se3
     {
     }
 
+    template<typename M4>
+    SE3Tpl(const Eigen::MatrixBase<M4> & m) 
+    : rot(m.template block<3,3>(LINEAR,LINEAR)), trans(m.template block<3,1>(LINEAR,ANGULAR))
+    {
+    }
+
     SE3Tpl(int) : rot(Matrix3::Identity()), trans(Vector3::Zero()) {}
 
     template<typename S2, int O2>
     SE3Tpl( const SE3Tpl<S2,O2> & clone )
     : rot(clone.rotation()),trans(clone.translation()) {}
 
+
     template<typename S2, int O2>
     SE3Tpl & operator= (const SE3Tpl<S2,O2> & other)
     {
@@ -220,6 +239,7 @@ namespace se3
       return M;
     }
 
+
     void disp_impl(std::ostream & os) const
     {
       os << "  R =\n" << rot << std::endl
@@ -249,6 +269,18 @@ namespace se3
 
     SE3Tpl __mult__(const SE3Tpl & m2) const { return this->act(m2);}
 
+    bool __equal__( const SE3Tpl & m2 ) const
+    {
+      return (rotation_impl() == m2.rotation() && translation_impl() == m2.translation());
+    }
+
+    bool isApprox_impl( const SE3Tpl & m2 ) const
+    {
+      Matrix4 diff( toHomogeneousMatrix_impl() - 
+                              m2.toHomogeneousMatrix_impl());
+      return (diff.isMuchSmallerThan(toHomogeneousMatrix_impl(), 1e-14)
+              && diff.isMuchSmallerThan(m2.toHomogeneousMatrix_impl(), 1e-14) );
+    }
 
   public:
     const Angular_t & rotation_impl() const { return rot; }
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
index 1716233faa8049cd871770d61c09a4d72355904f..088db0a40ca5277b4f962c6cee5da0edee8a32c5 100644
--- a/unittest/CMakeLists.txt
+++ b/unittest/CMakeLists.txt
@@ -61,6 +61,18 @@ IF(URDFDOM_FOUND)
 
   ADD_UNIT_TEST(value "eigen3;urdfdom")
   ADD_TEST_CFLAGS(value '-DPINOCCHIO_SOURCE_DIR=\\\"${${PROJECT_NAME}_SOURCE_DIR}\\\"')
+  IF(HPP_FCL_FOUND)
+    ADD_UNIT_TEST(geom "eigen3;urdfdom;assimp;hpp-fcl")
+    ADD_TEST_CFLAGS(geom '-DPINOCCHIO_SOURCE_DIR=\\\"${${PROJECT_NAME}_SOURCE_DIR}\\\"')
+    ADD_TEST_CFLAGS(geom "-DWITH_HPP_FCL")
+    IF(BUILD_TESTS_WITH_HPP)
+      ADD_OPTIONAL_DEPENDENCY("hpp-model-urdf")
+      IF(HPP_MODEL_URDF_FOUND)
+        PKG_CONFIG_USE_DEPENDENCY(geom hpp-model-urdf)
+        ADD_TEST_CFLAGS(geom "-DWITH_HPP_MODEL_URDF")
+      ENDIF(HPP_MODEL_URDF_FOUND)
+    ENDIF(BUILD_TESTS_WITH_HPP)
+  ENDIF(HPP_FCL_FOUND)
 ENDIF(URDFDOM_FOUND)
 
 IF(LUA5_1_FOUND)
diff --git a/unittest/geom.cpp b/unittest/geom.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4d211e9b8a470a991a34b7c845e26916c5254956
--- /dev/null
+++ b/unittest/geom.cpp
@@ -0,0 +1,526 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+/*
+ * Compare the value obtained with the RNEA with the values obtained from
+ * RBDL. The test is not complete. It only validates the RNEA for the revolute
+ * joints. The free-flyer is not tested. It should be extended to account for
+ * the free flyer and for the other algorithms.
+ *
+ * Additionnal notes: the RNEA is an algorithm that can be used to validate
+ * many others (in particular, the mass matrix (CRBA) can be numerically
+ * validated from the RNEA, then the center-of-mass jacobian can be validated
+ * from the mass matrix, etc.
+ *
+ */
+
+#include <iostream>
+#include <iomanip>
+
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/multibody/parser/sample-models.hpp"
+#include "pinocchio/algorithm/kinematics.hpp"
+#include "pinocchio/algorithm/collisions.hpp"
+#include "pinocchio/multibody/parser/urdf.hpp"
+#include "pinocchio/spatial/explog.hpp"
+
+#include "pinocchio/multibody/geometry.hpp"
+#include "pinocchio/multibody/parser/urdf-with-geometry.hpp"
+
+#include <vector>
+
+#ifdef WITH_HPP_MODEL_URDF
+#include <hpp/util/debug.hh>
+#include <hpp/model/device.hh>
+#include <hpp/model/body.hh>
+#include <hpp/model/collision-object.hh>
+#include <hpp/model/joint.hh>
+#include <hpp/model/urdf/util.hh>
+#endif
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE GeomTest
+#include <boost/test/unit_test.hpp>
+#include "pinocchio/tools/matrix-comparison.hpp"
+
+typedef std::map <std::string, se3::SE3> PositionsMap_t;
+typedef std::map <std::string, se3::SE3> JointPositionsMap_t;
+typedef std::map <std::string, se3::SE3> GeometryPositionsMap_t;
+typedef std::map <std::pair < std::string , std::string >, fcl::DistanceResult > PairDistanceMap_t;
+JointPositionsMap_t fillPinocchioJointPositions(const se3::Data & data);
+GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryData & data_geom);
+#ifdef WITH_HPP_MODEL_URDF
+JointPositionsMap_t fillHppJointPositions(const hpp::model::HumanoidRobotPtr_t robot);
+GeometryPositionsMap_t fillHppGeometryPositions(const hpp::model::HumanoidRobotPtr_t robot);
+#endif
+std::vector<std::string> getBodiesList();
+
+#ifdef WITH_HPP_MODEL_URDF
+class IsDistanceResultPair
+{
+typedef std::string string;
+public:
+IsDistanceResultPair( string body1, string body2): _body1(body1), _body2(body2){}
+
+bool operator()(hpp::model::DistanceResult dist) const
+{
+  return (dist.innerObject->name() == _body1 && dist.outerObject->name() == _body2);
+}
+private:
+string _body1;
+string _body2;
+};
+
+struct Distance_t
+{
+  Distance_t () :d_ (0), x0_ (0), y0_ (0), z0_ (0), x1_ (0), y1_ (0), z1_ (0)
+  {
+  }
+  Distance_t (double d, double x0, double y0, double z0,
+        double x1, double y1, double z1) : d_ (d),
+             x0_ (x0), y0_ (y0), z0_ (z0),
+             x1_ (x1), y1_ (y1), z1_ (z1)
+  {
+  }
+  Distance_t ( fcl::DistanceResult dr) : d_ (dr.min_distance),
+   x0_ (dr.nearest_points [0][0]), y0_ (dr.nearest_points [0][1]), z0_ (dr.nearest_points [0][2]),
+   x1_ (dr.nearest_points [1][0]), y1_ (dr.nearest_points [1][1]), z1_ (dr.nearest_points [1][2])
+  {
+  }
+  Distance_t (const Distance_t& other) :
+    d_ (other.d_), x0_ (other.x0_), y0_ (other.y0_), z0_ (other.z0_),
+    x1_ (other.x1_), y1_ (other.y1_), z1_ (other.z1_)
+  {
+  }
+  Distance_t& swap ()
+  {
+    double tmp;
+    tmp = x1_; x1_ = x0_; x0_ = tmp;
+    tmp = y1_; y1_ = y0_; y0_ = tmp;
+    tmp = z1_; z1_ = z0_; z0_ = tmp;
+    return *this;
+  }
+  void checkClose (const Distance_t& other)
+  {
+    BOOST_CHECK_MESSAGE (fabs (d_ - other.d_ ) < 1e-5, "values d are " << d_ << " and " << other.d_);
+    BOOST_CHECK_MESSAGE (fabs (x0_ - other.x0_ ) < 1e-5, "values x0 are " << x0_ << " and " << other.x0_);
+    BOOST_CHECK_MESSAGE (fabs (y0_ - other.y0_ ) < 1e-5, "values y0 are " << y0_ << " and " << other.y0_);
+    BOOST_CHECK_MESSAGE (fabs (z0_ - other.z0_ ) < 1e-5, "values z0 are " << z0_ << " and " << other.z0_);
+    BOOST_CHECK_MESSAGE (fabs (x1_ - other.x1_ ) < 1e-5, "values x1 are " << x1_ << " and " << other.x1_);
+    BOOST_CHECK_MESSAGE (fabs (y1_ - other.y1_ ) < 1e-5, "values y1 are " << y1_ << " and " << other.y1_);
+    BOOST_CHECK_MESSAGE (fabs (z1_ - other.z1_ ) < 1e-5, "values z1 are " << z1_ << " and " << other.z1_);
+  }
+  // Distance and closest points on bodies.
+  double d_, x0_, y0_, z0_, x1_, y1_, z1_;
+}; // struct Distance_t
+#endif
+std::ostream& operator<<(std::ostream& os, const std::pair < se3::Model, se3::GeometryModel >& robot)
+{
+  os << "Nb collision objects = " << robot.second.ngeom << std::endl;
+  
+  for(se3::GeometryModel::Index i=0;i<(se3::GeometryModel::Index)(robot.second.ngeom);++i)
+  {
+    os  << "Object n " << i << " : " << robot.second.geom_names[i] << ": attached to joint = " << robot.second.geom_parents[i]
+        << "=" << robot.first.getJointName(robot.second.geom_parents[i]) << std::endl;
+  }
+  return os;
+} 
+
+
+BOOST_AUTO_TEST_SUITE ( GeomTest )
+
+BOOST_AUTO_TEST_CASE ( simple_boxes )
+{
+  se3::Model model;
+  se3::GeometryModel model_geom;
+
+  se3::buildModels::collisionModel(model, model_geom);
+
+  se3::Data data(model);
+  se3::GeometryData data_geom(data, model_geom);
+
+  std::cout << "------ Model ------ " << std::endl;
+  std::cout << model;
+  std::cout << "------ Geom ------ " << std::endl;
+  std::cout << model_geom;
+  std::cout << "------ DataGeom ------ " << std::endl;
+  std::cout << data_geom;
+  assert(data_geom.collide(0,1) == true && "");
+
+  Eigen::VectorXd q(model.nq);
+  q <<  2, 0, 0,
+        0, 0, 0 ;
+
+  se3::updateCollisionGeometry(model, data, model_geom, data_geom, q, true);
+  std::cout << data_geom;
+  assert(data_geom.collide(0,1) == false && "");
+
+  q <<  0.99, 0, 0,
+        0, 0, 0 ;
+
+  se3::updateCollisionGeometry(model, data, model_geom, data_geom, q, true);
+  std::cout << data_geom;
+  assert(data_geom.collide(0,1) == true && "");
+
+  q <<  1.01, 0, 0,
+        0, 0, 0 ;
+
+  se3::updateCollisionGeometry(model, data, model_geom, data_geom, q, true);
+  std::cout << data_geom;
+  assert(data_geom.collide(0,1) == false && "");
+}
+
+BOOST_AUTO_TEST_CASE ( loading_model )
+{
+  typedef se3::Model Model;
+  typedef se3::GeometryModel GeometryModel;
+  typedef se3::Data Data;
+  typedef se3::GeometryData GeometryData;
+
+
+  std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  std::pair < Model, GeometryModel > robot = se3::urdf::buildModelAndGeom(filename, meshDir, se3::JointModelFreeFlyer());
+  std::cout << robot.first << std::endl;
+
+  Data data(robot.first);
+  GeometryData data_geom(data, robot.second);
+
+  Eigen::VectorXd q(robot.first.nq);
+  q << 0, 0, 0.840252, 0, 0, 0, 1, 0, 0, -0.3490658, 0.6981317, -0.3490658, 0, 0, 0, -0.3490658,
+       0.6981317, -0.3490658, 0, 0, 1.5, 0.6, -0.5, -1.05, -0.4, -0.3, -0.2, 0, 0, 0, 0,
+       1.5, -0.6, 0.5, 1.05, -0.4, -0.3, -0.2 ;
+
+  se3::updateCollisionGeometry(robot.first, data, robot.second, data_geom, q, true);
+
+  assert(data_geom.collide(1,10) == false && "");
+}
+
+#ifdef WITH_HPP_MODEL_URDF
+BOOST_AUTO_TEST_CASE ( hrp2_joints_meshes_positions )
+{
+  typedef se3::Model Model;
+  typedef se3::GeometryModel GeometryModel;
+  typedef se3::Data Data;
+  typedef se3::GeometryData GeometryData;
+  using hpp::model::Device;
+  using hpp::model::Joint;
+  using hpp::model::Body;
+  typedef hpp::model::ObjectVector_t ObjectVector_t;
+  typedef hpp::model::JointVector_t JointVector_t;
+  typedef std::vector<double> vector_t;
+
+
+
+  /// **********  Pinocchio  ********** /// 
+  /// ********************************* ///
+
+  // Building the model in pinocchio and compute kinematics/geometry for configuration q_pino
+  std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  std::pair < Model, GeometryModel > robot = se3::urdf::buildModelAndGeom(filename, meshDir, se3::JointModelFreeFlyer());
+
+  Data data(robot.first);
+  GeometryData data_geom(data, robot.second);
+
+  // Configuration to be tested
+  
+
+  Eigen::VectorXd q_pino(Eigen::VectorXd::Random(robot.first.nq));
+  q_pino.segment<4>(3) /= q_pino.segment<4>(3).norm();
+
+  Eigen::VectorXd q_hpp(q_pino);
+  Eigen::Vector4d quaternion;
+  quaternion <<  q_pino[6], q_pino[3], q_pino[4], q_pino[5];
+  q_hpp.segment<4>(3) = quaternion ;
+
+
+  assert(q_pino.size() == robot.first.nq && "wrong config size");
+
+  se3::updateCollisionGeometry(robot.first, data, robot.second, data_geom, q_pino, true);
+
+
+  /// *************  HPP  ************* /// 
+  /// ********************************* ///
+
+
+  hpp::model::HumanoidRobotPtr_t humanoidRobot =
+    hpp::model::HumanoidRobot::create ("romeo");
+  hpp::model::urdf::loadHumanoidModel(humanoidRobot, "freeflyer",
+              "romeo_pinocchio", "romeo",
+              "", "");
+
+
+  assert(robot.first.nq == humanoidRobot->configSize () && "Pinocchio model & HPP model config sizes are not the same ");
+
+  humanoidRobot->currentConfiguration (q_hpp);
+  humanoidRobot->computeForwardKinematics ();
+
+
+
+  /// **********  COMPARISON  ********* /// 
+  /// ********************************* ///
+  // retrieve all joint and geometry objects positions
+  JointPositionsMap_t joints_pin  = fillPinocchioJointPositions(data);
+  JointPositionsMap_t joints_hpp  = fillHppJointPositions(humanoidRobot);
+  GeometryPositionsMap_t geom_pin = fillPinocchioGeometryPositions(data_geom);
+  GeometryPositionsMap_t geom_hpp = fillHppGeometryPositions(humanoidRobot);
+
+
+  std::map <std::string, se3::SE3>::iterator it_hpp;
+  std::map <std::string, se3::SE3>::iterator it_pin;
+
+  // Comparing position of joints
+  se3::SE3 ff_pin = joints_pin["root_joint"];
+  se3::SE3 ff_hpp = joints_hpp["base_joint_SO3"];
+  assert( ff_pin.isApprox(ff_hpp) && "ff_hpp and ff_pin are not ==");
+
+  for (it_pin = joints_pin.begin(); it_pin != joints_pin.end();
+        ++it_pin)
+  {
+    it_hpp = joints_hpp.find(it_pin->first);
+    if (it_hpp != joints_hpp.end())
+    {
+      assert(it_pin->second.isApprox(it_hpp->second) && "joint positions are not equal");
+      // se3::Motion nu = se3::log6(it_pin->second.inverse() * it_hpp->second);
+    }
+  }
+
+  // Comparing position of geometry objects
+  for (it_pin = geom_pin.begin(); it_pin != geom_pin.end();
+        ++it_pin)
+  {
+    it_hpp = geom_hpp.find(it_pin->first);
+    if (it_hpp != joints_hpp.end())
+    {
+      assert(it_pin->second.isApprox(it_hpp->second) && "geometry objects positions are not equal");
+    }
+  }
+
+
+}
+
+
+BOOST_AUTO_TEST_CASE ( hrp2_mesh_distance)
+{
+  typedef se3::Model Model;
+  typedef se3::GeometryModel GeometryModel;
+  typedef se3::Data Data;
+  typedef se3::GeometryData GeometryData;
+  using hpp::model::Device;
+  using hpp::model::Joint;
+  using hpp::model::Body;
+  typedef hpp::model::ObjectVector_t ObjectVector_t;
+  typedef hpp::model::JointVector_t JointVector_t;
+  typedef std::vector<double> vector_t;
+
+
+
+  /// **********  Pinocchio  ********** /// 
+  /// ********************************* ///
+
+  // Building the model in pinocchio and compute kinematics/geometry for configuration q_pino
+  std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  std::pair < Model, GeometryModel > robot = se3::urdf::buildModelAndGeom(filename, meshDir, se3::JointModelFreeFlyer());
+
+  Data data(robot.first);
+  GeometryData data_geom(data, robot.second);
+
+  // Configuration to be tested
+  
+
+  Eigen::VectorXd q_pino(Eigen::VectorXd::Random(robot.first.nq));
+  q_pino.segment<4>(3) /= q_pino.segment<4>(3).norm();
+
+  Eigen::VectorXd q_hpp(q_pino);
+  Eigen::Vector4d quaternion;
+  quaternion <<  q_pino[6], q_pino[3], q_pino[4], q_pino[5];
+  q_hpp.segment<4>(3) = quaternion ;
+
+
+  assert(q_pino.size() == robot.first.nq && "wrong config size");
+
+  se3::updateCollisionGeometry(robot.first, data, robot.second, data_geom, q_pino, true);
+
+
+  /// *************  HPP  ************* /// 
+  /// ********************************* ///
+
+
+  hpp::model::HumanoidRobotPtr_t humanoidRobot =
+    hpp::model::HumanoidRobot::create ("romeo");
+  hpp::model::urdf::loadHumanoidModel(humanoidRobot, "freeflyer",
+              "romeo_pinocchio", "romeo",
+              "", "");
+
+
+  assert(robot.first.nq == humanoidRobot->configSize () && "Pinocchio model & HPP model config sizes are not the same ");
+
+  humanoidRobot->currentConfiguration (q_hpp);
+  humanoidRobot->computeForwardKinematics ();
+
+
+  humanoidRobot->computeDistances ();
+
+  /// **********  COMPARISON  ********* /// 
+  /// ********************************* ///
+
+  const hpp::model::DistanceResults_t& distances(humanoidRobot->distanceResults ());
+  std::vector<std::string> bodies = getBodiesList();
+
+  for (std::vector<std::string>::iterator i = bodies.begin(); i != bodies.end(); ++i)
+  {
+    for (std::vector<std::string>::iterator j = bodies.begin(); j != bodies.end(); ++j)
+    {
+      std::string body1 (*i); std::string inner1(body1 + "_0");
+      std::string body2 (*j); std::string inner2(body2 + "_0");
+      hpp::model::DistanceResults_t::const_iterator it = std::find_if ( distances.begin(),
+                                                                    distances.end(),
+                                                                    IsDistanceResultPair(inner1, inner2)
+                                                                    );
+      if(it != distances .end())
+      {
+        Distance_t distance_hpp(it->fcl);
+
+
+        std::cout << "comparison between " << body1 << " and " << body2 << std::endl;
+
+        fcl::DistanceResult dist_pin = data_geom.computeDistance( robot.second.getGeomId(body1),
+                                                                  robot.second.getGeomId(body2));
+
+        Distance_t distance_pin ( dist_pin);
+        distance_hpp.checkClose(distance_pin);
+      }
+    }
+  }
+
+}
+#endif
+BOOST_AUTO_TEST_SUITE_END ()
+
+JointPositionsMap_t fillPinocchioJointPositions(const se3::Data & data)
+{
+  JointPositionsMap_t result;
+  for (int i = 0; i < data.model.nbody; ++i)
+  {
+    result[data.model.getJointName(i)] = data.oMi[i];
+  }
+  return result;
+}
+
+GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryData & data_geom)
+{
+  GeometryPositionsMap_t result;
+  for (std::size_t i = 0; i < data_geom.model_geom.ngeom ; ++i)
+  {
+    result[data_geom.model_geom.getGeomName(i)] = data_geom.oMg[i];
+  }
+  return result;
+}
+
+#ifdef WITH_HPP_MODEL_URDF
+JointPositionsMap_t fillHppJointPositions(const hpp::model::HumanoidRobotPtr_t robot)
+{
+  JointPositionsMap_t result;
+  const hpp::model::JointVector_t& joints(robot->getJointVector ());
+  
+  for (hpp::model::JointVector_t::const_iterator it = joints.begin (); it != joints.end (); ++it)
+  {
+    if((*it)->configSize() != 0) // Retrieving joints that are not anchors
+    {
+      result[(*it)->name()] = se3::toPinocchioSE3((*it)->currentTransformation() * (*it)->linkInJointFrame());
+    }
+  }
+  return result;  
+
+}
+
+GeometryPositionsMap_t fillHppGeometryPositions(const hpp::model::HumanoidRobotPtr_t robot)
+{
+  GeometryPositionsMap_t result;
+
+  const hpp::model::JointVector_t& joints(robot->getJointVector ());
+  // retrieving only the positions of link that have collision geometry
+  for (hpp::model::JointVector_t::const_iterator it = joints.begin (); it != joints.end (); ++it)
+  {
+    if((*it)->configSize() != 0) // Retrieving body attached to joints that are not anchors
+    {
+      hpp::model::BodyPtr_t body = (*it)->linkedBody ();
+      if(body)
+      {
+        const hpp::model::ObjectVector_t& ov (body->innerObjects (hpp::model::COLLISION));
+        for (hpp::model::ObjectVector_t::const_iterator itObj = ov.begin ();itObj != ov.end (); itObj ++)
+        {
+          result[body->name()] = se3::toPinocchioSE3((*itObj)->fcl ()->getTransform ());
+        }
+      }
+    }
+  }
+
+  return result;
+}
+
+#endif
+
+std::vector<std::string> getBodiesList()
+{
+  std::vector<std::string> result;
+
+  result.push_back( "CHEST_LINK0");
+  result.push_back( "torso");
+  result.push_back( "HEAD_LINK0");
+  result.push_back( "HEAD_LINK1");
+  result.push_back( "LARM_LINK0");
+  result.push_back( "LARM_LINK1");
+  result.push_back( "LARM_LINK2");
+  result.push_back( "LARM_LINK3");
+  result.push_back( "LARM_LINK4");
+  result.push_back( "l_wrist");
+  result.push_back( "LARM_LINK6");
+  result.push_back( "LHAND_LINK0");
+  result.push_back( "LHAND_LINK1");
+  result.push_back( "LHAND_LINK2");
+  result.push_back( "LHAND_LINK3");
+  result.push_back( "LHAND_LINK4");
+  result.push_back( "RARM_LINK0");
+  result.push_back( "RARM_LINK1");
+  result.push_back( "RARM_LINK2");
+  result.push_back( "RARM_LINK3");
+  result.push_back( "RARM_LINK4");
+  result.push_back( "r_wrist");
+  result.push_back( "RARM_LINK6");
+  result.push_back( "RHAND_LINK0");
+  result.push_back( "RHAND_LINK1");
+  result.push_back( "RHAND_LINK2");
+  result.push_back( "RHAND_LINK3");
+  result.push_back( "RHAND_LINK4");
+  result.push_back( "LLEG_LINK0");
+  result.push_back( "LLEG_LINK1");
+  result.push_back( "LLEG_LINK2");
+  result.push_back( "LLEG_LINK3");
+  result.push_back( "LLEG_LINK4");
+  result.push_back( "l_ankle");
+  result.push_back( "RLEG_LINK0");
+  result.push_back( "RLEG_LINK1");
+  result.push_back( "RLEG_LINK2");
+  result.push_back( "RLEG_LINK3");
+  result.push_back( "RLEG_LINK4");
+  result.push_back( "r_ankle");
+
+  return result;
+}