diff --git a/CMakeLists.txt b/CMakeLists.txt
index fdfa254a8af06fe498c333785777ff966048d377..55f00d742fad6752985f3b4b2cdb458aa59d661b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,6 +118,7 @@ SET(${PROJECT_NAME}_MATH_HEADERS
   math/fwd.hpp
   math/sincos.hpp
   math/quaternion.hpp
+  math/matrix.hpp
   )
 
 SET(${PROJECT_NAME}_TOOLS_HEADERS
@@ -156,6 +157,7 @@ SET(${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS
   multibody/joint/joint.hpp
   multibody/joint/joint-basic-visitors.hpp
   multibody/joint/joint-basic-visitors.hxx
+  multibody/joint/joint-composite.hpp
   ) 
 
 SET(${PROJECT_NAME}_MULTIBODY_HEADERS
diff --git a/benchmark/timings-geometry.cpp b/benchmark/timings-geometry.cpp
index c34ccea678c75405a19981f24624730fdcbe12df..955d165566093dff9cd37dbd3c7fb7f84c82bd43 100644
--- a/benchmark/timings-geometry.cpp
+++ b/benchmark/timings-geometry.cpp
@@ -70,8 +70,9 @@ int main()
   std::string romeo_meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
   package_dirs.push_back(romeo_meshDir);
 
-  se3::Model model = se3::urdf::buildModel(romeo_filename, se3::JointModelFreeFlyer());
-  se3::GeometryModel geom_model = se3::urdf::buildGeom(model, romeo_filename, package_dirs, COLLISION);
+  se3::Model model;
+  se3::urdf::buildModel(romeo_filename, se3::JointModelFreeFlyer(),model);
+  se3::GeometryModel geom_model; se3::urdf::buildGeom(model, romeo_filename, COLLISION, geom_model, package_dirs);
 #ifdef WITH_HPP_FCL  
   geom_model.addAllCollisionPairs();
 #endif // WITH_HPP_FCL
@@ -113,7 +114,7 @@ int main()
     updateGeometryPlacements(model,data,geom_model,geom_data,qs_romeo[_smooth]);
     for (std::vector<se3::CollisionPair>::iterator it = geom_model.collisionPairs.begin(); it != geom_model.collisionPairs.end(); ++it)
     {
-      geom_data.computeCollision(*it);
+      computeCollision(geom_model,geom_data,std::size_t(it-geom_model.collisionPairs.begin()));
     }
   }
   double collideTime = timer.toc(StackTicToc::US)/NBT - (update_col_time + geom_time);
@@ -124,7 +125,7 @@ int main()
   timer.tic();
   SMOOTH(NBT)
   {
-    computeCollisions(model,data,geom_model,geom_data,qs_romeo[_smooth], true);
+    computeCollisions(geom_model,geom_data, 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
@@ -203,7 +204,7 @@ hpp::model::HumanoidRobotPtr_t humanoidRobot =
   timer.tic();
   SMOOTH(NBT)
   {
-    computeCollisions(geom_data, true);
+    computeCollisions(geom_model, geom_data, 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
@@ -244,7 +245,7 @@ hpp::model::HumanoidRobotPtr_t humanoidRobot =
   timer.tic();
   SMOOTH(NBD)
   {
-    computeDistances(geom_data);
+    computeDistances(geom_model, geom_data);
   }
   computeDistancesTime = timer.toc(StackTicToc::US)/NBD ;
   std::cout << "Pinocchio - Compute distances (D) " << geom_model.collisionPairs.size() << " col pairs\t" << computeDistancesTime 
diff --git a/benchmark/timings.cpp b/benchmark/timings.cpp
index 55107238d6486981a4fc714c62cdbc344d601c14..d52031052ae1deffc9547c0842318bf09f5f71af 100644
--- a/benchmark/timings.cpp
+++ b/benchmark/timings.cpp
@@ -59,7 +59,7 @@ int main(int argc, const char ** argv)
   else if( filename == "H2" )
     se3::buildModels::humanoid2d(model);
   else
-    model = se3::urdf::buildModel(filename,JointModelFreeFlyer());
+    se3::urdf::buildModel(filename,JointModelFreeFlyer(),model);
   std::cout << "nq = " << model.nq << std::endl;
 
   se3::Data data(model);
diff --git a/bindings/python/algorithm/expose-geometry.cpp b/bindings/python/algorithm/expose-geometry.cpp
index dadf7c06c3b06f5778ed0f0eb6a2ac136034e6de..ff4fc77fad637a03a1566ef945938fbeea818609 100644
--- a/bindings/python/algorithm/expose-geometry.cpp
+++ b/bindings/python/algorithm/expose-geometry.cpp
@@ -36,11 +36,20 @@ namespace se3
       return updateGeometryPlacements(*model, *data, *geom_model, *geom_data, q);
     }
 
-#ifdef WITH_HPP_FCL    
-    static bool computeCollisions_proxy(GeometryDataHandler & data_geom,
+#ifdef WITH_HPP_FCL   
+
+    static bool computeCollision_proxy(const GeometryModelHandler & model_geom,
+                                       GeometryDataHandler & data_geom,
+                                       const PairIndex & pairId)
+    {
+      return computeCollision(*model_geom, *data_geom, pairId);
+    }
+
+    static bool computeCollisions_proxy(const GeometryModelHandler & model_geom,
+                                        GeometryDataHandler & data_geom,
                                         const bool stopAtFirstCollision)
     {
-      return computeCollisions(*data_geom, stopAtFirstCollision);
+      return computeCollisions(*model_geom, *data_geom, stopAtFirstCollision);
     }
     
     static bool computeGeometryAndCollisions_proxy(const ModelHandler & model,
@@ -53,20 +62,29 @@ namespace se3
       return computeCollisions(*model,*data,*model_geom, *data_geom, q, stopAtFirstCollision);
     }
     
-    static void computeDistances_proxy(GeometryDataHandler & data_geom)
+    static fcl::DistanceResult computeDistance_proxy(const GeometryModelHandler & model_geom,
+                                                     GeometryDataHandler & data_geom,
+                                                     const PairIndex & pairId)
+    {
+      return computeDistance(*model_geom, *data_geom, pairId);
+    }
+
+    static std::size_t computeDistances_proxy(const GeometryModelHandler & model_geom,
+                                              GeometryDataHandler & data_geom)
     {
-      computeDistances(*data_geom);
+      return computeDistances(*model_geom, *data_geom);
     }
     
-    static void computeGeometryAndDistances_proxy(const ModelHandler & model,
-                                                  DataHandler & data,
-                                                  const GeometryModelHandler & model_geom,
-                                                  GeometryDataHandler & data_geom,
-                                                  const Eigen::VectorXd & q
-                                                  )
+    static std::size_t 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);
+      return computeDistances<true>(*model, *data, *model_geom, *data_geom, q);
     }
+
 #endif // WITH_HPP_FCL
 
     void exposeGeometryAlgo()
@@ -78,6 +96,12 @@ namespace se3
               );
       
 #ifdef WITH_HPP_FCL       
+      bp::def("computeCollision", computeCollision_proxy,
+              bp::args("GoometryModel", "GeometryData", "pairIndex"),
+              "Check if the collision objects of a collision pair for a given Geometry Model and Data are in collision."
+             "The collision pair is given by the two index of the collision objects."
+              );
+
       bp::def("computeCollisions",computeCollisions_proxy,
               bp::args("GeometryData","bool"),
               "Determine if collision pairs are effectively in collision."
@@ -89,9 +113,14 @@ namespace se3
               "determine if all collision pairs are effectively in collision or not."
               );
       
+      bp::def("computeDistance",computeDistance_proxy,
+              bp::args("GeometryModel","GeometryData", "pairIndex"),
+              "Compute the distance between the two geometry objects of a given collision pair for a GeometryModel and associated GeometryData."
+              );
+
       bp::def("computeDistances",computeDistances_proxy,
-              bp::args("GeometryData"),
-              "Compute the distance between each collision pair."
+              bp::args("GeometryModel","GeometryData"),
+              "Compute the distance between each collision pair for a given GeometryModel and associated GeometryData."
               );
       
       bp::def("computeGeometryAndDistances",computeGeometryAndDistances_proxy,
diff --git a/bindings/python/algorithm/expose-joints.cpp b/bindings/python/algorithm/expose-joints.cpp
index 54023c1959ecf7d4d2bb294394a1df8a466fa9fd..0c4179b72b326d2c79db0e2857ce517b7a81fc6e 100644
--- a/bindings/python/algorithm/expose-joints.cpp
+++ b/bindings/python/algorithm/expose-joints.cpp
@@ -57,6 +57,21 @@ namespace se3
     {
       return randomConfiguration(*model, lowerPosLimit, upperPosLimit);
     }
+
+    static void normalize_proxy(const ModelHandler & model,
+                                VectorXd_fx & config)
+    {
+      Eigen::VectorXd q(config);
+      normalize(*model, q);
+      config = q;
+    }
+
+    static bool isSameConfiguration_proxy(const ModelHandler & model,
+                                          const VectorXd_fx & q1,
+                                          const VectorXd_fx & q2)
+    {
+      return isSameConfiguration(*model, q1, q2);
+    }
     
     void exposeJointsAlgo()
     {
@@ -88,6 +103,15 @@ namespace se3
                        "Joint lower limits (size Model::nq)",
                        "Joint upper limits (size Model::nq)"),
               "Generate a random configuration ensuring provied joint limits are respected ");
+      bp::def("normalize",normalize_proxy,
+              bp::args("Model",
+                       "Configuration q (size Model::nq)"),
+              "return the configuration normalized ");
+      bp::def("isSameConfiguration",isSameConfiguration_proxy,
+              bp::args("Model",
+                       "Configuration q1 (size Model::nq)",
+                       "Configuration q2 (size Model::nq)"),
+              "Return true if two configurations are equivalent");
     }
     
   } // namespace python
diff --git a/bindings/python/force.hpp b/bindings/python/force.hpp
index 52852ff0dadc4b0549fe127c1bb168d1331b1603..5e29e6cc7c71657a4e108ed345056f8ff91e30b4 100644
--- a/bindings/python/force.hpp
+++ b/bindings/python/force.hpp
@@ -85,6 +85,7 @@ namespace se3
         
         .def("__add__",&ForcePythonVisitor::add)
         .def("__sub__",&ForcePythonVisitor::subst)
+        .def("__neg__",&ForcePythonVisitor::neg)
         .def(bp::self_ns::str(bp::self_ns::self))
         .def(bp::self_ns::repr(bp::self_ns::self))
         
@@ -108,6 +109,7 @@ namespace se3
       
       static Force_fx add(const Force_fx & f1, const Force_fx & f2) { return f1+f2; }
       static Force_fx subst(const Force_fx & f1, const Force_fx & f2) { return f1-f2; }
+      static Force_fx neg(const Force_fx & f1) { return -f1; }
 
       static void expose()
       {
diff --git a/bindings/python/frame.hpp b/bindings/python/frame.hpp
index 4a1984655d6f62de1273da245ddd5c4512756d1c..c255ef3b349218c80d1c4c600f55af270675fec5 100644
--- a/bindings/python/frame.hpp
+++ b/bindings/python/frame.hpp
@@ -52,16 +52,20 @@ namespace se3
       void visit(PyClass& cl) const 
       {
         cl
-          .def(bp::init< const std::string&,const JointIndex, const SE3_fx&,FrameType> ((bp::arg("name (string)"),bp::arg("parent (index)"), bp::arg("SE3 placement"), bp::arg("type (FrameType)")),
-                "Initialize from name, parent id and placement wrt parent joint."))
+          .def(bp::init< const std::string&,const JointIndex, const FrameIndex, const SE3_fx&,FrameType> ((bp::arg("name (string)"),bp::arg("index of parent joint"), bp::args("index of parent frame"), bp::arg("SE3 placement"), bp::arg("type (FrameType)")),
+                "Initialize from name, parent joint id, parent frame id and placement wrt parent joint."))
 
           .def_readwrite("name", &Frame::name, "name  of the frame")
           .def_readwrite("parent", &Frame::parent, "id of the parent joint")
+          .def_readwrite("previousFrame", &Frame::previousFrame, "id of the previous frame") 
           .add_property("placement", 
                         &FramePythonVisitor::getPlacementWrtParentJoint, 
                         &FramePythonVisitor::setPlacementWrtParentJoint, 
                         "placement in the parent joint local frame")
           .def_readwrite("type", &Frame::type, "type of the frame")
+
+          .def(bp::self_ns::str(bp::self_ns::self))
+          .def(bp::self_ns::repr(bp::self_ns::self))
           ;
       }
 
diff --git a/bindings/python/geometry-data.hpp b/bindings/python/geometry-data.hpp
index e8b380f0d57c62ce643d4ce64cbbe18cd0f752bd..b95ec75734b8d569db046cb6dcc1443c77cd5801 100644
--- a/bindings/python/geometry-data.hpp
+++ b/bindings/python/geometry-data.hpp
@@ -28,6 +28,20 @@
 #include "pinocchio/bindings/python/data.hpp"
 #include "pinocchio/bindings/python/geometry-model.hpp"
 
+namespace fcl
+{
+  // This operator is defined here temporary, as it is needed by vector_indexing_suite
+  // It has also been defined in hpp-fcl in a pending pull request.
+  // Once it has been integrated in releases of hpp-fcl, please remove this operator
+  inline bool operator ==(const DistanceResult & dr1, const DistanceResult& dr2)
+  {
+    return dr1.min_distance == dr2.min_distance
+        && dr1.o1 == dr2.o1
+        && dr1.o2 == dr2.o2
+        && dr1.nearest_points[0] == dr2.nearest_points[0]
+        && dr1.nearest_points[1] == dr2.nearest_points[1];
+  }
+}
 namespace se3
 {
   namespace python
@@ -96,18 +110,33 @@ namespace se3
                       bp::make_function(&GeometryDataPythonVisitor::oMg,
                                         bp::return_internal_reference<>()),
                       "Vector of collision objects placement relative to the world.")
-#ifdef WITH_HPP_FCL        
-        .add_property("distance_results",
-                      bp::make_function(&GeometryDataPythonVisitor::distance_results,
+#ifdef WITH_HPP_FCL
+        .add_property("activeCollisionPairs",
+                      bp::make_function(&GeometryDataPythonVisitor::activeCollisionPairs,
+                                        bp::return_internal_reference<>()))
+        .add_property("distanceRequest",
+                      bp::make_function(&GeometryDataPythonVisitor::distanceRequest,
+                                        bp::return_internal_reference<>()),
+                      "Defines what information should be computed by fcl for distances")
+        .add_property("distanceResults",
+                      bp::make_function(&GeometryDataPythonVisitor::distanceResults,
                                         bp::return_internal_reference<>()),
                       "Vector of distance results computed in ")
+        .add_property("CollisionRequest",
+                      bp::make_function(&GeometryDataPythonVisitor::CollisionRequest,
+                                        bp::return_internal_reference<>()),
+                      "Defines what information should be computed by fcl for collision tests")
         .add_property("collision_results",
                       bp::make_function(&GeometryDataPythonVisitor::collision_results,
                                         bp::return_internal_reference<>())  )
-        .add_property("activeCollisionPairs",
-                      bp::make_function(&GeometryDataPythonVisitor::activeCollisionPairs,
-                                        bp::return_internal_reference<>()))
+        .add_property("radius",
+                      bp::make_function(&GeometryDataPythonVisitor::radius,
+                                        bp::return_internal_reference<>()),
+                      "Vector of radius of bodies, ie distance of the further point of the geometry object from the joint center ")
         
+        .def("fillInnerOuterObjectMaps", &GeometryDataPythonVisitor::fillInnerOuterObjectMaps,
+             bp::args("GeometryModel"),
+             "Fill inner and outer objects maps")
         .def("activateCollisionPair",&GeometryDataPythonVisitor::activateCollisionPair,
              bp::args("pairIndex (int)"),
              "Activate pair ID <pairIndex> in geomModel.collisionPairs."
@@ -116,23 +145,6 @@ namespace se3
              bp::args("pairIndex (int)"),
              "Deactivate pair ID <pairIndex> in geomModel.collisionPairs.")
 
-        .def("computeCollision",&GeometryDataPythonVisitor::computeCollision,
-             bp::args("co1 (index)","co2 (index)"),
-             "Check if the two collision objects of a collision pair are in collision."
-             "The collision pair is given by the two index of the collision objects.")
-        .def("computeAllCollisions",&GeometryDataPythonVisitor::computeAllCollisions,
-             "Same as computeCollision. It applies computeCollision to all collision pairs contained collision_pairs."
-             "The results are stored in collision_results.")
-        .def("isColliding",&GeometryDataPythonVisitor::isColliding,
-             "Check if at least one of the collision pairs is in collision.")
-        
-        .def("computeDistance",&GeometryDataPythonVisitor::computeDistance,
-             bp::args("co1 (index)","co2 (index)"),
-             "Compute the distance result between two collision objects of a collision pair."
-             "The collision pair is given by the two index of the collision objects.")
-        .def("computeAllDistances",&GeometryDataPythonVisitor::computeAllDistances,
-             "Same as computeDistance. It applies computeDistance to all collision pairs contained collision_pairs."
-             "The results are stored in collision_distances.")
 #endif // WITH_HPP_FCL        
         .def("__str__",&GeometryDataPythonVisitor::toString)
         ;
@@ -145,25 +157,21 @@ namespace se3
 
       static std::vector<SE3> & oMg(GeometryDataHandler & m) { return m->oMg; }
 #ifdef WITH_HPP_FCL      
-      static std::vector<DistanceResult> & distance_results( GeometryDataHandler & m ) { return m->distance_results; }
-      static std::vector<CollisionResult> & collision_results( GeometryDataHandler & m ) { return m->collision_results; }
       static std::vector<bool> & activeCollisionPairs(GeometryDataHandler & m) { return m->activeCollisionPairs; }
-      static CollisionResult computeCollision(const GeometryDataHandler & m, const GeomIndex co1, const GeomIndex co2)
-      {
-        return m->computeCollision(CollisionPair(co1, co2));
-      }
-      static bool isColliding(const GeometryDataHandler & m) { return m->isColliding(); }
-      static void computeAllCollisions(GeometryDataHandler & m) { m->computeAllCollisions(); }
+      static fcl::DistanceRequest & distanceRequest( GeometryDataHandler & m ) { return m->distanceRequest; }
+      static std::vector<fcl::DistanceResult> & distanceResults( GeometryDataHandler & m ) { return m->distanceResults; }
+      static fcl::CollisionRequest & CollisionRequest( GeometryDataHandler & m ) { return m->collisionRequest; } 
+      static std::vector<fcl::CollisionResult> & collision_results( GeometryDataHandler & m ) { return m->collisionResults; }
+      static std::vector<double> & radius( GeometryDataHandler & m ) { return m->radius; }
+
+      static void fillInnerOuterObjectMaps(GeometryDataHandler & m, const GeometryModelHandler & model)
+      {m->fillInnerOuterObjectMaps(*model);}
+
       static void activateCollisionPair(GeometryDataHandler & m,
                                         Index pairID) { m->activateCollisionPair(pairID); } 
       static void deactivateCollisionPair(GeometryDataHandler & m,
                                           Index pairID) { m->deactivateCollisionPair(pairID); } 
       
-      static DistanceResult computeDistance(const GeometryDataHandler & m, const GeomIndex co1, const GeomIndex co2)
-      {
-        return m->computeDistance(CollisionPair(co1, co2));
-      }
-      static void computeAllDistances(GeometryDataHandler & m) { m->computeAllDistances(); }
 #endif // WITH_HPP_FCL      
       
       static std::string toString(const GeometryDataHandler& m)
@@ -173,11 +181,11 @@ namespace se3
       static void expose()
       {
 #ifdef WITH_HPP_FCL        
-        bp::class_< std::vector<DistanceResult> >("StdVec_DistanceResult")
-        .def(bp::vector_indexing_suite< std::vector<DistanceResult> >());
+        bp::class_< std::vector<fcl::DistanceResult> >("StdVec_DistanceResult")
+        .def(bp::vector_indexing_suite< std::vector<fcl::DistanceResult> >());
   
-        bp::class_< std::vector<CollisionResult> >("StdVec_CollisionResult")
-        .def(bp::vector_indexing_suite< std::vector<CollisionResult> >());
+        bp::class_< std::vector<fcl::CollisionResult> >("StdVec_CollisionResult")
+        .def(bp::vector_indexing_suite< std::vector<fcl::CollisionResult> >());
 #endif // WITH_HPP_FCL
         bp::class_<GeometryDataHandler>("GeometryData",
                                         "Geometry data linked to a geometry model and data struct.",
diff --git a/bindings/python/geometry-model.hpp b/bindings/python/geometry-model.hpp
index 1dcc106a5d79ded02491bef4c205ec229b3eb7c9..7fa8a1ece64c6ce96ca1cf074b6d590ed1a07ce5 100644
--- a/bindings/python/geometry-model.hpp
+++ b/bindings/python/geometry-model.hpp
@@ -28,6 +28,8 @@
 
 #include "pinocchio/multibody/geometry.hpp"
 
+#include "pinocchio/bindings/python/model.hpp"
+
 namespace se3
 {
   namespace python
@@ -62,17 +64,19 @@ namespace se3
       {
 	cl
           .add_property("ngeoms", &GeometryModelPythonVisitor::ngeoms)
-
-          .def("getGeometryId",&GeometryModelPythonVisitor::getGeometryId)
-          .def("existGeometryName",&GeometryModelPythonVisitor::existGeometryName)
-          .def("getGeometryName",&GeometryModelPythonVisitor::getGeometryName)
           .add_property("geometryObjects",
                         bp::make_function(&GeometryModelPythonVisitor::geometryObjects,
                                           bp::return_internal_reference<>())  )
+
+          .def("addGeometryObject", &GeometryModelPythonVisitor::addGeometryObject,
+               bp::args("GeometryObject", "Model", "bool"),
+               "Add a GeometryObject to a GeometryModel")
+          .def("getGeometryId",&GeometryModelPythonVisitor::getGeometryId)
+          .def("existGeometryName",&GeometryModelPythonVisitor::existGeometryName)
           .def("__str__",&GeometryModelPythonVisitor::toString)
 #ifdef WITH_HPP_FCL
-          .add_property("collision_pairs",
-                        bp::make_function(&GeometryModelPythonVisitor::collision_pairs,
+          .add_property("collisionPairs",
+                        bp::make_function(&GeometryModelPythonVisitor::collisionPairs,
                                           bp::return_internal_reference<>()),
                         "Vector of collision pairs.")
           .def("addCollisionPair",&GeometryModelPythonVisitor::addCollisionPair,
@@ -106,12 +110,14 @@ namespace se3
       { return  gmodelPtr->getGeometryId(name); }
       static bool existGeometryName(const GeometryModelHandler & gmodelPtr, const std::string & name)
       { return gmodelPtr->existGeometryName(name);}
-      static std::string getGeometryName(const GeometryModelHandler & gmodelPtr, const GeomIndex index)
-      { return gmodelPtr->getGeometryName(index);}
+
       
       static std::vector<GeometryObject> & geometryObjects( GeometryModelHandler & m ) { return m->geometryObjects; }
+      static GeomIndex addGeometryObject( GeometryModelHandler & m, GeometryObject gobject, const ModelHandler & model, const bool autofillJointParent)
+      { return m-> addGeometryObject(gobject, *model, autofillJointParent); }
+
 #ifdef WITH_HPP_FCL      
-      static std::vector<CollisionPair> & collision_pairs( GeometryModelHandler & m ) 
+      static std::vector<CollisionPair> & collisionPairs( GeometryModelHandler & m ) 
       { return m->collisionPairs; }
       
       static void addCollisionPair (GeometryModelHandler & m, const GeomIndex co1, const GeomIndex co2)
@@ -146,7 +152,6 @@ namespace se3
         bp::enum_<GeometryType>("GeometryType")
         .value("VISUAL",VISUAL)
         .value("COLLISION",COLLISION)
-        .value("NONE",NONE)
         ;
         
         bp::class_<GeometryModelHandler>("GeometryModel",
diff --git a/bindings/python/geometry-object.hpp b/bindings/python/geometry-object.hpp
index cd9506845e11acf9da5b8c0b4c3f5fdeb4796a15..5117a77a4d10a2bb2b456a99b94ef1411e30800f 100644
--- a/bindings/python/geometry-object.hpp
+++ b/bindings/python/geometry-object.hpp
@@ -53,11 +53,12 @@ namespace se3
       {
         cl
           .def_readwrite("name", &GeometryObject::name, "Name of the GeometryObject")
-          .def_readwrite("parent", &GeometryObject::parent, "Index of the parent joint")
+          .def_readwrite("parentJoint", &GeometryObject::parentJoint, "Index of the parent joint")
+          .def_readwrite("parentFrame", &GeometryObject::parentFrame, "Index of the parent frame")
           .add_property("placement", &GeometryObjectPythonVisitor::getPlacementWrtParentJoint,
                                       &GeometryObjectPythonVisitor::setPlacementWrtParentJoint,
                                       "Position of geometry object in parent joint's frame")
-          .def_readonly("mesh_path", &GeometryObject::mesh_path, "Absolute path to the mesh file")
+          .def_readonly("meshPath", &GeometryObject::meshPath, "Absolute path to the mesh file")
           ;
       }
 
@@ -67,7 +68,7 @@ namespace se3
       static void expose()
       {
         bp::class_<GeometryObject>("GeometryObject",
-                           "A wrapper on a collision geometry including its parent joint, placement in parent frame.\n\n",
+                           "A wrapper on a collision geometry including its parent joint, parent frame, placement in parent joint's frame.\n\n",
 	                         bp::no_init
                          )
 	                       .def(GeometryObjectPythonVisitor())
diff --git a/bindings/python/joint.hpp b/bindings/python/joint.hpp
index 9014d720fdbbb2e9609aa0db29bc280911f6ccf6..094bb7f02102f11fa6268a549bd5a0c2e6b9e90d 100644
--- a/bindings/python/joint.hpp
+++ b/bindings/python/joint.hpp
@@ -20,7 +20,7 @@
 
 #include <eigenpy/exception.hpp>
 #include <eigenpy/eigenpy.hpp>
-#include "pinocchio/multibody/joint/joint.hpp"
+#include "pinocchio/multibody/joint/joint-composite.hpp"
 
 namespace se3
 {
diff --git a/bindings/python/model.hpp b/bindings/python/model.hpp
index 6e16e9686eca03af940726c8d487730b21d70cec..a9136c0cdfef877a4edadc75065ef01c4cad7a99 100644
--- a/bindings/python/model.hpp
+++ b/bindings/python/model.hpp
@@ -94,16 +94,15 @@ namespace se3
       void visit(PyClass& cl) const 
       {
         cl
-          .def("getBodyId",&ModelPythonVisitor::getBodyId)
-          .def("getJointId",&ModelPythonVisitor::getJointId)
-          .def("createData",&ModelPythonVisitor::createData)
+          // Class Members
 
           .def("__str__",&ModelPythonVisitor::toString)
 
           .add_property("nq", &ModelPythonVisitor::nq)
           .add_property("nv", &ModelPythonVisitor::nv)
-          .add_property("njoint", &ModelPythonVisitor::njoint)
-          .add_property("nbody", &ModelPythonVisitor::nbody)
+          .add_property("njoints", &ModelPythonVisitor::njoints)
+          .add_property("nbodies", &ModelPythonVisitor::nbodies)
+          .add_property("nframes", &ModelPythonVisitor::nframes)
           .add_property("inertias",
             bp::make_function(&ModelPythonVisitor::inertias,
                   bp::return_internal_reference<>())  )
@@ -116,32 +115,41 @@ namespace se3
           .add_property("parents", 
             bp::make_function(&ModelPythonVisitor::parents,
                   bp::return_internal_reference<>())  )
-        .add_property("subtrees",
-                      bp::make_function(&ModelPythonVisitor::subtrees,
-                                        bp::return_internal_reference<>()), "Vector of subtrees. subtree[j] corresponds to the subtree supported by the joint j.")
           .add_property("names",
             bp::make_function(&ModelPythonVisitor::names,
                   bp::return_internal_reference<>())  )
-        
-        .def("addJoint",&ModelPythonVisitor::addJoint,bp::args("parent_id","joint_model","joint_placement","joint_name"),"Adds a joint to the kinematic tree. The joint is defined by its placement relative to its parent joint and its name.")
-        .def("appendBodyToJoint",&ModelPythonVisitor::appendBodyToJoint,bp::args("joint_id","body_inertia","body_placement","body_name"),"Appends a body to the joint given by its index. The body is defined by its inertia, its relative placement regarding to the joint and its name.")
-
-
-          .add_property("effortLimit", bp::make_function(&ModelPythonVisitor::effortLimit), "Joint max effort")
           .add_property("neutralConfiguration", bp::make_function(&ModelPythonVisitor::neutralConfiguration), "Joint's neutral configurations")
+          .add_property("effortLimit", bp::make_function(&ModelPythonVisitor::effortLimit), "Joint max effort")
           .add_property("velocityLimit", bp::make_function(&ModelPythonVisitor::velocityLimit), "Joint max velocity")
           .add_property("lowerPositionLimit", bp::make_function(&ModelPythonVisitor::lowerPositionLimit), "Limit for joint lower position")
           .add_property("upperPositionLimit", bp::make_function(&ModelPythonVisitor::upperPositionLimit), "Limit for joint upper position")
+        
+          .add_property("frames", bp::make_function(&ModelPythonVisitor::frames, bp::return_internal_reference<>()),"Vector of frames contained in the model.")
 
-          .def("getFrameParent", &ModelPythonVisitor::getFrameParent)
-          .def("getFramePlacement", &ModelPythonVisitor::getFramePlacement)
-        .def("addFrame",(bool (*)(ModelHandler&,const std::string &,const JointIndex, const SE3_fx &,const FrameType &)) &ModelPythonVisitor::addFrame,bp::args("name","parent_id","placement","type"),"Add a frame to the vector of frames. See also Frame for more details. Returns False if the frame already exists.")
-        .def("addFrame",(bool (*)(ModelHandler&,const Frame &)) &ModelPythonVisitor::addFrame,bp::args("frame"),"Add a frame to the vector of frames.")
-        .add_property("frames", bp::make_function(&ModelPythonVisitor::frames, bp::return_internal_reference<>()),"Vector of frames contained in the model.")
-        .def("existFrame",&ModelPythonVisitor::existFrame,bp::args("name"),"Returns true if the frame given by its name exists inside the Model.")
-        .def("getFrameId",&ModelPythonVisitor::getFrameId,bp::args("name"),"Returns the index of the frame given by its name. If the frame is not in the frames vector, it returns the current size of the frames vector.")
-
+          .add_property("subtrees",
+                      bp::make_function(&ModelPythonVisitor::subtrees,
+                                        bp::return_internal_reference<>()), "Vector of subtrees. subtree[j] corresponds to the subtree supported by the joint j.")
+        
           .add_property("gravity",&ModelPythonVisitor::gravity,&ModelPythonVisitor::setGravity)
+
+          // Class Methods
+          .def("addJoint",&ModelPythonVisitor::addJoint,bp::args("parent_id","joint_model","joint_placement","joint_name"),"Adds a joint to the kinematic tree. The joint is defined by its placement relative to its parent joint and its name.")
+          // ADD addJoint with limits ? See boost::python overloading/default parameters
+          .def("addJointFrame", &ModelPythonVisitor::addJointFrame, bp::args("jointIndex", "frameIndex"), "add the joint at index jointIndex as a frame to the frame tree")
+          .def("appendBodyToJoint",&ModelPythonVisitor::appendBodyToJoint,bp::args("joint_id","body_inertia","body_placement"),"Appends a body to the joint given by its index. The body is defined by its inertia, its relative placement regarding to the joint and its name.")
+
+          .def("addBodyFrame", &ModelPythonVisitor::addBodyFrame, bp::args("body_name", "parentJoint", "body_plaement", "previous_frame(parent frame)"), "add a body to the frame tree")
+          .def("getBodyId",&ModelPythonVisitor::getBodyId, bp::args("name"), "Return the index of a frame of type BODY given by its name")
+          .def("existBodyName", &ModelPythonVisitor::existBodyName, bp::args("name"), "Check if a frame of type BODY exists, given its name")
+          .def("getJointId",&ModelPythonVisitor::getJointId, bp::args("name"), "Return the index of a joint given by its name")
+          .def("existJointName", &ModelPythonVisitor::existJointName, bp::args("name"), "Check if a joint given by its name exists")
+          .def("getFrameId",&ModelPythonVisitor::getFrameId,bp::args("name"),"Returns the index of the frame given by its name. If the frame is not in the frames vector, it returns the current size of the frames vector.")
+          .def("existFrame",&ModelPythonVisitor::existFrame,bp::args("name"),"Returns true if the frame given by its name exists inside the Model.")
+
+          .def("addFrame",(bool (*)(ModelHandler&,const std::string &,const JointIndex, const FrameIndex, const SE3_fx &,const FrameType &)) &ModelPythonVisitor::addFrame,bp::args("name","parent_id","placement","type"),"Add a frame to the vector of frames. See also Frame for more details. Returns False if the frame already exists.")
+          .def("addFrame",(bool (*)(ModelHandler&,const Frame &)) &ModelPythonVisitor::addFrame,bp::args("frame"),"Add a frame to the vector of frames.")
+
+          .def("createData",&ModelPythonVisitor::createData)
           .def("BuildEmptyModel",&ModelPythonVisitor::maker_empty)
           .staticmethod("BuildEmptyModel")
           .def("BuildHumanoidSimple",&ModelPythonVisitor::maker_humanoidSimple)
@@ -149,24 +157,28 @@ namespace se3
           ;
       }
 
-      static Model::Index getBodyId( const ModelHandler & modelPtr, const std::string & name )
-      { return  modelPtr->getBodyId(name); }
-      static Model::Index getJointId( const ModelHandler & modelPtr, const std::string & name )
-      { return  modelPtr->getJointId(name); }
-      static boost::shared_ptr<Data> createData(const ModelHandler& m )
-      { return boost::shared_ptr<Data>( new Data(*m) );      } 
       
       static int nq( ModelHandler & m ) { return m->nq; }
       static int nv( ModelHandler & m ) { return m->nv; }
-      static int njoint( ModelHandler & m ) { return m->njoint; }
-      static int nbody( ModelHandler & m ) { return m->nbody; }
+      static int njoints( ModelHandler & m ) { return m->njoints; }
+      static int nbodies( ModelHandler & m ) { return m->nbodies; }
+      static int nframes( ModelHandler & m ) { return m->nframes; }
       static std::vector<Inertia> & inertias( ModelHandler & m ) { return m->inertias; }
       static std::vector<SE3> & jointPlacements( ModelHandler & m ) { return m->jointPlacements; }
       static JointModelVector & joints( ModelHandler & m ) { return m->joints; }
       static std::vector<Model::JointIndex> & parents( ModelHandler & m ) { return m->parents; }
       static std::vector<std::string> & names ( ModelHandler & m ) { return m->names; }
+      static Eigen::VectorXd neutralConfiguration(ModelHandler & m) {return m->neutralConfiguration;}
+      static Eigen::VectorXd effortLimit(ModelHandler & m) {return m->effortLimit;}
+      static Eigen::VectorXd velocityLimit(ModelHandler & m) {return m->velocityLimit;}
+      static Eigen::VectorXd lowerPositionLimit(ModelHandler & m) {return m->lowerPositionLimit;}
+      static Eigen::VectorXd upperPositionLimit(ModelHandler & m) {return m->upperPositionLimit;}
+      static std::vector<Frame> & frames ( ModelHandler & m ) {return m->frames; }
       static std::vector<Model::IndexVector> & subtrees(ModelHandler & m) { return m->subtrees; }
 
+      static Motion gravity( ModelHandler & m ) { return m->gravity; }
+      static void setGravity( ModelHandler & m,const Motion_fx & g ) { m->gravity = g; }
+
       static JointIndex addJoint(ModelHandler & model,
                                  JointIndex parent_id,
                                  bp::object jmodel,
@@ -177,39 +189,51 @@ namespace se3
         return boost::apply_visitor(addJointVisitor(model,parent_id,joint_placement,joint_name), jmodel_variant);
       }
       
+      static int addJointFrame( ModelHandler & m, const JointIndex jointIndex, int frameIndex)
+      {
+        return m->addJointFrame(jointIndex, frameIndex);
+      }
+
       static void appendBodyToJoint(ModelHandler & model,
                                     const JointIndex joint_parent_id,
                                     const Inertia_fx & inertia,
-                                    const SE3_fx & body_placement,
-                                    const std::string & body_name)
+                                    const SE3_fx & body_placement)
       {
-        model->appendBodyToJoint(joint_parent_id,inertia,body_placement,body_name);
+        model->appendBodyToJoint(joint_parent_id,inertia,body_placement);
       }
 
-      static Eigen::VectorXd neutralConfiguration(ModelHandler & m) {return m->neutralConfiguration;}
-      static Eigen::VectorXd effortLimit(ModelHandler & m) {return m->effortLimit;}
-      static Eigen::VectorXd velocityLimit(ModelHandler & m) {return m->velocityLimit;}
-      static Eigen::VectorXd lowerPositionLimit(ModelHandler & m) {return m->lowerPositionLimit;}
-      static Eigen::VectorXd upperPositionLimit(ModelHandler & m) {return m->upperPositionLimit;}
-
-      static Model::JointIndex  getFrameParent( ModelHandler & m, const std::string & name ) { return m->getFrameParent(name); }
-      static SE3  getFramePlacement(ModelHandler & m, const std::string & name) { return m->getFramePlacement(name); }
-      
-      static bool addFrame(ModelHandler & m, const Frame & frame) { return m->addFrame(frame); }
-      static bool addFrame( ModelHandler & m, const std::string & frameName, const JointIndex parent, const SE3_fx & placementWrtParent, const FrameType & type)
+      static bool addBodyFrame( ModelHandler & m, const std::string & bodyName, const JointIndex parentJoint, const SE3_fx & bodyPlacement, int previousFrame)
       {
-        return m->addFrame(frameName,parent,placementWrtParent,type);
+        return m->addBodyFrame(bodyName,parentJoint,bodyPlacement,previousFrame);
       }
+
+      static Model::Index getBodyId( const ModelHandler & m, const std::string & name )
+      { return  m->getBodyId(name); }
+
+      static bool existBodyName( const ModelHandler & m, const std::string & name )
+      { return  m->existBodyName(name); }
+
+      static Model::Index getJointId( const ModelHandler & m, const std::string & name )
+      { return  m->getJointId(name); }
+
+      static bool existJointName( const ModelHandler & m, const std::string & name )
+      { return  m->existJointName(name); }
+
       static Model::FrameIndex getFrameId(const ModelHandler & m, const std::string & frame_name)
       { return m->getFrameId(frame_name); }
       static bool existFrame(const ModelHandler & m, const std::string & frame_name)
       { return m->existFrame(frame_name); }
+
+      static bool addFrame(ModelHandler & m, const Frame & frame) { return m->addFrame(frame); }
+      static bool addFrame( ModelHandler & m, const std::string & frameName, const JointIndex parentJoint, const FrameIndex parentFrame, const SE3_fx & placementWrtParent, const FrameType & type)
+      {
+        return m->addFrame(Frame(frameName,parentJoint,parentFrame,placementWrtParent,type));
+      }
       
-      static std::vector<Frame> & frames (ModelHandler & m ) { return m->frames;}
 
-      static Motion gravity( ModelHandler & m ) { return m->gravity; }
-      static void setGravity( ModelHandler & m,const Motion_fx & g ) { m->gravity = g; }
 
+      static boost::shared_ptr<Data> createData(const ModelHandler& m )
+      { return boost::shared_ptr<Data>( new Data(*m) );      } 
 
       static ModelHandler maker_empty()
       {
diff --git a/bindings/python/motion.hpp b/bindings/python/motion.hpp
index d0be176ce44f1ffef1edc1073bdf6276cf3d7a0f..b84af9dfeb75b87a2a330eba6d46788576df9bb3 100644
--- a/bindings/python/motion.hpp
+++ b/bindings/python/motion.hpp
@@ -91,6 +91,7 @@ namespace se3
         
         .def("__add__",&MotionPythonVisitor::add)
         .def("__sub__",&MotionPythonVisitor::subst)
+        .def("__neg__",&MotionPythonVisitor::neg)
         .def(bp::self_ns::str(bp::self_ns::self))
         
         .def("Random",&Motion_fx::Random)
@@ -113,6 +114,7 @@ namespace se3
       
       static Motion_fx add( const Motion_fx& m1,const Motion_fx& m2 ) { return m1+m2; }     
       static Motion_fx subst( const Motion_fx& m1,const Motion_fx& m2 ) { return m1-m2; }     
+      static Motion_fx neg(const Motion_fx & m1) { return -m1; }
       static Motion_fx cross_motion( const Motion_fx& m1,const Motion_fx& m2 ) { return m1.cross(m2); }
       static Force_fx cross_force( const Motion_fx& m,const Force_fx& f ) { return m.cross(f); }
 
diff --git a/bindings/python/robot_wrapper.py b/bindings/python/robot_wrapper.py
index 8e8b8156b6ce683ef01bdee096bbafa597844100..ebb0d943c64f99cd5ccb267e9eab5a08339b3e66 100644
--- a/bindings/python/robot_wrapper.py
+++ b/bindings/python/robot_wrapper.py
@@ -32,6 +32,7 @@ class RobotWrapper(object):
         self.data = self.model.createData()
         self.model_filename = filename
 
+        print dir(se3)
         if "buildGeomFromUrdf" not in dir(se3):
             self.collision_model = None
             self.visual_model = None
diff --git a/models/simple_model.py b/models/simple_model.py
index 2151c0819af9bbe67481e0e0368346469965463b..6fbf0661b35411256671d8705226a305ab885e7f 100644
--- a/models/simple_model.py
+++ b/models/simple_model.py
@@ -86,7 +86,9 @@ class ModelWrapper(object):
                 self.display.viewer.gui.addSphere(body_name, dimensions, color(body_color))
         body_inertia.lever = lever.translation
         joint_id = self.model.addJoint(parent, joint_model, joint_placement, joint_name)
-        self.model.appendBodyToJoint(joint_id, body_inertia, se3.SE3.Identity(), body_name)
+        self.model.appendBodyToJoint(joint_id, body_inertia, se3.SE3.Identity())
+        self.model.addJointFrame(joint_id, -1)
+        self.model.addBodyFrame(body_name, joint_id, se3.SE3.Identity(),-1)
         self.visuals.append((body_name, joint_placement, lever))
         self.data = self.model.createData()
         if self.display:
diff --git a/python/bindings_frame.py b/python/bindings_frame.py
index 2643ced00d7e41279b25394c223e4323f9e52d7f..69fa1a417659ab2c140b1647ae9c061ea68f71f3 100644
--- a/python/bindings_frame.py
+++ b/python/bindings_frame.py
@@ -24,19 +24,19 @@ class TestFrameBindings(unittest.TestCase):
     robot = RobotWrapper(romeo_model_path, hint_list, se3.JointModelFreeFlyer())
 
     def test_type_get_set(self):
-        f = self.robot.model.frames[2]
+        f = self.robot.model.frames[5]
         self.assertTrue(f.type == se3.FrameType.JOINT)
         f.type = se3.FrameType.BODY
         self.assertTrue(f.type == se3.FrameType.BODY)
 
     def test_name_get_set(self):
-        f = self.robot.model.frames[2]
+        f = self.robot.model.frames[5]
         self.assertTrue(f.name == 'LHipYaw')
         f.name = 'new_hip_frame'
         self.assertTrue(f.name == 'new_hip_frame')
 
     def test_parent_get_set(self):
-        f = self.robot.model.frames[2]
+        f = self.robot.model.frames[5]
         self.assertTrue(f.parent == 2)
         f.parent = 5
         self.assertTrue(f.parent == 5)
diff --git a/python/bindings_geometry_object.py b/python/bindings_geometry_object.py
index c9868b6dd923225b08723d0354387aa0aef0a155..e64bc1783ec07fa2d3a9966f607277ae33e6e64e 100644
--- a/python/bindings_geometry_object.py
+++ b/python/bindings_geometry_object.py
@@ -32,9 +32,9 @@ class TestGeometryObjectBindings(unittest.TestCase):
 
     def test_parent_get_set(self):
         col = self.robot.collision_model.geometryObjects[1]
-        self.assertTrue(col.parent == 4)
-        col.parent = 5
-        self.assertTrue(col.parent == 5)
+        self.assertTrue(col.parentJoint == 4)
+        col.parentJoint = 5
+        self.assertTrue(col.parentJoint == 5)
 
     def test_placement_get_set(self):
         m = se3.SE3(self.m3ones, self.v3zero)
@@ -47,7 +47,7 @@ class TestGeometryObjectBindings(unittest.TestCase):
     def test_meshpath_get(self):
         expected_mesh_path = os.path.join(self.pinocchio_models_dir,'meshes/romeo/collision/LHipPitch.dae')
         col = self.robot.collision_model.geometryObjects[1]
-        self.assertTrue(col.mesh_path == expected_mesh_path)
+        self.assertTrue(col.meshPath == expected_mesh_path)
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/python/model.py b/python/model.py
index 280a4d2378c7576d150513fd78b1744f907d6b6d..4824c16029629e12e6fea54d42245e475ccfe764 100644
--- a/python/model.py
+++ b/python/model.py
@@ -10,14 +10,14 @@ class TestModel(TestCase):
 
     def test_empty_model_sizes(self):
         model = se3.Model.BuildEmptyModel()
-        self.assertEqual(model.nbody, 1)
+        self.assertEqual(model.nbodies, 1)
         self.assertEqual(model.nq, 0)
         self.assertEqual(model.nv, 0)
 
     def test_model(self):
         model = self.model
         nb = 28  # We should have 28 bodies, thus 27 joints, one of them a free-flyer.
-        self.assertEqual(model.nbody, nb)
+        self.assertEqual(model.nbodies, nb)
         self.assertEqual(model.nq, nb - 1 + 6)
         self.assertEqual(model.nv, nb - 1 + 5)
 
@@ -46,11 +46,11 @@ class TestModel(TestCase):
         q = zero(model.nq)
         qdot = zero(model.nv)
         qddot = zero(model.nv)
-        for i in range(model.nbody):
+        for i in range(model.nbodies):
             data.a[i] = se3.Motion.Zero()
 
         se3.rnea(model, data, q, qdot, qddot)
-        for i in range(model.nbody):
+        for i in range(model.nbodies):
             self.assertApprox(data.v[i].np, zero(6))
         self.assertApprox(data.a_gf[0].np, -model.gravity.np)
         self.assertApprox(data.f[-1], model.inertias[-1] * data.a_gf[-1])
diff --git a/src/algorithm/aba.hxx b/src/algorithm/aba.hxx
index 6b49a33a4ac8db993b8704474a41b0cd6230b043..af0f5c413af8ee0ea2e069f23fee04355ea7aade 100644
--- a/src/algorithm/aba.hxx
+++ b/src/algorithm/aba.hxx
@@ -197,19 +197,19 @@ namespace se3
     data.a[0] = -model.gravity;
     data.u = tau;
     
-    for(Model::Index i=1;i<(Model::Index)model.njoint;++i)
+    for(Model::Index i=1;i<(Model::Index)model.njoints;++i)
     {
       AbaForwardStep1::run(model.joints[i],data.joints[i],
                            AbaForwardStep1::ArgsType(model,data,q,v));
     }
     
-    for( Model::Index i=(Model::Index)model.njoint-1;i>0;--i )
+    for( Model::Index i=(Model::Index)model.njoints-1;i>0;--i )
     {
       AbaBackwardStep::run(model.joints[i],data.joints[i],
                            AbaBackwardStep::ArgsType(model,data));
     }
     
-    for(Model::Index i=1;i<(Model::Index)model.njoint;++i)
+    for(Model::Index i=1;i<(Model::Index)model.njoints;++i)
     {
       AbaForwardStep2::run(model.joints[i],data.joints[i],
                            AbaForwardStep2::ArgsType(model,data));
diff --git a/src/algorithm/center-of-mass.hxx b/src/algorithm/center-of-mass.hxx
index 680fd31ece03f922a94b91f48594551aa5929ad4..af008090177ebcd86cbd520af8feb0fb9f3e6945 100644
--- a/src/algorithm/center-of-mass.hxx
+++ b/src/algorithm/center-of-mass.hxx
@@ -36,7 +36,7 @@ namespace se3
     if (updateKinematics)
       forwardKinematics(model, data, q);
 
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
     {
       const double mass = model.inertias[i].mass();
       const SE3::Vector3 & lever = model.inertias[i].lever();
@@ -46,7 +46,7 @@ namespace se3
     }
     
     // Backward Step
-    for(Model::JointIndex i=(Model::JointIndex)(model.njoint-1); i>0; --i)
+    for(Model::JointIndex i=(Model::JointIndex)(model.njoints-1); i>0; --i)
     {
       const Model::JointIndex & parent = model.parents[i];
       
@@ -84,7 +84,7 @@ namespace se3
     if (updateKinematics)
       forwardKinematics(model, data, q, v);
     
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
     {
       const double mass = model.inertias[i].mass();
       const SE3::Vector3 & lever = model.inertias[i].lever();
@@ -98,7 +98,7 @@ namespace se3
     }
     
     // Backward Step
-    for(Model::JointIndex i=(Model::JointIndex)(model.njoint-1); i>0; --i)
+    for(Model::JointIndex i=(Model::JointIndex)(model.njoints-1); i>0; --i)
     {
       const Model::JointIndex & parent = model.parents[i];
       
@@ -142,7 +142,7 @@ namespace se3
     if (updateKinematics)
       forwardKinematics(model, data, q, v, a);
     
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
     {
       const double mass = model.inertias[i].mass();
       const SE3::Vector3 & lever = model.inertias[i].lever();
@@ -158,7 +158,7 @@ namespace se3
     }
     
     // Backward Step
-    for(Model::JointIndex i=(Model::JointIndex)(model.njoint-1); i>0; --i)
+    for(Model::JointIndex i=(Model::JointIndex)(model.njoints-1); i>0; --i)
     {
       const Model::JointIndex & parent = model.parents[i];
       
@@ -225,14 +225,37 @@ namespace se3
       ColBlock Jcols = jmodel.jointCols(data.J);
       Jcols = data.oMi[i].act(jdata.S());
       
-      if( JointModel::NV==1 )
+      if (JointModel::NV == -1)
+      {
+        if( jmodel.nv() ==1 )
+        {
         data.Jcom.col(jmodel.idx_v())
         = data.mass[i] * Jcols.template topLeftCorner<3,1>()
         - data.com[i].cross(Jcols.template bottomLeftCorner<3,1>()) ;
+        }
+        else
+        {
+          jmodel.jointCols(data.Jcom)
+          = data.mass[i] * Jcols.template topRows<3>()
+          - skew(data.com[i]) * Jcols.template bottomRows<3>();
+        }
+      }
       else
-        jmodel.jointCols(data.Jcom)
-        = data.mass[i] * Jcols.template topRows<3>()
-        - skew(data.com[i]) * Jcols.template bottomRows<3>();
+      {
+        if( JointModel::NV ==1 )
+        {
+        data.Jcom.col(jmodel.idx_v())
+        = data.mass[i] * Jcols.template topLeftCorner<3,1>()
+        - data.com[i].cross(Jcols.template bottomLeftCorner<3,1>()) ;
+        }
+        else
+        {
+          jmodel.jointCols(data.Jcom)
+          = data.mass[i] * Jcols.template topRows<3>()
+          - skew(data.com[i]) * Jcols.template bottomRows<3>();
+        }
+      }
+      
     
       if(computeSubtreeComs)
         data.com[i] /= data.mass[i];
@@ -253,7 +276,7 @@ namespace se3
     if (updateKinematics)
       forwardKinematics(model, data, q);
       
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
     {
       const double mass = model.inertias[i].mass();
       const SE3::Vector3 & lever = model.inertias[i].lever();
@@ -263,7 +286,7 @@ namespace se3
     }
    
     // Backward step
-    for( Model::JointIndex i= (Model::JointIndex) (model.njoint-1);i>0;--i )
+    for( Model::JointIndex i= (Model::JointIndex) (model.njoints-1);i>0;--i )
     {
       JacobianCenterOfMassBackwardStep
       ::run(model.joints[i],data.joints[i],
diff --git a/src/algorithm/compute-all-terms.hpp b/src/algorithm/compute-all-terms.hpp
index eceab35543f10bf0a8ee28d374d7300b865ae7f5..66525c539c3b9661b2f1f9d2dd979840ec286626 100644
--- a/src/algorithm/compute-all-terms.hpp
+++ b/src/algorithm/compute-all-terms.hpp
@@ -211,13 +211,13 @@ namespace se3
     data.com[0].setZero ();
     data.vcom[0].setZero ();
 
-    for(Model::JointIndex i=1;i<(Model::JointIndex) model.njoint;++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex) model.njoints;++i)
     {
       CATForwardStep::run(model.joints[i],data.joints[i],
                           CATForwardStep::ArgsType(model,data,q,v));
     }
 
-    for(Model::JointIndex i=(Model::JointIndex)(model.njoint-1);i>0;--i)
+    for(Model::JointIndex i=(Model::JointIndex)(model.njoints-1);i>0;--i)
     {
       CATBackwardStep::run(model.joints[i],data.joints[i],
                            CATBackwardStep::ArgsType(model,data));
diff --git a/src/algorithm/copy.hpp b/src/algorithm/copy.hpp
index c9bc510f8db12e6b44b398745ac50160ebe45dd3..c0d5b1e913b354317ccc2a43c90e3f8f40c04423 100644
--- a/src/algorithm/copy.hpp
+++ b/src/algorithm/copy.hpp
@@ -47,7 +47,7 @@ namespace se3
   inline void
   copy (const Model& model, const Data & origin, Data & dest )
   {
-    for( se3::JointIndex jid=1; int(jid)<model.njoint; ++ jid )
+    for( se3::JointIndex jid=1; int(jid)<model.njoints; ++ jid )
       {
         assert(LEVEL>=0);
 
diff --git a/src/algorithm/crba.hxx b/src/algorithm/crba.hxx
index c84190f7ff2d68ae473b9f51445d4b7f0e5b71a9..a3315af801524cc59f51647f541acb4b926cf847 100644
--- a/src/algorithm/crba.hxx
+++ b/src/algorithm/crba.hxx
@@ -102,13 +102,13 @@ namespace se3
   crba(const Model & model, Data& data,
        const Eigen::VectorXd & q)
   {
-    for( Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i )
+    for( Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i )
     {
       CrbaForwardStep::run(model.joints[i],data.joints[i],
                            CrbaForwardStep::ArgsType(model,data,q));
     }
     
-    for( Model::JointIndex i=(Model::JointIndex)(model.njoint-1);i>0;--i )
+    for( Model::JointIndex i=(Model::JointIndex)(model.njoints-1);i>0;--i )
     {
       CrbaBackwardStep::run(model.joints[i],data.joints[i],
                             CrbaBackwardStep::ArgsType(model,data));
@@ -161,7 +161,7 @@ namespace se3
                      const se3::Model & model,
                      se3::Data & data)
     {
-      typedef typename Data::Matrix6x::NColsBlockXpr<JointModel::NV>::Type ColsBlock;
+      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<Data::Matrix6x>::Type ColsBlock;
       
       const Model::JointIndex & i = (Model::JointIndex) jmodel.id();
       const Model::Index & parent = model.parents[i];
@@ -169,11 +169,33 @@ namespace se3
       data.Ycrb[parent] += data.liMi[i].act(data.Ycrb[i]);
       
       jdata.U() = data.Ycrb[i] * jdata.S();
+
       ColsBlock jF
-      = data.Ag.middleCols <JointModel::NV> (jmodel.idx_v());
+        = data.Ag.middleCols <JointModel::NV> (jmodel.idx_v());
+
       forceSet::se3Action(data.oMi[i],jdata.U(),jF);
     }
     
+    static void algo(const se3::JointModelBase<JointModelComposite> & jmodel,
+                     se3::JointDataBase<JointDataComposite> & jdata,
+                     const se3::Model & model,
+                     se3::Data & data)
+    {
+      typedef SizeDepType<JointModel::NV>::ColsReturn<Data::Matrix6x>::Type ColsBlock;
+      
+      const Model::JointIndex & i = (Model::JointIndex) jmodel.id();
+      const Model::Index & parent = model.parents[i];
+      
+      data.Ycrb[parent] += data.liMi[i].act(data.Ycrb[i]);
+      
+      jdata.U() = data.Ycrb[i] * jdata.S();
+      
+      ColsBlock jF
+        = data.Ag.middleCols(jmodel.idx_v(), jmodel.nv());
+
+      forceSet::se3Action(data.oMi[i],jdata.U(),jF);
+    }
+
   }; // struct CcrbaBackwardStep
   
   inline const Data::Matrix6x &
@@ -185,11 +207,11 @@ namespace se3
     
     forwardKinematics(model, data, q);
     data.Ycrb[0].setZero();
-    for(Model::Index i=1;i<(Model::Index)(model.njoint);++i )
+    for(Model::Index i=1;i<(Model::Index)(model.njoints);++i )
       data.Ycrb[i] = model.inertias[i];
     
     
-    for(Model::Index i=(Model::Index)(model.njoint-1);i>0;--i)
+    for(Model::Index i=(Model::Index)(model.njoints-1);i>0;--i)
     {
       CcrbaBackwardStep::run(model.joints[i],data.joints[i],
                              CcrbaBackwardStep::ArgsType(model,data));
diff --git a/src/algorithm/energy.hpp b/src/algorithm/energy.hpp
index 6c6207e57f0645f5d3f410fe6194ec1dc0e7d980..c6287805a839aca3f2c6292de13ce629c2cd7adf 100644
--- a/src/algorithm/energy.hpp
+++ b/src/algorithm/energy.hpp
@@ -76,7 +76,7 @@ namespace se3
     if (update_kinematics)
       forwardKinematics(model,data,q,v);
     
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
       data.kinetic_energy += model.inertias[i].vtiv(data.v[i]);
     
     data.kinetic_energy *= .5;
@@ -96,7 +96,7 @@ namespace se3
     if (update_kinematics)
       forwardKinematics(model,data,q);
     
-    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoint);++i)
+    for(Model::JointIndex i=1;i<(Model::JointIndex)(model.njoints);++i)
     {
       com_global = data.oMi[i].translation() + data.oMi[i].rotation() * model.inertias[i].lever();
       data.potential_energy += model.inertias[i].mass() * com_global.dot(g);
diff --git a/src/algorithm/frames.hpp b/src/algorithm/frames.hpp
index 30fbc7c1573126c17019ce3f99d92777360c4d59..825251898c5f8b31e964282e90a24ee741f83b6e 100644
--- a/src/algorithm/frames.hpp
+++ b/src/algorithm/frames.hpp
@@ -84,7 +84,7 @@ namespace se3
                                       Data & data
                                       )
   {
-    for (Model::FrameIndex i=0; i < (Model::FrameIndex) model.nFrames; ++i)
+    for (Model::FrameIndex i=0; i < (Model::FrameIndex) model.nframes; ++i)
     {
       const Frame & frame = model.frames[i];
       const Model::JointIndex & parent = frame.parent;
diff --git a/src/algorithm/geometry.hpp b/src/algorithm/geometry.hpp
index b99352e61b9855c389214859a24652986b70ee43..8612aef9b0fac64bb31539f5f48d82f2a0422ac7 100644
--- a/src/algorithm/geometry.hpp
+++ b/src/algorithm/geometry.hpp
@@ -27,20 +27,19 @@
 namespace se3
 {
 
-
   ///
   /// \brief Apply a forward kinematics and update the placement of the geometry objects.
   ///
   /// \param[in] model The model structure of the rigid body system.
   /// \param[in] data The data structure of the rigid body system.
-  /// \param[in] geom The geometry model containing the collision objects.
-  /// \param[out] geom_data The geometry data containing the placements of the collision objects. See oMg field in GeometryData.
+  /// \param[in] geomModel The geometry model containing the collision objects.
+  /// \param[out] geomData The geometry data containing the placements of the collision objects. See oMg field in GeometryData.
   /// \param[in] q The joint configuration vector (dim model.nq).
   ///
   inline void updateGeometryPlacements(const Model & model,
                                        Data & data,
-                                       const GeometryModel & geom,
-                                       GeometryData & geom_data,
+                                       const GeometryModel & geomModel,
+                                       GeometryData & geomData,
                                        const Eigen::VectorXd & q
                                        );
   
@@ -49,50 +48,115 @@ namespace se3
   ///
   /// \param[in] model The model structure of the rigid body system.
   /// \param[in] data The data structure of the rigid body system.
-  /// \param[in] geom The geometry model containing the collision objects.
-  /// \param[out] geom_data The geometry data containing the placements of the collision objects. See oMg field in GeometryData.
+  /// \param[in] geomModel The geometry model containing the collision objects.
+  /// \param[out] geomData The geometry data containing the placements of the collision objects. See oMg field in GeometryData.
   ///
   inline void updateGeometryPlacements(const Model & model,
                                        const Data & data,
-                                       const GeometryModel & geom,
-                                       GeometryData & geom_data
+                                       const GeometryModel & geomModel,
+                                       GeometryData & geomData
                                        );
+
 #ifdef WITH_HPP_FCL
+
+  ///
+  /// \brief Compute the collision status between a *SINGLE* collision pair.
+  /// The result is store in the collisionResults vector.
+  ///
+  /// \param[in] GeomModel the geometry model (const)
+  /// \param[out] GeomData the corresponding geometry data, where computations are done.
+  /// \param[in] pairId The collsion pair index in the GeometryModel.
+  ///
+  /// \return Return true is the collision objects are colliding.
+  /// \note The complete collision result is also available in geomData.collisionResults[pairId]
+  ///
+  bool computeCollision(const GeometryModel & geomModel,
+                        GeometryData & geomData,
+                        const PairIndex & pairId
+                        );
+    
+  /// Compute the forward kinematics, update the geometry placements and
+  /// calls computeCollision for every active pairs of GeometryData.
+  ///
+  /// \param[in] model robot model (const)
+  /// \param[out] data corresponding data (nonconst) where FK results are stored
+  /// \param[in] geomModel geometry model (const)
+  /// \param[out] geomData corresponding geometry data (nonconst) where distances are computed
+  /// \param[in] q robot configuration.
+  /// \param[in] stopAtFirstCollision if true, stop the loop on pairs after the first collision.
+  /// \return When ComputeShortest is true, the index of the collision pair which has the shortest distance.
+  ///         When ComputeShortest is false, the number of collision pairs.
+  /// \warning if stopAtFirstcollision = true, then the collisions vector will
+  /// not be entirely fulfilled (of course).
+  /// \note A similar function is available without model, data and q, not recomputing the FK.
   inline bool computeCollisions(const Model & model,
                                 Data & data,
-                                const GeometryModel & model_geom,
-                                GeometryData & data_geom,
+                                const GeometryModel & geomModel,
+                                GeometryData & geomData,
                                 const Eigen::VectorXd & q,
                                 const bool stopAtFirstCollision = false
                                 );
 
-  inline bool computeCollisions(GeometryData & data_geom,
-                                const bool stopAtFirstCollision = false
-                                );
-
-  /// Compute the distances of all collision pairs
   ///
-  /// \param ComputeShortest default to true.
-  /// \param data_geom
+  /// \brief Compute the minimal distance between collision objects of a *SINGLE* collison pair
+  ///
+  /// \param[in] GeomModel the geometry model (const)
+  /// \param[out] GeomData the corresponding geometry data, where computations are done.
+  /// \param[in] pairId The index of the collision pair in geom model.
+  ///
+  /// \return A reference on fcl struct containing the distance result, referring an element
+  /// of vector geomData::distanceResults.
+  /// \note The complete distance result is also available in geomData.distanceResults[pairId]
+  ///
+  fcl::DistanceResult & computeDistance(const GeometryModel & geomModel,
+                                        GeometryData & geomData,
+                                        const PairIndex & pairId
+                                        );
+    
+  /// Compute the forward kinematics, update the geometry placements and
+  /// calls computeDistance for every active pairs of GeometryData.
+  ///
+  /// \param[in] ComputeShortest default to true.
+  /// \param[in][out] model: robot model (const)
+  /// \param[out] data: corresponding data (nonconst) where FK results are stored
+  /// \param[in] geomModel: geometry model (const)
+  /// \param[out] geomData: corresponding geometry data (nonconst) where distances are computed
+  /// \param[in] q: robot configuration.
   /// \return When ComputeShortest is true, the index of the collision pair which has the shortest distance.
   ///         When ComputeShortest is false, the number of collision pairs.
-  template <bool ComputeShortest>
-  inline std::size_t computeDistances(GeometryData & data_geom);
-
-  /// Compute the forward kinematics, update the goemetry placements and
-  /// calls computeDistances(GeometryData&).
+  /// \note A similar function is available without model, data and q, not recomputing the FK.
   template <bool ComputeShortest>
   inline std::size_t computeDistances(const Model & model,
                                       Data & data,
-                                      const GeometryModel & model_geom,
-                                      GeometryData & data_geom,
+                                      const GeometryModel & geomModel,
+                                      GeometryData & geomData,
                                       const Eigen::VectorXd & q
                                       );
 
+  /// Compute the radius of the geometry volumes attached to every joints.
+  /// \sa GeometryData::radius
   inline void computeBodyRadius(const Model &         model,
                                 const GeometryModel & geomModel,
                                 GeometryData &        geomData);
 #endif // WITH_HPP_FCL
+
+  /// Append geomModel2 to geomModel1
+  ///
+  /// The steps for appending are:
+  /// \li add GeometryObject of geomModel2 to geomModel1,
+  /// \li add the collision pairs of geomModel2 into geomModel1 (indexes are updated)
+  /// \li add all the collision pairs between geometry objects of geomModel1 and geomModel2.
+  /// It is possible to ommit both data (an additional function signature is available which makes
+  /// them optionnal), then inner/outer objects are not updated.
+  ///
+  /// \param[out] geomModel1   geometry model where the data is added
+  /// \param[in]  geomModel2   geometry model from which new geometries are taken
+  /// \note Of course, the geomData corresponding to geomModel1 will not be valid anymore, 
+  /// and should be updated (or more simply, re-created from the new setting of geomModel1).
+  /// \todo This function is not asserted in unittest.
+  inline void appendGeometryModel(GeometryModel & geomModel1,
+                                  GeometryData & geomData1);
+
 } // namespace se3 
 
 /* --- Details -------------------------------------------------------------------- */
diff --git a/src/algorithm/geometry.hxx b/src/algorithm/geometry.hxx
index 3865d4e6147706fc2778452b595870e75356d949..da39583c5445f81d597d47915794c3e524b6c1ce 100644
--- a/src/algorithm/geometry.hxx
+++ b/src/algorithm/geometry.hxx
@@ -22,49 +22,75 @@
 
 namespace se3 
 {
-  
+  /* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */
+  /* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */
+  /* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */
   inline void updateGeometryPlacements(const Model & model,
                                       Data & data,
-                                      const GeometryModel & model_geom,
-                                      GeometryData & data_geom,
+                                      const GeometryModel & geomModel,
+                                      GeometryData & geomData,
                                       const Eigen::VectorXd & q
                                       )
   {
     forwardKinematics(model, data, q);
-    updateGeometryPlacements(model, data, model_geom, data_geom);
+    updateGeometryPlacements(model, data, geomModel, geomData);
   }
   
   inline void  updateGeometryPlacements(const Model &,
                                        const Data & data,
-                                       const GeometryModel & model_geom,
-                                       GeometryData & data_geom
+                                       const GeometryModel & geomModel,
+                                       GeometryData & geomData
                                        )
   {
-    for (GeomIndex i=0; i < (GeomIndex) data_geom.model_geom.ngeoms; ++i)
+    for (GeomIndex i=0; i < (GeomIndex) geomModel.ngeoms; ++i)
     {
-      const Model::JointIndex & parent = model_geom.geometryObjects[i].parent;
-      if (parent>0) data_geom.oMg[i] =  (data.oMi[parent] * model_geom.geometryObjects[i].placement);
-      else          data_geom.oMg[i] =  model_geom.geometryObjects[i].placement;
+      const Model::JointIndex & joint = geomModel.geometryObjects[i].parentJoint;
+      if (joint>0) geomData.oMg[i] =  (data.oMi[joint] * geomModel.geometryObjects[i].placement);
+      else         geomData.oMg[i] =  geomModel.geometryObjects[i].placement;
 #ifdef WITH_HPP_FCL  
-      data_geom.collisionObjects[i].setTransform( toFclTransform3f(data_geom.oMg[i]) );
+      geomData.collisionObjects[i].setTransform( toFclTransform3f(geomData.oMg[i]) );
 #endif // WITH_HPP_FCL
     }
   }
 #ifdef WITH_HPP_FCL  
-  inline bool computeCollisions(GeometryData & data_geom,
-                                const bool stopAtFirstCollision
-                                )
+
+  /* --- COLLISIONS ----------------------------------------------------------------- */
+  /* --- COLLISIONS ----------------------------------------------------------------- */
+  /* --- COLLISIONS ----------------------------------------------------------------- */
+
+  inline bool computeCollision(const GeometryModel & geomModel,
+                               GeometryData & geomData,
+                               const PairIndex& pairId)
+  {
+    assert( pairId < geomModel.collisionPairs.size() );
+    const CollisionPair & pair = geomModel.collisionPairs[pairId];
+
+    assert( pairId      < geomData.collisionResults.size() );
+    assert( pair.first  < geomData.collisionObjects.size() );
+    assert( pair.second < geomData.collisionObjects.size() );
+
+    fcl::CollisionResult& collisionResult = geomData.collisionResults[pairId];
+    collisionResult.clear();
+    fcl::collide (&geomData.collisionObjects[pair.first],
+                  &geomData.collisionObjects[pair.second],
+                  geomData.collisionRequest,
+                  collisionResult);
+
+    return collisionResult.isCollision();
+  }
+  
+  inline bool computeCollisions(const GeometryModel & geomModel,
+                                GeometryData & geomData,
+                                const bool stopAtFirstCollision = true)
   {
     bool isColliding = false;
-    const GeometryModel & geomModel = data_geom.model_geom;
     
     for (std::size_t cpt = 0; cpt < geomModel.collisionPairs.size(); ++cpt)
     {
-      if(data_geom.activeCollisionPairs[cpt])
+      if(geomData.activeCollisionPairs[cpt])
         {
-          data_geom.collision_results[cpt]
-            = data_geom.computeCollision(geomModel.collisionPairs[cpt]);
-          isColliding |= data_geom.collision_results[cpt].fcl_collision_result.isCollision();
+          computeCollision(geomModel,geomData,cpt);
+          isColliding |= geomData.collisionResults[cpt].isCollision();
           if(isColliding && stopAtFirstCollision)
             return true;
         }
@@ -76,67 +102,97 @@ namespace se3
   // 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 GeometryModel & geomModel,
+                                GeometryData & geomData,
                                 const Eigen::VectorXd & q,
                                 const bool stopAtFirstCollision
                                 )
   {
-    updateGeometryPlacements (model, data, model_geom, data_geom, q);
+    updateGeometryPlacements (model, data, geomModel, geomData, q);
     
-    return computeCollisions(data_geom, stopAtFirstCollision);
+    return computeCollisions(geomModel,geomData, stopAtFirstCollision);
   }
 
-  // Required to have a default template argument on templated free function
-  inline std::size_t computeDistances(GeometryData & data_geom)
+  /* --- DISTANCES ----------------------------------------------------------------- */
+  /* --- DISTANCES ----------------------------------------------------------------- */
+  /* --- DISTANCES ----------------------------------------------------------------- */
+
+  inline fcl::DistanceResult & computeDistance(const GeometryModel & geomModel,
+                                               GeometryData & geomData,
+                                               const PairIndex & pairId )
   {
-    return computeDistances<true>(data_geom);
+    assert( pairId < geomModel.collisionPairs.size() );
+    const CollisionPair & pair = geomModel.collisionPairs[pairId];
+
+    assert( pairId      < geomData.distanceResults.size() );
+    assert( pair.first  < geomData.collisionObjects.size() );
+    assert( pair.second < geomData.collisionObjects.size() );
+
+    geomData.distanceResults[pairId].clear();
+    fcl::distance ( &geomData.collisionObjects[pair.first],
+                    &geomData.collisionObjects[pair.second],
+                    geomData.distanceRequest,
+                    geomData.distanceResults[pairId]);
+
+    return geomData.distanceResults[pairId];
   }
   
+
   template <bool COMPUTE_SHORTEST>
-  inline std::size_t computeDistances(GeometryData & data_geom)
+  inline std::size_t computeDistances(const GeometryModel & geomModel,
+                                      GeometryData & geomData)
   {
-    const GeometryModel & geomModel = data_geom.model_geom;
     std::size_t min_index = geomModel.collisionPairs.size();
     double min_dist = std::numeric_limits<double>::infinity();
     for (std::size_t cpt = 0; cpt < geomModel.collisionPairs.size(); ++cpt)
     {
-      if(data_geom.activeCollisionPairs[cpt])
+      if(geomData.activeCollisionPairs[cpt])
         {
-          data_geom.distance_results[cpt] = data_geom.computeDistance(geomModel.collisionPairs[cpt]);
-          if (COMPUTE_SHORTEST && data_geom.distance_results[cpt].distance() < min_dist)
+          computeDistance(geomModel,geomData,cpt);
+          if (COMPUTE_SHORTEST && geomData.distanceResults[cpt].min_distance < min_dist)
             {
               min_index = cpt;
-              min_dist = data_geom.distance_results[cpt].distance();
+              min_dist = geomData.distanceResults[cpt].min_distance;
             }
         }
     }
     return min_index;
   }
   
+  // Required to have a default template argument on templated free function
+  inline std::size_t computeDistances(const GeometryModel& geomModel,
+                                      GeometryData & geomData)
+  {
+    return computeDistances<true>(geomModel,geomData);
+  }
+  
   // Required to have a default template argument on templated free function
   inline std::size_t computeDistances(const Model & model,
                                Data & data,
-                               const GeometryModel & model_geom,
-                               GeometryData & data_geom,
+                               const GeometryModel & geomModel,
+                               GeometryData & geomData,
                                const Eigen::VectorXd & q
                                )
   {
-    return computeDistances<true>(model, data, model_geom, data_geom, q);
+    return computeDistances<true>(model, data, geomModel, geomData, q);
   }
 
   template <bool ComputeShortest>
   inline std::size_t computeDistances(const Model & model,
                                Data & data,
-                               const GeometryModel & model_geom,
-                               GeometryData & data_geom,
+                               const GeometryModel & geomModel,
+                               GeometryData & geomData,
                                const Eigen::VectorXd & q
                                )
   {
-    updateGeometryPlacements (model, data, model_geom, data_geom, q);
-    return computeDistances<ComputeShortest>(data_geom);
+    updateGeometryPlacements (model, data, geomModel, geomData, q);
+    return computeDistances<ComputeShortest>(geomModel,geomData);
   }
 
+  /* --- RADIUS -------------------------------------------------------------------- */
+  /* --- RADIUS -------------------------------------------------------------------- */
+  /* --- RADIUS -------------------------------------------------------------------- */
+
   /// Given p1..3 being either "min" or "max", return one of the corners of the 
   /// AABB cub of the FCL object.
 #define SE3_GEOM_AABB(FCL,p1,p2,p3)                                     \
@@ -156,10 +212,12 @@ namespace se3
     BOOST_FOREACH(const GeometryObject & geom,geomModel.geometryObjects)
     {
       const boost::shared_ptr<const fcl::CollisionGeometry> & fcl
-        = geom.collision_geometry;
+        = geom.fcl;
       const SE3 & jMb = geom.placement; // placement in joint.
+      const Model::JointIndex & i = geom.parentJoint;
+      assert (i<geomData.radius.size());
 
-      double radius = geomData.radius[geom.parent];
+      double radius = geomData.radius[i];
 
       // The radius is simply the one of the 8 corners of the AABB cube, expressed 
       // in the joint frame, whose norm is the highest.
@@ -173,14 +231,48 @@ namespace se3
       radius = std::max (jMb.act(SE3_GEOM_AABB(fcl,max,max,max)).squaredNorm(),radius);
 
       // Don't forget to sqroot the squared norm before storing it.
-      assert (geom.parent<geomData.radius.size());
-      geomData.radius[geom.parent] = sqrt(radius);
+      geomData.radius[i] = sqrt(radius);
     }
   }
 
 #undef SE3_GEOM_AABB
 #endif // WITH_HPP_FCL
 
+  /* --- APPEND GEOMETRY MODEL ----------------------------------------------------------- */
+
+  inline void appendGeometryModel(GeometryModel & geomModel1,
+                                  const GeometryModel & geomModel2)
+  {
+    assert (geomModel1.ngeoms == geomModel1.geometryObjects.size());
+    Index nGeom1 = geomModel1.geometryObjects.size();
+    Index nColPairs1 = geomModel1.collisionPairs.size();
+    assert (geomModel2.ngeoms == geomModel2.geometryObjects.size());
+    Index nGeom2 = geomModel2.geometryObjects.size();
+    Index nColPairs2 = geomModel2.collisionPairs.size();
+
+    /// Append the geometry objects and geometry positions
+    geomModel1.geometryObjects.insert(geomModel1.geometryObjects.end(),
+        geomModel2.geometryObjects.begin(), geomModel2.geometryObjects.end());
+    geomModel1.ngeoms += nGeom2;
+
+    /// 1. copy the collision pairs and update geomData1 accordingly.
+    geomModel1.collisionPairs.reserve(nColPairs1 + nColPairs2 + nGeom1 * nGeom2);
+    for (Index i = 0; i < nColPairs2; ++i)
+    {
+      const CollisionPair& cp = geomModel2.collisionPairs[i];
+      geomModel1.collisionPairs.push_back(
+          CollisionPair (cp.first + nGeom1, cp.second + nGeom1)
+          );
+    }
+
+    /// 2. add the collision pairs between geomModel1 and geomModel2.
+    for (Index i = 0; i < nGeom1; ++i) {
+      for (Index j = 0; j < nGeom2; ++j) {
+        geomModel1.collisionPairs.push_back(CollisionPair(i, nGeom1 + j));
+      }
+    }
+  }
+
 } // namespace se3
 
 #endif // ifnded __se3_algo_geometry_hxx__
diff --git a/src/algorithm/jacobian.hxx b/src/algorithm/jacobian.hxx
index 396c54ec036ad4ea97acd7708726dd981b77282b..adae3233e437e02b84a5da1efb49bc0802cf7ca8 100644
--- a/src/algorithm/jacobian.hxx
+++ b/src/algorithm/jacobian.hxx
@@ -59,7 +59,7 @@ namespace se3
   computeJacobians(const Model & model, Data & data,
                    const Eigen::VectorXd & q)
   {
-    for( Model::JointIndex i=1; i< (Model::JointIndex) model.njoint;++i )
+    for( Model::JointIndex i=1; i< (Model::JointIndex) model.njoints;++i )
     {
       JacobiansForwardStep::run(model.joints[i],data.joints[i],
                                 JacobiansForwardStep::ArgsType(model,data,q));
diff --git a/src/algorithm/joint-configuration.hpp b/src/algorithm/joint-configuration.hpp
index a9de210cdf684197a68eacbdbb354b9c4f3ad348..d4a98f35e405fd52e411367811812ae45caa36d7 100644
--- a/src/algorithm/joint-configuration.hpp
+++ b/src/algorithm/joint-configuration.hpp
@@ -71,7 +71,7 @@ namespace se3
    * @param[in]  model      Model we want to compute the distance
    * @param[in]  q0         Configuration 0 (size model.nq)
    * @param[in]  q1         Configuration 1 (size model.nq)
-   * @return     The corresponding distances for each joint (size model.njoint-1 = number of joints)
+   * @return     The corresponding distances for each joint (size model.njoints-1 = number of joints)
    */
   inline Eigen::VectorXd distance(const Model & model,
                                   const Eigen::VectorXd & q0,
@@ -146,7 +146,6 @@ namespace se3
                      const Eigen::VectorXd & v,
                      Eigen::VectorXd & result) 
     {
-     
       jmodel.jointConfigSelector(result) = jmodel.integrate(q, v);
     }
 
@@ -158,7 +157,7 @@ namespace se3
                  const Eigen::VectorXd & v)
   {
     Eigen::VectorXd integ(model.nq);
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       IntegrateStep::run(model.joints[i],
                           IntegrateStep::ArgsType (q, v, integ)
@@ -197,7 +196,7 @@ namespace se3
                const double u)
   {
     Eigen::VectorXd interp(model.nq);
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       InterpolateStep::run(model.joints[i],
                             InterpolateStep::ArgsType (q0, q1, u, interp)
@@ -232,7 +231,7 @@ namespace se3
                      const Eigen::VectorXd & q1)
   {
     Eigen::VectorXd diff(model.nv);
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       DifferentiateStep::run(model.joints[i],
                               DifferentiateStep::ArgsType (q0, q1, diff)
@@ -268,8 +267,8 @@ namespace se3
                const Eigen::VectorXd & q0,
                const Eigen::VectorXd & q1)
   {
-    Eigen::VectorXd distances(model.njoint-1);
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    Eigen::VectorXd distances(model.njoints-1);
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       DistanceStep::run(model.joints[i],
                         DistanceStep::ArgsType (i-1, q0, q1, distances)
@@ -305,7 +304,7 @@ namespace se3
   randomConfiguration(const Model & model, const Eigen::VectorXd & lowerLimits, const Eigen::VectorXd & upperLimits)
   {
     Eigen::VectorXd q(model.nq);
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       RandomConfiguration::run(model.joints[i],
                                RandomConfiguration::ArgsType ( q, lowerLimits, upperLimits)
@@ -338,7 +337,7 @@ namespace se3
   normalize(const Model & model,
             Eigen::VectorXd & q)
   {
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       NormalizeStep::run(model.joints[i],
                          NormalizeStep::ArgsType (q));
@@ -370,7 +369,7 @@ namespace se3
                       const Eigen::VectorXd & q2)
   {
     bool result = false;
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       IsSameConfigurationStep::run(model.joints[i], IsSameConfigurationStep::ArgsType (result,q1,q2)); 
       if( !result )
diff --git a/src/algorithm/kinematics.hxx b/src/algorithm/kinematics.hxx
index 51361b8124fbbd32d042499e16475779fe039e72..efb20a29fdb25e71fc3299af14b45aedab7742d1 100644
--- a/src/algorithm/kinematics.hxx
+++ b/src/algorithm/kinematics.hxx
@@ -44,7 +44,7 @@ namespace se3
   inline void emptyForwardPass(const Model & model,
                                Data & data)
   {
-    for (Model::JointIndex i=1; i < (Model::JointIndex) model.njoint; ++i)
+    for (Model::JointIndex i=1; i < (Model::JointIndex) model.njoints; ++i)
     {
       emptyForwardStep::run(model.joints[i],
                             data.joints[i],
@@ -91,7 +91,7 @@ namespace se3
   {
     assert(q.size() == model.nq && "The configuration vector is not of right size");
     
-    for (Model::JointIndex i=1; i < (Model::JointIndex) model.njoint; ++i)
+    for (Model::JointIndex i=1; i < (Model::JointIndex) model.njoints; ++i)
     {
       ForwardKinematicZeroStep::run(model.joints[i], data.joints[i],
                                     ForwardKinematicZeroStep::ArgsType (model,data,q)
@@ -146,7 +146,7 @@ namespace se3
     
     data.v[0].setZero();
 
-    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i )
     {
       ForwardKinematicFirstStep::run(model.joints[i],data.joints[i],
                                      ForwardKinematicFirstStep::ArgsType(model,data,q,v));
@@ -207,7 +207,7 @@ namespace se3
     data.v[0].setZero();
     data.a[0].setZero();
     
-    for( Model::JointIndex i=1; i < (Model::JointIndex) model.njoint; ++i )
+    for( Model::JointIndex i=1; i < (Model::JointIndex) model.njoints; ++i )
     {
       ForwardKinematicSecondStep::run(model.joints[i],data.joints[i],
                                       ForwardKinematicSecondStep::ArgsType(model,data,q,v,a));
diff --git a/src/algorithm/rnea.hxx b/src/algorithm/rnea.hxx
index b08303b380827dd8b707fb39161c484ff831ced0..f0eeaca52a6413b932737e31611c08596730a1a1 100644
--- a/src/algorithm/rnea.hxx
+++ b/src/algorithm/rnea.hxx
@@ -93,13 +93,13 @@ namespace se3
     data.v[0].setZero();
     data.a_gf[0] = -model.gravity;
 
-    for( Model::JointIndex i=1;i<(Model::JointIndex)model.njoint;++i )
+    for( Model::JointIndex i=1;i<(Model::JointIndex)model.njoints;++i )
     {
       RneaForwardStep::run(model.joints[i],data.joints[i],
                            RneaForwardStep::ArgsType(model,data,q,v,a));
     }
     
-    for( Model::JointIndex i=(Model::JointIndex)model.njoint-1;i>0;--i )
+    for( Model::JointIndex i=(Model::JointIndex)model.njoints-1;i>0;--i )
     {
       RneaBackwardStep::run(model.joints[i],data.joints[i],
                             RneaBackwardStep::ArgsType(model,data));
@@ -174,13 +174,13 @@ namespace se3
     data.v[0].setZero ();
     data.a_gf[0] = -model.gravity;
     
-    for( size_t i=1;i<(size_t) model.njoint;++i )
+    for( size_t i=1;i<(size_t) model.njoints;++i )
     {
       NLEForwardStep::run(model.joints[i],data.joints[i],
                           NLEForwardStep::ArgsType(model,data,q,v));
     }
     
-    for( size_t i=(size_t) (model.njoint-1);i>0;--i )
+    for( size_t i=(size_t) (model.njoints-1);i>0;--i )
     {
       NLEBackwardStep::run(model.joints[i],data.joints[i],
                            NLEBackwardStep::ArgsType(model,data));
diff --git a/src/math/matrix.hpp b/src/math/matrix.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..08e09bb417ac1806d3e708c5a54913d02b9f77de
--- /dev/null
+++ b/src/math/matrix.hpp
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 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/>.
+
+#ifndef __math_matrix_hpp__
+#define __math_matrix_hpp__
+
+#include <Eigen/Dense>
+
+namespace se3
+{
+
+  template<typename Derived>
+  inline bool hasNaN(const Eigen::DenseBase<Derived> & m) 
+  {
+    return !((m.derived().array()==m.derived().array()).all());
+  }
+
+
+}
+#endif //#ifndef __math_matrix_hpp__
diff --git a/src/math/quaternion.hpp b/src/math/quaternion.hpp
index 8f20cc57ba690ddb494ed5bd203869d11bc04bee..aa98d53a7b2e9a699591a80f966cab219141a8b2 100644
--- a/src/math/quaternion.hpp
+++ b/src/math/quaternion.hpp
@@ -61,5 +61,25 @@ namespace se3
     return (q1.coeffs().isApprox(q2.coeffs()) || q1.coeffs().isApprox(-q2.coeffs()) );
   }
 
+  /// Approximately normalize by applying the first order limited development
+  /// of the normalization function.
+  ///
+  /// Only additions and multiplications are required. Neither square root nor
+  /// division are used (except a division by 2).
+  ///
+  /// \warning \f$ ||q||^2 - 1 \f$ should already be close to zero.
+  ///
+  /// \note See
+  /// http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html#title3
+  /// to know the reason why the argument is const.
+  template <typename D> void
+    firstOrderNormalize(const Eigen::QuaternionBase<D> & q)
+  {
+    assert(std::fabs(q.norm() - 1) < 1e-2);
+    typedef typename D::Scalar Scalar;
+    const Scalar alpha = ((Scalar)3 - q.squaredNorm()) / 2;
+    const_cast <Eigen::QuaternionBase<D> &> (q).coeffs() *= alpha;
+  }
+
 }
 #endif //#ifndef __math_quaternion_hpp__
diff --git a/src/multibody/constraint.hpp b/src/multibody/constraint.hpp
index cbb1c72bbdf662abb23a117fc80225cff3a0cff3..450f3403fc218f836c096ea750825599f6ca9a5e 100644
--- a/src/multibody/constraint.hpp
+++ b/src/multibody/constraint.hpp
@@ -181,6 +181,11 @@ namespace se3
       return (m.toActionMatrix()*S).eval();
     }
     
+    DenseBase se3ActionInverse(const SE3 & m) const
+    {
+      return (m.inverse().toActionMatrix()*S).eval();
+    }
+
     void disp_impl(std::ostream & os) const { os << "S =\n" << S << std::endl;}
 
   protected:
diff --git a/src/multibody/fcl.hpp b/src/multibody/fcl.hpp
index 0ba8b92aca7f34c2f64071970ccf52889cd7aa10..1587e4b5a09b248ba39612c4803ed48e79431e75 100644
--- a/src/multibody/fcl.hpp
+++ b/src/multibody/fcl.hpp
@@ -30,7 +30,7 @@
 
 #include <iostream>
 #include <map>
-#include <list>
+#include <vector>
 #include <utility>
 #include <assert.h>
 
@@ -44,116 +44,16 @@ namespace se3
 
     typedef std::pair<GeomIndex, GeomIndex> Base;
    
-    ///
-    /// \brief Default constructor of a collision pair from two collision object indexes.
-    ///        The indexes must be ordered such that co1 < co2. If not, the constructor reverts the indexes.
-    ///
-    /// \param[in] co1 Index of the first collision object
-    /// \param[in] co2 Index of the second collision object
-    ///
-    CollisionPair(const GeomIndex co1, const GeomIndex co2) : Base(co1,co2)
-    {
-      assert(co1 != co2 && "The index of collision objects must not be equal.");
-    }
-
-    bool operator== (const CollisionPair& rhs) const
-    {
-      return (first == rhs.first && second == rhs.second)
-        || (first == rhs.second && second == rhs.first);
-    }
-    
-    void disp(std::ostream & os) const { os << "collision pair (" << first << "," << second << ")\n"; }
-    friend std::ostream & operator << (std::ostream & os, const CollisionPair & X);
+    CollisionPair(const GeomIndex co1, const GeomIndex co2);
+    bool                  operator == (const CollisionPair& rhs) const;
+    void                  disp        (std::ostream & os)        const;
+    friend std::ostream & operator << (std::ostream & os,const CollisionPair & X);
 
   }; // struct CollisionPair
-  typedef std::vector<CollisionPair> CollisionPairsVector_t;
-
-#ifdef WITH_HPP_FCL  
-  /**
-   * @brief      Result of distance computation between two CollisionObjects
-   */
-  struct DistanceResult
-  {
-
-    DistanceResult() : fcl_distance_result(), object1(0), object2(0) {}
-    DistanceResult(fcl::DistanceResult dist_fcl, const GeomIndex co1, const GeomIndex co2)
-    : fcl_distance_result(dist_fcl), object1(co1), object2(co2)
-    {}
-
-
-    ///
-    /// @brief Return the minimal distance between two geometry objects
-    ///
-    double distance () const;
-
-    ///
-    /// \brief Return the witness point on the inner object expressed in global frame.
-    ///
-    Eigen::Vector3d closestPointInner () const;
-    
-    ///
-    /// \brief Return the witness point on the outer object expressed in global frame.
-    ///
-    Eigen::Vector3d closestPointOuter () const;
-    
-    bool operator == (const DistanceResult & other) const
-    {
-      return (distance() == other.distance()
-        && closestPointInner() == other.closestPointInner()
-        && closestPointOuter() == other.closestPointOuter()
-        && object1 == other.object1
-        && object2 == other.object2);
-    }
-    
-    /// \brief The FCL result of the distance computation
-    fcl::DistanceResult fcl_distance_result;
-    
-    /// \brief Index of the first colision object
-    GeomIndex object1;
-
-    /// \brief Index of the second colision object
-    GeomIndex object2;
-    
-  }; // struct DistanceResult 
-  
-
-  /**
-   * @brief      Result of collision computation between two CollisionObjects
-   */
-  struct CollisionResult
-  {
 
-    /**
-     * @brief      Default constrcutor of a CollisionResult
-     *
-     * @param[in]  coll_fcl  The FCL collision result
-     * @param[in]  co1       Index of the first geometry object involved in the computation
-     * @param[in]  co2       Index of the second geometry object involved in the computation
-     */
-    CollisionResult(fcl::CollisionResult coll_fcl, const GeomIndex co1, const GeomIndex co2)
-    : fcl_collision_result(coll_fcl), object1(co1), object2(co2)
-    {}
-    CollisionResult() : fcl_collision_result(), object1(0), object2(0) {}
-
-    bool operator == (const CollisionResult & other) const
-    {
-      return (fcl_collision_result == other.fcl_collision_result
-              && object1 == other.object1
-              && object2 == other.object2);
-    }
-
-    /// \brief The FCL result of the collision computation
-    fcl::CollisionResult fcl_collision_result;
-
-    /// \brief Index of the first collision object
-    GeomIndex object1;
-
-    /// \brief Index of the second collision object
-    GeomIndex object2;
-
-  }; // struct CollisionResult
+  typedef std::vector<CollisionPair> CollisionPairsVector_t;
 
-#else
+#ifndef WITH_HPP_FCL  
 
   namespace fcl
   {
@@ -179,8 +79,7 @@ namespace se3
 enum GeometryType
 {
   VISUAL,
-  COLLISION,
-  NONE
+  COLLISION
 };
 
 struct GeometryObject
@@ -189,44 +88,51 @@ struct GeometryObject
   /// \brief Name of the geometry object
   std::string name;
 
+  /// \brief Index of the parent frame
+  ///
+  /// Parent frame may be unset (set to -1) as it is mostly used as a documentation of the tree, or in third-party libraries.
+  /// The URDF parser of Pinocchio is setting it to the proper value according to the urdf link-joint tree.
+  /// In particular, anchor joints of URDF would cause parent frame to be different to joint frame.
+  FrameIndex parentFrame;
+
   /// \brief Index of the parent joint
-  JointIndex parent;
+  JointIndex parentJoint;
 
   /// \brief The actual cloud of points representing the collision mesh of the object
-  boost::shared_ptr<fcl::CollisionGeometry> collision_geometry;
+  boost::shared_ptr<fcl::CollisionGeometry> fcl;
 
-  /// \brief Position of geometry object in parent joint's frame
+  /// \brief Position of geometry object in parent joint frame
   SE3 placement;
 
   /// \brief Absolute path to the mesh file
-  std::string mesh_path;
-
+  std::string meshPath;
 
-  GeometryObject(const std::string & name, const JointIndex parent, const boost::shared_ptr<fcl::CollisionGeometry> & collision,
-                 const SE3 & placement, const std::string & mesh_path)
+  GeometryObject(const std::string & name, const FrameIndex parentF,
+                 const JointIndex parentJ, const boost::shared_ptr<fcl::CollisionGeometry> & collision,
+                 const SE3 & placement, const std::string & meshPath)
                 : name(name)
-                , parent(parent)
-                , collision_geometry(collision)
+                , parentFrame(parentF)
+                , parentJoint(parentJ)
+                , fcl(collision)
                 , placement(placement)
-                , mesh_path(mesh_path)
+                , meshPath(meshPath)
   {}
 
   GeometryObject & operator=(const GeometryObject & other)
   {
-    name = other.name;
-    parent = other.parent;
-    collision_geometry = other.collision_geometry;
-    placement = other.placement;
-    mesh_path = other.mesh_path;
+    name                = other.name;
+    parentFrame         = other.parentFrame;
+    parentJoint         = other.parentJoint;
+    fcl                 = other.fcl;
+    placement           = other.placement;
+    meshPath            = other.meshPath;
     return *this;
   }
 
-  friend std::ostream & operator<< (std::ostream & os, const GeometryObject & geom_object);
+  friend std::ostream & operator<< (std::ostream & os, const GeometryObject & geomObject);
 };
   
 
-
-
 } // namespace se3
 
 /* --- Details -------------------------------------------------------------- */
diff --git a/src/multibody/fcl.hxx b/src/multibody/fcl.hxx
index 4a5a4070b43b794a77793c6c7c601d57e19888eb..95a7d26ac670d063b74b18465b533246a7d32744 100644
--- a/src/multibody/fcl.hxx
+++ b/src/multibody/fcl.hxx
@@ -25,6 +25,28 @@
 namespace se3
 {
 
+  ///
+  /// \brief Default constructor of a collision pair from two collision object indexes.
+  ///        The indexes must be ordered such that co1 < co2. If not, the constructor reverts the indexes.
+  ///
+  /// \param[in] co1 Index of the first collision object
+  /// \param[in] co2 Index of the second collision object
+  ///
+  inline CollisionPair::CollisionPair(const GeomIndex co1, const GeomIndex co2) 
+    : Base(co1,co2)
+  {
+    assert(co1 != co2 && "The index of collision objects must not be equal.");
+  }
+
+  inline bool CollisionPair::operator== (const CollisionPair& rhs) const
+  {
+    return (first == rhs.first  && second == rhs.second)
+      ||   (first == rhs.second && second == rhs.first );
+  }
+
+  inline void CollisionPair::disp(std::ostream & os) const
+  { os << "collision pair (" << first << "," << second << ")\n"; }
+
   inline std::ostream & operator << (std::ostream & os, const CollisionPair & X)
   {
     X.disp(os); return os;
@@ -33,22 +55,6 @@ namespace se3
 
 #ifdef WITH_HPP_FCL  
 
-
-  inline double DistanceResult::distance () const
-  {
-    return fcl_distance_result.min_distance;
-  }
-
-  inline Eigen::Vector3d DistanceResult::closestPointInner () const
-  {
-    return toVector3d(fcl_distance_result.nearest_points [0]);
-  }
-
-  inline Eigen::Vector3d DistanceResult::closestPointOuter () const
-  {
-    return toVector3d(fcl_distance_result.nearest_points [1]);
-  }
-    
   inline bool operator == (const fcl::CollisionObject & lhs, const fcl::CollisionObject & rhs)
   {
     return lhs.collisionGeometry() == rhs.collisionGeometry()
@@ -57,25 +63,25 @@ namespace se3
   }
   
 #endif // WITH_HPP_FCL
-
   
   inline bool operator==(const GeometryObject & lhs, const GeometryObject & rhs)
   {
-    return ( lhs.name == rhs.name
-            && lhs.parent == rhs.parent
-            && lhs.collision_geometry == rhs.collision_geometry
-            && lhs.placement == rhs.placement
-            && lhs.mesh_path ==  rhs.mesh_path
+    return ( lhs.name           == rhs.name
+            && lhs.parentFrame  == rhs.parentFrame
+            && lhs.parentJoint  == rhs.parentJoint
+            && lhs.fcl          == rhs.fcl
+            && lhs.placement    == rhs.placement
+            && lhs.meshPath     == rhs.meshPath
             );
   }
 
   inline std::ostream & operator<< (std::ostream & os, const GeometryObject & geom_object)
   {
     os  << "Name: \t \n" << geom_object.name << "\n"
-        << "Parent ID: \t \n" << geom_object.parent << "\n"
-        // << "collision object: \t \n" << geom_object.collision_geometry << "\n"
+        << "Parent frame ID: \t \n" << geom_object.parentFrame << "\n"
+        << "Parent joint ID: \t \n" << geom_object.parentJoint << "\n"
         << "Position in parent frame: \t \n" << geom_object.placement << "\n"
-        << "Absolute path to mesh file: \t \n" << geom_object.mesh_path << "\n"
+        << "Absolute path to mesh file: \t \n" << geom_object.meshPath << "\n"
         << std::endl;
     return os;
   }
diff --git a/src/multibody/frame.hpp b/src/multibody/frame.hpp
index 6634f40cab536814685657cfc515593cc8c47ed6..c440277efc64bdc7f9c4cd352512347967a04bc6 100644
--- a/src/multibody/frame.hpp
+++ b/src/multibody/frame.hpp
@@ -33,11 +33,11 @@ namespace se3
   ///
   enum FrameType
   {
-    OP_FRAME, // operational frame type
-    JOINT, // joint frame type
-    FIXED_JOINT, // fixed joint frame type
-    BODY, // body frame type
-    SENSOR // sensor frame type
+    OP_FRAME     = 0x1 << 0, // operational frame type
+    JOINT        = 0x1 << 1, // joint frame type
+    FIXED_JOINT  = 0x1 << 2, // fixed joint frame type
+    BODY         = 0x1 << 3, // body frame type
+    SENSOR       = 0x1 << 4 // sensor frame type
   };
   
   ///
@@ -58,12 +58,14 @@ namespace se3
     ///
     /// \param[in] name Name of the frame.
     /// \param[in] parent Index of the parent joint in the kinematic tree.
+    /// \param[in] previousFrame Index of the parent frame in the kinematic tree.
     /// \param[in] placement Placement of the frame wrt the parent joint frame.
     /// \param[in] type The type of the frame, see the enum FrameType
     ///
-    Frame(const std::string & name, const JointIndex parent, const SE3 & frame_placement, const FrameType type)
+    Frame(const std::string & name, const JointIndex parent, const FrameIndex previousFrame, const SE3 & frame_placement, const FrameType type)
     : name(name)
     , parent(parent)
+    , previousFrame(previousFrame)
     , placement(frame_placement)
     , type(type)
     {}
@@ -76,6 +78,7 @@ namespace se3
     bool operator == (const Frame & other) const
     {
       return name == other.name && parent == other.parent
+      && previousFrame == other.previousFrame
       && placement == other.placement
       && type == other.type ;
     }
@@ -86,14 +89,24 @@ namespace se3
     /// \brief Index of the parent joint.
     JointIndex parent;
     
+    /// \brief Index of the previous frame.
+    FrameIndex previousFrame;
+    
     /// \brief Placement of the frame wrt the parent joint.
     SE3 placement;
 
     /// \brief Type of the frame
     FrameType type;
-    
+
   }; // struct Frame
 
+  inline std::ostream & operator << (std::ostream& os, const Frame & f)
+  {
+    os << "Frame name:" << f.name  << "paired to (parent joint/ previous frame)" << "(" <<f.parent << "/" << f.previousFrame << ")"<< std::endl;
+    os << "with relative placement wrt parent joint:\n" << f.placement << std::endl;
+    return os;
+  }
+
 } // namespace se3
 
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::Frame)
diff --git a/src/multibody/fwd.hpp b/src/multibody/fwd.hpp
index 5d9a3032c6cbe81412d2753a54a07e8c3327583e..29da7ab5e6aa2e8c5e64cc87d75ac58f4d37fef6 100644
--- a/src/multibody/fwd.hpp
+++ b/src/multibody/fwd.hpp
@@ -18,12 +18,15 @@
 #ifndef __se3_multibody_fwd_hpp__
 #define __se3_multibody_fwd_hpp__
 
+# include <cstddef> // std::size_t
+
 namespace se3
 {
   typedef std::size_t Index;
   typedef Index JointIndex;
   typedef Index GeomIndex;
   typedef Index FrameIndex;
+  typedef Index PairIndex;
   
   struct Frame;
   struct Model;
diff --git a/src/multibody/geometry.hpp b/src/multibody/geometry.hpp
index 0a2aedd22e0825d6aa540216f9ea49a63cf43f4a..e9b00f5578b4b1246ec3e8ddf2c79d3af9c5f39b 100644
--- a/src/multibody/geometry.hpp
+++ b/src/multibody/geometry.hpp
@@ -37,9 +37,6 @@ namespace se3
   struct GeometryModel
   {
     
-    typedef std::vector<GeomIndex> GeomIndexList;
-
-    
     /// \brief The number of GeometryObjects
     Index ngeoms;
 
@@ -48,22 +45,12 @@ namespace se3
     ///
     /// \brief Vector of collision pairs.
     ///
-    CollisionPairsVector_t collisionPairs;
+    std::vector<CollisionPair> collisionPairs;
   
-    /// \brief A list of associated collision GeometryObjects to a given joint Id.
-    ///        Inner objects can be seen as geometry objects that directly move when the associated joint moves
-    std::map < JointIndex, GeomIndexList >  innerObjects;
-
-    /// \brief A list of associated collision GeometryObjects to a given joint Id
-    ///        Outer objects can be seen as geometry objects that may often be obstacles to the Inner objects of given joint
-    std::map < JointIndex, GeomIndexList >  outerObjects;
-
     GeometryModel()
       : ngeoms(0)
       , geometryObjects()
       , collisionPairs()
-      , innerObjects()
-      , outerObjects()
     { 
       const std::size_t num_max_collision_pairs = (ngeoms * (ngeoms-1))/2;
       collisionPairs.reserve(num_max_collision_pairs);
@@ -74,19 +61,16 @@ namespace se3
     /**
      * @brief      Add a geometry object to a GeometryModel
      *
-     * @param[in]  parent     Index of the parent joint
-     * @param[in]  co         The actual fcl CollisionGeometry
-     * @param[in]  placement  The relative placement regarding to the parent frame
-     * @param[in]  geom_name  The name of the Geometry Object
-     * @param[in]  mesh_path  The absolute path to the mesh
+     * @param[in]  object     Object 
+     * @param[in]  model      Corresponding model, used to assert the attributes of object.
+     * @param[in]  autofillJointParent if true, set jointParent from frameParent.
      *
      * @return     The index of the new added GeometryObject in geometryObjects
+     * @note object is a nonconst copy to ease the insertion code.
      */
-    inline GeomIndex addGeometryObject(const JointIndex parent, const boost::shared_ptr<fcl::CollisionGeometry> & co,
-                                       const SE3 & placement, const std::string & geom_name = "",
-                                       const std::string & mesh_path = "") throw(std::invalid_argument);
-
-
+    inline GeomIndex addGeometryObject(GeometryObject object,
+                                       const Model & model,
+                                       const bool autofillJointParent = false);
 
     /**
      * @brief      Return the index of a GeometryObject given by its name.
@@ -115,7 +99,7 @@ namespace se3
      *
      * @return     Name of the GeometryObject
      */
-    const std::string & getGeometryName(const GeomIndex index) const;
+    PINOCCHIO_DEPRECATED const std::string & getGeometryName(const GeomIndex index) const;
 
 #ifdef WITH_HPP_FCL
     ///
@@ -129,6 +113,9 @@ namespace se3
     ///
     /// \brief Add all possible collision pairs.
     ///
+    /// \note Collision pairs between geometries of having the same parent joint
+    ///       are not added.
+    ///
     void addAllCollisionPairs();
    
     ///
@@ -159,39 +146,15 @@ namespace se3
     ///
     /// \return The index of the CollisionPair in collisionPairs.
     ///
-    Index findCollisionPair (const CollisionPair & pair) const;
+    PairIndex findCollisionPair (const CollisionPair & pair) const;
     
-    /// \brief Display on std::cout the list of pairs (is it really useful?).
-    void displayCollisionPairs() const;
 #endif // WITH_HPP_FCL
 
-    /**
-     * @brief      Associate a GeometryObject of type COLLISION to a joint's inner objects list
-     *
-     * @param[in]  joint         Index of the joint
-     * @param[in]  inner_object  Index of the GeometryObject that will be an inner object
-     */
-    void addInnerObject(const JointIndex joint, const GeomIndex inner_object);
-    
-    /**
-     * @brief      Associate a GeometryObject of type COLLISION to a joint's outer objects list
-     *
-     * @param[in]  joint         Index of the joint
-     * @param[in]  inner_object  Index of the GeometryObject that will be an outer object
-     */
-    void addOutterObject(const JointIndex joint, const GeomIndex outer_object);
     friend std::ostream& operator<<(std::ostream & os, const GeometryModel & model_geom);
   }; // struct GeometryModel
 
   struct GeometryData
   {
-
-    ///
-    /// \brief A const reference to the model storing all the geometries.
-    ///        See class GeometryModel.
-    ///
-    const GeometryModel & model_geom;
-
     ///
     /// \brief Vector gathering the SE3 placements of the geometry objects relative to the world.
     ///        See updateGeometryPlacements to update the placements.
@@ -200,6 +163,7 @@ namespace se3
     /// for fcl (collision) computation. The copy is done in collisionObjects[i]->setTransform(.)
     ///
     std::vector<se3::SE3> oMg;
+
 #ifdef WITH_HPP_FCL
     ///
     /// \brief Collision objects (ie a fcl placed geometry).
@@ -214,88 +178,90 @@ namespace se3
     ///
     std::vector<bool> activeCollisionPairs;
 
+    ///
+    /// \brief Defines what information should be computed by distance computation.
+    ///
+    fcl::DistanceRequest distanceRequest;
+
     ///
     /// \brief Vector gathering the result of the distance computation for all the collision pairs.
     ///
-    std::vector <DistanceResult> distance_results;
+    std::vector <fcl::DistanceResult> distanceResults;
     
+    ///
+    /// \brief Defines what information should be computed by collision test.
+    ///
+    fcl::CollisionRequest collisionRequest;
+
     ///
     /// \brief Vector gathering the result of the collision computation for all the collision pairs.
     ///
-    std::vector <CollisionResult> collision_results;
+    std::vector <fcl::CollisionResult> collisionResults;
 
     ///
     /// \brief Radius of the bodies, i.e. distance of the further point of the geometry model
     /// attached to the body from the joint center.
     ///
     std::vector<double> radius;
-    GeometryData(const GeometryModel & modelGeom)
-        : model_geom(modelGeom)
-        , oMg(model_geom.ngeoms)
-        , activeCollisionPairs(modelGeom.collisionPairs.size(), true)
-        , distance_results(modelGeom.collisionPairs.size())
-        , collision_results(modelGeom.collisionPairs.size())
-        , radius()
-         
-    {
-      collisionObjects.reserve(modelGeom.geometryObjects.size());
-      BOOST_FOREACH( const GeometryObject & geom, modelGeom.geometryObjects)
-        { collisionObjects.push_back
-            (fcl::CollisionObject(geom.collision_geometry)); }
-    }
-#else
-    GeometryData(const GeometryModel & modelGeom)
-    : model_geom(modelGeom)
-    , oMg(model_geom.ngeoms)
-    {}
-#endif // WITH_HPP_FCL   
-
-
-    ~GeometryData() {};
-#ifdef WITH_HPP_FCL
-    void activateCollisionPair(const Index pairId,const bool flag=true);
-    void deactivateCollisionPair(const Index pairId);
 
     ///
-    /// \brief Compute the collision status between two collision objects of a given collision pair.
-    ///
-    /// \param[in] pair The collsion pair.
+    /// \brief index of the collision pair
     ///
-    /// \return Return true is the collision objects are colliding.
-    ///
-    CollisionResult computeCollision(const CollisionPair & pair) const;
-    
+    /// It is used by some method to return additional information. For instance,
+    /// the algo computeCollisions() sets it to the first colliding pair.
     ///
-    /// \brief Compute the collision result of all the collision pairs according to
-    ///        the current placements of the geometires stored in GeometryData::oMg.
-    ///        The results are stored in the vector GeometryData::collision_results.
-    ///
-    void computeAllCollisions();
-    
-    ///
-    /// \brief Check if at least one of the collision pairs has its two collision objects in collision.
-    ///
-    bool isColliding() const;
+    PairIndex collisionPairIndex;
 
+    typedef std::vector<GeomIndex> GeomIndexList;
+
+    /// \brief Map over vector GeomModel::geometryObjects, indexed by joints.
+    /// 
+    /// The map lists the collision GeometryObjects associated to a given joint Id.
+    ///  Inner objects can be seen as geometry objects that directly move when the associated joint moves
+    std::map < JointIndex, GeomIndexList >  innerObjects;
+
+    /// \brief A list of associated collision GeometryObjects to a given joint Id
     ///
-    /// \brief Compute the minimal distance between collision objects of a collison pair
-    ///
-    /// \param[in] pair The collsion pair.
+    /// Outer objects can be seen as geometry objects that may often be
+    /// obstacles to the Inner objects of given joint
+    std::map < JointIndex, GeomIndexList >  outerObjects;
+#endif // WITH_HPP_FCL   
+
+    GeometryData(const GeometryModel & geomModel);
+    ~GeometryData() {};
+
+#ifdef WITH_HPP_FCL
+
+    /// Fill both innerObjects and outerObjects maps, from vectors collisionObjects and 
+    /// collisionPairs. 
     ///
-    /// \return An fcl struct containing the distance result.
+    /// This simply corresponds to storing in a re-arranged manner the information stored
+    /// in geomModel.geometryObjects and geomModel.collisionPairs.
+    /// \param[in] GeomModel the geometry model (const)
     ///
-    DistanceResult computeDistance(const CollisionPair & pair) const;
-    
+    /// \warning Outer objects are not duplicated (i.e. if a is in outerObjects[b], then
+    /// b is not in outerObjects[a]).
+    void fillInnerOuterObjectMaps(const GeometryModel & geomModel);
+
+    /// Activate a collision pair, for which collisions and distances would now be computed.
     ///
-    /// \brief Compute the distance result for all collision pairs according to
-    ///        the current placements of the geometries stored in GeometryData::oMg.
-    ///        The results are stored in the vector GeometryData::distance_results.
+    /// A collision (resp distance) between to geometries of GeomModel::geometryObjects
+    /// is computed *iff* the corresponding pair has been added in GeomModel::collisionPairs *AND*
+    /// it is active, i.e. the corresponding boolean in GeomData::activePairs is true. The second
+    /// condition can be used to temporarily remove a pair without touching the model, in a versatile
+    /// manner. 
+    /// \param[in] pairId the index of the pair in GeomModel::collisionPairs vector.
+    /// \param[in] new value of the activation boolean (true by default).
+    void activateCollisionPair(const PairIndex pairId,const bool flag=true);
+
+    /// Deactivate a collision pair.
     ///
-    void computeAllDistances();
-    
-    void resetDistances();
+    /// Calls indeed GeomData::activateCollisionPair(pairId,false)
+    /// \sa activateCollisionPair
+    void deactivateCollisionPair(const PairIndex pairId);
+
 #endif //WITH_HPP_FCL
-    friend std::ostream & operator<<(std::ostream & os, const GeometryData & data_geom);
+    friend std::ostream & operator<<(std::ostream & os, const GeometryData & geomData);
     
   }; // struct GeometryData
 
diff --git a/src/multibody/geometry.hxx b/src/multibody/geometry.hxx
index 759575dcd146ff71f24c8ce11d1a1efce769a083..c1a6eff85d2e26793dd88c5fbc47fe7e47c90e0c 100644
--- a/src/multibody/geometry.hxx
+++ b/src/multibody/geometry.hxx
@@ -31,23 +31,50 @@
 
 namespace se3
 {
+  inline GeometryData::GeometryData(const GeometryModel & modelGeom)
+    : oMg(modelGeom.ngeoms)
+
+#ifdef WITH_HPP_FCL   
+    , activeCollisionPairs(modelGeom.collisionPairs.size(), true)
+    , distanceRequest (true, 0, 0, fcl::GST_INDEP)
+    , distanceResults(modelGeom.collisionPairs.size())
+    , collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP)
+    , collisionResults(modelGeom.collisionPairs.size())
+    , radius()
+    , collisionPairIndex(-1)
+    , innerObjects()
+    , outerObjects()
+  {
+    collisionObjects.reserve(modelGeom.geometryObjects.size());
+    BOOST_FOREACH( const GeometryObject & geom, modelGeom.geometryObjects)
+      { collisionObjects.push_back
+          (fcl::CollisionObject(geom.fcl)); }
+    fillInnerOuterObjectMaps(modelGeom);
+  }
+#else
+  {}
+#endif // WITH_HPP_FCL   
 
-  inline GeomIndex GeometryModel::addGeometryObject(const JointIndex parent,
-                                                    const boost::shared_ptr<fcl::CollisionGeometry> & co,
-                                                    const SE3 & placement,
-                                                    const std::string & geom_name,
-                                                    const std::string & mesh_path) throw(std::invalid_argument)
+  inline GeomIndex GeometryModel::addGeometryObject(GeometryObject object,
+                                                    const Model & model,
+                                                    const bool autofillJointParent)
   {
+    // TODO reenable when relevant: assert( (object.parentFrame != -1) || (object.parentJoint != -1) );
+
+    if( autofillJointParent )
+      // TODO: this might be automatically done for some default value of parentJoint (eg ==-1)
+      object.parentJoint = model.frames[object.parentFrame].parent; 
 
-    Index idx = (Index) (ngeoms ++);
+    assert( //TODO: reenable when relevant (object.parentFrame == -1) ||
+           (model.frames[object.parentFrame].type == se3::BODY)  );
+    assert( //TODO: reenable when relevant (object.parentFrame == -1) ||
+           (model.frames[object.parentFrame].parent == object.parentJoint) );
 
-    geometryObjects.push_back(GeometryObject( geom_name, parent, co,
-                                               placement, mesh_path));
-    addInnerObject(parent, idx);
+    GeomIndex idx = (GeomIndex) (ngeoms ++);
+    geometryObjects.push_back(object);
     return idx;
   }
 
-
   inline GeomIndex GeometryModel::getGeometryId(const std::string & name) const
   {
 
@@ -75,50 +102,76 @@ namespace se3
   }
 
 
-  inline void GeometryModel::addInnerObject(const JointIndex joint_id, const GeomIndex inner_object)
-  {
-    if (std::find(innerObjects[joint_id].begin(),
-                  innerObjects[joint_id].end(),
-                  inner_object) == innerObjects[joint_id].end())
-      innerObjects[joint_id].push_back(inner_object);
-    else
-      std::cout << "inner object already added" << std::endl;
-  }
-
-  inline void GeometryModel::addOutterObject (const JointIndex joint, const GeomIndex 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;
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's inner objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an inner object
+     */
+  // inline void GeometryModel::addInnerObject(const JointIndex joint_id, const GeomIndex inner_object)
+  // {
+  //   if (std::find(innerObjects[joint_id].begin(),
+  //                 innerObjects[joint_id].end(),
+  //                 inner_object) == innerObjects[joint_id].end())
+  //     innerObjects[joint_id].push_back(inner_object);
+  //   else
+  //     std::cout << "inner object already added" << std::endl;
+  // }
+
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's outer objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an outer object
+     */
+  // inline void GeometryModel::addOutterObject (const JointIndex joint, const GeomIndex 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 void GeometryData::fillInnerOuterObjectMaps(const GeometryModel & geomModel)
+  {
+    innerObjects.clear();
+    outerObjects.clear();
+
+    for( GeomIndex gid = 0; gid<geomModel.geometryObjects.size(); gid++)
+      innerObjects[geomModel.geometryObjects[gid].parentJoint].push_back(gid);
+
+    BOOST_FOREACH( const CollisionPair & pair, geomModel.collisionPairs )
+      {
+        outerObjects[geomModel.geometryObjects[pair.first].parentJoint].push_back(pair.second);
+      }
   }
 
-  inline std::ostream & operator<< (std::ostream & os, const GeometryModel & model_geom)
+  inline std::ostream & operator<< (std::ostream & os, const GeometryModel & geomModel)
   {
-    os << "Nb geometry objects = " << model_geom.ngeoms << std::endl;
+    os << "Nb geometry objects = " << geomModel.ngeoms << std::endl;
     
-    for(Index i=0;i<(Index)(model_geom.ngeoms);++i)
+    for(GeomIndex i=0;i<(GeomIndex)(geomModel.ngeoms);++i)
     {
-      os  << model_geom.geometryObjects[i] <<std::endl;
+      os  << geomModel.geometryObjects[i] <<std::endl;
     }
 
     return os;
   }
 
-  inline std::ostream & operator<< (std::ostream & os, const GeometryData & data_geom)
+  inline std::ostream & operator<< (std::ostream & os, const GeometryData & geomData)
   {
 #ifdef WITH_HPP_FCL
-    os << "Nb collision pairs = " << data_geom.activeCollisionPairs.size() << std::endl;
+    os << "Nb collision pairs = " << geomData.activeCollisionPairs.size() << std::endl;
     
-    for(Index i=0;i<(Index)(data_geom.activeCollisionPairs.size());++i)
+    for(PairIndex i=0;i<(PairIndex)(geomData.activeCollisionPairs.size());++i)
     {
-      os << "collision object in position " << data_geom.model_geom.collisionPairs[i] << std::endl;
+      os << "Pairs " << i << (geomData.activeCollisionPairs[i]?"active":"unactive") << std::endl;
     }
 #else
     os << "WARNING** Without fcl, no collision computations are possible. Only Positions can be computed" << std::endl;
-    os << "Nb of geometry objects = " << data_geom.oMg.size() << std::endl;
+    os << "Nb of geometry objects = " << geomData.oMg.size() << std::endl;
 #endif
 
     return os;
@@ -135,9 +188,16 @@ namespace se3
   inline void GeometryModel::addAllCollisionPairs()
   {
     removeAllCollisionPairs();
-    for (Index i = 0; i < ngeoms; ++i)
-      for (Index j = i+1; j < ngeoms; ++j)
-        addCollisionPair(CollisionPair(i,j));
+    for (GeomIndex i = 0; i < ngeoms; ++i)
+    {
+      const JointIndex& joint_i = geometryObjects[i].parentJoint;
+      for (GeomIndex j = i+1; j < ngeoms; ++j)
+      {
+        const JointIndex& joint_j = geometryObjects[j].parentJoint;
+        if (joint_i != joint_j)
+          addCollisionPair(CollisionPair(i,j));
+      }
+    }
   }
   
   inline void GeometryModel::removeCollisionPair (const CollisionPair & pair)
@@ -159,100 +219,27 @@ namespace se3
                       pair) != collisionPairs.end());
   }
   
-  inline Index GeometryModel::findCollisionPair (const CollisionPair & pair) const
+  inline PairIndex GeometryModel::findCollisionPair (const CollisionPair & pair) const
   {
     CollisionPairsVector_t::const_iterator it = std::find(collisionPairs.begin(),
                                                           collisionPairs.end(),
                                                           pair);
     
-    return (Index) distance(collisionPairs.begin(), it);
-  }
-
-  inline void GeometryModel::displayCollisionPairs() const
-  {
-    for (CollisionPairsVector_t::const_iterator it = collisionPairs.begin(); 
-         it != collisionPairs.end(); ++it)
-      {
-        std::cout << it-> first << "\t" << it->second << std::endl;
-      }
+    return (PairIndex) std::distance(collisionPairs.begin(), it);
   }
 
-  inline void GeometryData::activateCollisionPair(const Index pairId,const bool flag)
+  inline void GeometryData::activateCollisionPair(const PairIndex pairId,const bool flag)
   {
-    assert( activeCollisionPairs.size() == model_geom.collisionPairs.size() );
     assert( pairId < activeCollisionPairs.size() );
     activeCollisionPairs[pairId] = flag;
   }
 
-  inline void GeometryData::deactivateCollisionPair(const Index pairId)
+  inline void GeometryData::deactivateCollisionPair(const PairIndex pairId)
   {
-    assert( activeCollisionPairs.size() == model_geom.collisionPairs.size() );
     assert( pairId < activeCollisionPairs.size() );
     activeCollisionPairs[pairId] = false;
   }
 
-  inline CollisionResult GeometryData::computeCollision(const CollisionPair & pair) const
-  {
-    const Index & co1 = pair.first;     assert(co1<collisionObjects.size());
-    const Index & co2 = pair.second;    assert(co2<collisionObjects.size());
-
-    fcl::CollisionRequest collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP);
-    fcl::CollisionResult collisionResult;
-
-    fcl::collide (&collisionObjects[co1],&collisionObjects[co2],
-                  collisionRequest, collisionResult);
-
-    return CollisionResult (collisionResult, co1, co2);
-  }
-  
-  inline void GeometryData::computeAllCollisions()
-  {
-    assert( activeCollisionPairs.size() == model_geom.collisionPairs.size() );
-    assert( collision_results   .size() == model_geom.collisionPairs.size() );
-    for(size_t i = 0; i<model_geom.collisionPairs.size(); ++i)
-    {
-      if(activeCollisionPairs[i])
-        { collision_results[i] = computeCollision(model_geom.collisionPairs[i]); }
-    }
-  }
-  
-  inline bool GeometryData::isColliding() const
-  {
-    for(size_t i = 0; i<model_geom.collisionPairs.size(); ++i)
-    {
-      if (activeCollisionPairs[i] 
-          && computeCollision(model_geom.collisionPairs[i]).fcl_collision_result.isCollision())
-        return true;
-    }
-    return false;
-  }
-
-  inline DistanceResult GeometryData::computeDistance(const CollisionPair & pair) const
-  {
-    const Index & co1 = pair.first;     assert(co1<collisionObjects.size());
-    const Index & co2 = pair.second;    assert(co2<collisionObjects.size());
-    
-    fcl::DistanceRequest distanceRequest (true, 0, 0, fcl::GST_INDEP);
-    fcl::DistanceResult result;
-    fcl::distance ( &collisionObjects[co1],&collisionObjects[co2],
-                    distanceRequest, result);
-    
-    return DistanceResult (result, co1, co2);
-  }
-  
-  inline void GeometryData::computeAllDistances ()
-  {
-    for(size_t i = 0; i<activeCollisionPairs.size(); ++i)
-    {
-      if (activeCollisionPairs[i])
-        distance_results[i] = computeDistance(model_geom.collisionPairs[i]);
-    }
-  }
-
-  inline void GeometryData::resetDistances()
-  {
-    std::fill(distance_results.begin(), distance_results.end(), DistanceResult( fcl::DistanceResult(), 0, 0) );
-  }
 #endif //WITH_HPP_FCL
 } // namespace se3
 
diff --git a/src/multibody/joint/joint-base.hpp b/src/multibody/joint/joint-base.hpp
index d5f2a83a410114d933c13dffb516465cc6d28005..8950273c4eb5ab47da295cfb514b894c1fb7b13a 100644
--- a/src/multibody/joint/joint-base.hpp
+++ b/src/multibody/joint/joint-base.hpp
@@ -399,7 +399,9 @@ namespace se3
     int  idx_v() const { return i_v; }
     JointIndex id() const { return i_id; }
 
-    void setIndexes(JointIndex id,int q,int v) { i_id = id, i_q = q; i_v = v; }
+    void setIndexes(JointIndex id, int q, int v) { derived().setIndexes_impl(id, q, v); }
+    
+    void setIndexes_impl(JointIndex id,int q,int v) { i_id = id, i_q = q; i_v = v; }
     
     void disp(std::ostream & os) const
     {
diff --git a/src/multibody/joint/joint-basic-visitors.hpp b/src/multibody/joint/joint-basic-visitors.hpp
index 9aa612990297fa4b1dc0716b4d73823922386e28..bcaf830478692801d41ae4b37941a6221ce5ab8f 100644
--- a/src/multibody/joint/joint-basic-visitors.hpp
+++ b/src/multibody/joint/joint-basic-visitors.hpp
@@ -19,9 +19,9 @@
 #define __se3_joint_basic_visitors_hpp__
 
 #include <Eigen/StdVector>
-#include <boost/variant.hpp>
 #include "pinocchio/multibody/joint/joint-variant.hpp"
 
+
 namespace se3
 {
   
@@ -108,6 +108,16 @@ namespace se3
                                      const double u);
 
   
+  /**
+   * @brief       Visit a JointModelVariant through JointRandomVisitor to
+   *              generate a random configuration vector
+   *
+   * @param[in]  jmodel           The JointModelVariant
+   *
+   * @return     The joint randomconfiguration
+   */
+  inline Eigen::VectorXd random(const JointModelVariant & jmodel);
+
   /**
    * @brief       Visit a JointModelVariant through JointRandomConfigurationVisitor to
    *              generate a configuration vector uniformly sampled among provided limits
@@ -343,7 +353,8 @@ namespace se3
 
 
 /* --- Details -------------------------------------------------------------------- */
-#include "pinocchio/multibody/joint/joint-basic-visitors.hxx"
+// Included later
+// #include "pinocchio/multibody/joint/joint-basic-visitors.hxx"
 
 
 #endif // ifndef __se3_joint_basic_visitors_hpp__
diff --git a/src/multibody/joint/joint-basic-visitors.hxx b/src/multibody/joint/joint-basic-visitors.hxx
index ecb549b4ea5f511dc97d3660356501e682d1acca..a155bb2d21d3c8ef9df270381c24e3abaf5a7316 100644
--- a/src/multibody/joint/joint-basic-visitors.hxx
+++ b/src/multibody/joint/joint-basic-visitors.hxx
@@ -19,7 +19,8 @@
 #define __se3_joint_basic_visitors_hxx__
 
 #include "pinocchio/assert.hpp"
-#include "pinocchio/multibody/joint/joint-variant.hpp"
+#include "pinocchio/multibody/joint/joint-basic-visitors.hpp"
+#include "pinocchio/multibody/joint/joint-composite.hpp"
 #include "pinocchio/multibody/visitor.hpp"
 
 namespace se3
@@ -192,6 +193,25 @@ namespace se3
     return JointInterpolateVisitor::run(jmodel, q0, q1, u);
   }
 
+  /**
+   * @brief      JointRandomVisitor visitor
+   */
+  class JointRandomVisitor: public boost::static_visitor<Eigen::VectorXd>
+  {
+  public:
+
+    template<typename D>
+    Eigen::VectorXd operator()(const JointModelBase<D> & jmodel) const
+    { return jmodel.random(); }
+    
+    static Eigen::VectorXd run(const JointModelVariant & jmodel)
+    { return boost::apply_visitor( JointRandomVisitor(), jmodel ); }
+  };
+  inline Eigen::VectorXd random(const JointModelVariant & jmodel)
+  {
+    return JointRandomVisitor::run(jmodel);
+  }
+
   /**
    * @brief      JointRandomConfigurationVisitor visitor
    */
@@ -348,8 +368,8 @@ namespace se3
   {
   public:
     template<typename D>
-    int operator()(const JointModelBase<D> & ) const
-    { return D::NV; }
+    int operator()(const JointModelBase<D> & jmodel) const
+    { return jmodel.nv(); }
     
     static int run( const JointModelVariant & jmodel)
     { return boost::apply_visitor( JointNvVisitor(), jmodel ); }
@@ -364,8 +384,8 @@ namespace se3
   {
   public:
     template<typename D>
-    int operator()(const JointModelBase<D> & ) const
-    { return D::NQ; }
+    int operator()(const JointModelBase<D> & jmodel) const
+    { return jmodel.nq(); }
     
     static int run( const JointModelVariant & jmodel)
     { return boost::apply_visitor( JointNqVisitor(), jmodel ); }
diff --git a/src/multibody/joint/joint-composite.hpp b/src/multibody/joint/joint-composite.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..01ed3d89d7b62f3741ba6ec239c96fc421d4ea3f
--- /dev/null
+++ b/src/multibody/joint/joint-composite.hpp
@@ -0,0 +1,481 @@
+//
+// Copyright (c) 2016 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terljMj 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_joint_composite_hpp__
+#define __se3_joint_composite_hpp__
+
+#include "pinocchio/assert.hpp"
+#include "pinocchio/multibody/joint/joint.hpp"
+
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::SE3)
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::Motion)
+
+namespace se3
+{
+
+  struct JointComposite;
+  struct JointModelComposite;
+  struct JointDataComposite;
+
+  template<>
+  struct traits<JointComposite>
+  {
+
+    enum {
+      NQ = Eigen::Dynamic,
+      NV = Eigen::Dynamic
+    };
+    typedef double Scalar;
+    typedef JointDataComposite JointDataDerived;
+    typedef JointModelComposite JointModelDerived;
+    typedef ConstraintXd Constraint_t;
+    typedef SE3 Transformation_t;
+    typedef Motion Motion_t;
+    typedef Motion Bias_t;
+
+    typedef Eigen::Matrix<double,6,Eigen::Dynamic> F_t;
+    // [ABA]
+    typedef Eigen::Matrix<double,6,Eigen::Dynamic> U_t;
+    typedef Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> D_t;
+    typedef Eigen::Matrix<double,6,Eigen::Dynamic> UD_t;
+
+    typedef Eigen::Matrix<double,Eigen::Dynamic,1> ConfigVector_t;
+    typedef Eigen::Matrix<double,Eigen::Dynamic,1> TangentVector_t;
+  };
+  template<> struct traits<JointDataComposite> { typedef JointComposite JointDerived; };
+  template<> struct traits<JointModelComposite> { typedef JointComposite JointDerived; };
+
+  struct JointDataComposite : public JointDataBase<JointDataComposite> 
+  {
+    typedef JointComposite Joint;
+    SE3_JOINT_TYPEDEF;
+
+    JointDataVector joints;
+    int nq_composite,nv_composite;
+
+    Constraint_t S;
+    std::vector<Transformation_t> ljMj;
+    Transformation_t M;
+    Motion_t v;
+    Bias_t c;
+
+    
+    // // [ABA] specific data
+    U_t U;
+    D_t Dinv;
+    UD_t UDinv;
+
+
+    // JointDataComposite()  {} // can become necessary if we want a vector of JointDataComposite ?
+    JointDataComposite( JointDataVector & joints, int nq, int nv )
+    : joints(joints)
+    , nq_composite(nq)
+    , nv_composite(nv)
+    , S(Eigen::MatrixXd::Zero(6, nv_composite))
+    , ljMj(joints.size())
+    , M(Transformation_t::Identity())
+    , v(Motion_t::Zero())
+    , c(Bias_t::Zero())
+    , U(Eigen::MatrixXd::Zero(6, nv_composite))
+    , Dinv(Eigen::MatrixXd::Zero(nv_composite, nv_composite))
+    , UDinv(Eigen::MatrixXd::Zero(6, nv_composite))
+    {}
+
+  };
+
+  struct JointModelComposite : public JointModelBase<JointModelComposite> 
+  {
+    typedef JointComposite Joint;
+    SE3_JOINT_TYPEDEF;
+    SE3_JOINT_USE_INDEXES;
+    using JointModelBase<JointModelComposite>::id;
+    using JointModelBase<JointModelComposite>::setIndexes;
+
+    std::size_t max_joints;
+    JointModelVector joints;
+    int nq_composite,nv_composite;
+
+    // Same as JointModelComposite(1)
+    JointModelComposite() : max_joints(1)
+                          , joints(0)
+                          , nq_composite(0)
+                          , nv_composite(0)
+                          {} 
+    JointModelComposite(std::size_t max_number_of_joints) : max_joints(max_number_of_joints)
+                                                          , joints(0)
+                                                          , nq_composite(0)
+                                                          , nv_composite(0)
+                                                          {} 
+    
+    template <typename D1>
+    JointModelComposite(const JointModelBase<D1> & jmodel1) : max_joints(1)
+                                                            , joints(0)
+                                                            , nq_composite(jmodel1.nq())
+                                                            , nv_composite(jmodel1.nv())
+    {
+        joints.push_back(JointModel(jmodel1.derived()));
+    }
+
+    template <typename D1, typename D2 >
+    JointModelComposite(const JointModelBase<D1> & jmodel1, const JointModelBase<D2> & jmodel2)
+    : max_joints(2)
+    , joints(0)
+    , nq_composite(jmodel1.nq() + jmodel2.nq())
+    , nv_composite(jmodel1.nv() + jmodel2.nv())
+    {
+      joints.push_back(JointModel(jmodel1.derived()));
+      joints.push_back(JointModel(jmodel2.derived()));
+    }
+    
+    template <typename D1, typename D2, typename D3 >
+    JointModelComposite(const JointModelBase<D1> & jmodel1,
+                        const JointModelBase<D2> & jmodel2,
+                        const JointModelBase<D3> & jmodel3)
+    : max_joints(3)
+    , joints(0)
+    , nq_composite(jmodel1.nq() + jmodel2.nq() + jmodel3.nq())
+    , nv_composite(jmodel1.nv() + jmodel2.nv() + jmodel3.nv())
+    {
+      joints.push_back(JointModel(jmodel1.derived()));
+      joints.push_back(JointModel(jmodel2.derived()));
+      joints.push_back(JointModel(jmodel3.derived()));
+    }
+
+    // JointModelComposite( const JointModelVector & models ) : max_joints(models.size()) , joints(models) {}
+    
+    template < typename D>
+    std::size_t addJointModel(const JointModelBase<D> & jmodel)
+    {
+      std::size_t nb_joints = joints.size();
+      if (!isFull())
+      {
+        joints.push_back(JointModel(jmodel.derived()));
+        nq_composite += jmodel.nq();
+        nv_composite += jmodel.nv();
+        nb_joints = joints.size();
+      }
+      return nb_joints;
+    }
+
+    bool isFull() const
+    {
+      return joints.size() == max_joints ; 
+    }
+
+    bool isEmpty() const
+    {
+      return joints.size() <= 0 ; 
+    }
+    JointDataDerived createData() const
+    {
+      JointDataVector res;
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        res.push_back(::se3::createData(*i));
+      }
+      return JointDataDerived(res, nq_composite, nv_composite);
+    }
+
+
+    void calc (JointDataDerived & data,
+               const Eigen::VectorXd & qs) const
+    {
+      data.M.setIdentity();
+      for (JointDataVector::iterator i = data.joints.begin(); i != data.joints.end(); ++i)
+      {
+        JointDataVector::iterator::difference_type index = i - data.joints.begin();
+        calc_zero_order(joints[(std::size_t)index], *i, qs);
+        data.ljMj[(std::size_t)index] = joint_transform(*i);
+        data.M =  data.M * data.ljMj[(std::size_t)index];
+      }
+    }
+
+    void calc (JointDataDerived & data,
+               const Eigen::VectorXd & qs,
+               const Eigen::VectorXd & vs ) const
+    {
+      data.M.setIdentity();
+      data.v.setZero();
+      data.c.setZero();
+      data.S.matrix().setZero();
+      for (JointDataVector::iterator i = data.joints.begin(); i != data.joints.end(); ++i)
+      {
+        JointDataVector::iterator::difference_type index = i - data.joints.begin();
+        calc_first_order(joints[(std::size_t)index], *i, qs, vs);
+        data.ljMj[(std::size_t)index] = joint_transform(*i);
+        data.M = data.M * data.ljMj[(std::size_t)index];
+        data.v = motion(*i);
+        if (i == data.joints.begin())
+        {}
+        else 
+        {
+          data.v += data.ljMj[(std::size_t)index].actInv(motion(*(i-1)));
+        }
+      }
+
+      data.c = bias(data.joints[joints.size()-1]);
+      int start_col = nv_composite;
+      int sub_constraint_dimension = (int)constraint_xd(data.joints[joints.size()-1]).matrix().cols();
+      start_col -= sub_constraint_dimension;
+      data.S.matrix().middleCols(start_col,sub_constraint_dimension) = constraint_xd(data.joints[joints.size()-1]).matrix();
+
+      SE3 iMcomposite(SE3::Identity());
+      for (JointDataVector::reverse_iterator i = data.joints.rbegin()+1; i != data.joints.rend(); ++i)
+      {
+        sub_constraint_dimension = (int)constraint_xd(*i).matrix().cols();
+        start_col -= sub_constraint_dimension;
+
+        iMcomposite = joint_transform(*(i+0)) * iMcomposite;
+        data.S.matrix().middleCols(start_col,sub_constraint_dimension) = iMcomposite.actInv(constraint_xd(*(i+0)));
+
+        Motion acceleration_d_entrainement_coriolis = Motion::Zero(); // TODO: compute
+        data.c += iMcomposite.actInv(bias(*i)) + acceleration_d_entrainement_coriolis;
+      }
+    }
+   
+    
+    void calc_aba(JointDataDerived & data, Inertia::Matrix6 & I, const bool update_I) const
+    {
+    // calc has been called previously in abaforwardstep1 so data.M, data.v are up to date
+      data.U.setZero();
+      data.Dinv.setZero();
+      data.UDinv.setZero();
+      for (JointDataVector::iterator i = data.joints.begin(); i != data.joints.end(); ++i)
+      {
+        JointDataVector::iterator::difference_type index = i - data.joints.begin();
+        ::se3::calc_aba(joints[(std::size_t)index], *i, I, false);
+      }
+      data.U = I * data.S;
+      Eigen::MatrixXd tmp = data.S.matrix().transpose() * I * data.S.matrix();
+      data.Dinv = tmp.inverse();
+      data.UDinv = data.U * data.Dinv;
+
+      if (update_I)
+        I -= data.UDinv * data.U.transpose();
+    }
+
+    Scalar finiteDifferenceIncrement() const
+    {
+      using std::sqrt;
+      return 2.*sqrt(sqrt(Eigen::NumTraits<Scalar>::epsilon()));
+    }
+
+    ConfigVector_t integrate_impl(const Eigen::VectorXd & qs,const Eigen::VectorXd & vs) const
+    {
+      ConfigVector_t result(Eigen::VectorXd::Zero(nq_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_q(*i),::se3::nq(*i)) += ::se3::integrate(*i,qs,vs);
+      }
+      return result;
+    }
+
+    ConfigVector_t interpolate_impl(const Eigen::VectorXd & q0,const Eigen::VectorXd & q1, const double u) const
+    {
+      ConfigVector_t result(Eigen::VectorXd::Zero(nq_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_q(*i),::se3::nq(*i)) += ::se3::interpolate(*i,q0,q1,u);
+      }
+      return result;
+    }
+
+    ConfigVector_t random_impl() const
+    { 
+      ConfigVector_t result(Eigen::VectorXd::Zero(nq_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_q(*i),::se3::nq(*i)) += ::se3::random(*i);
+      }
+      return result;
+    } 
+
+    ConfigVector_t randomConfiguration_impl(const ConfigVector_t & lower_pos_limit, const ConfigVector_t & upper_pos_limit ) const throw (std::runtime_error)
+    { 
+      ConfigVector_t result(Eigen::VectorXd::Zero(nq_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_q(*i),::se3::nq(*i)) += 
+                                ::se3::randomConfiguration(*i,
+                                                          lower_pos_limit.segment(::se3::idx_q(*i), ::se3::nq(*i)),
+                                                          upper_pos_limit.segment(::se3::idx_q(*i), ::se3::nq(*i))
+                                                          );
+      }
+      return result;
+    } 
+
+    TangentVector_t difference_impl(const Eigen::VectorXd & q0,const Eigen::VectorXd & q1) const
+    { 
+      TangentVector_t result(Eigen::VectorXd::Zero(nv_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_v(*i),::se3::nv(*i)) += ::se3::difference(*i,q0,q1);
+      }
+      return result;
+    } 
+
+    double distance_impl(const Eigen::VectorXd & q0,const Eigen::VectorXd & q1) const
+    { 
+      return difference_impl(q0,q1).norm();
+    }
+
+    void normalize_impl(Eigen::VectorXd & q) const
+    {
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        ::se3::normalize(*i,q);
+      } 
+    }
+
+    ConfigVector_t neutralConfiguration_impl() const
+    { 
+      ConfigVector_t result(Eigen::VectorXd::Zero(nq_composite));
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        result.segment(::se3::idx_q(*i),::se3::nq(*i)) += ::se3::neutralConfiguration(*i);
+      }
+      return result;
+    } 
+
+    bool isSameConfiguration_impl(const Eigen::VectorXd& q1, const Eigen::VectorXd& q2, const Scalar & = Eigen::NumTraits<Scalar>::dummy_precision()) const
+    {
+      for (JointModelVector::const_iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        if ( !::se3::isSameConfiguration(*i, q1, q2) )
+          return false;
+      }
+      return true;
+    }
+
+    int     nv_impl() const { return nv_composite; }
+    int     nq_impl() const { return nq_composite; }
+
+
+    /**
+     * @brief      Update the indexes of subjoints in the stack 
+     */
+    void updateComponentsIndexes()
+    {
+      int current_idx_q, current_idx_v;
+      int next_idx_q = idx_q();
+      int next_idx_v = idx_v();
+
+      for (JointModelVector::iterator i = joints.begin(); i != joints.end(); ++i)
+      {
+        current_idx_q = next_idx_q;
+        current_idx_v = next_idx_v;
+        ::se3::setIndexes(*i,id(),current_idx_q, current_idx_v);
+        next_idx_q = current_idx_q + ::se3::nq(*i);
+        next_idx_v = current_idx_v + ::se3::nv(*i);
+      }
+    }
+
+    void setIndexes_impl(JointIndex id, int q, int v)
+    {
+      JointModelBase<JointModelComposite>::setIndexes_impl(id, q, v);
+      updateComponentsIndexes();
+    }
+
+    static std::string classname() { return std::string("JointModelComposite"); }
+    std::string shortname() const { return classname(); }
+
+    template <class D>
+    bool operator == (const JointModelBase<D> &) const
+    {
+      return false;
+    }
+    
+    bool operator == (const JointModelBase<JointModelComposite> & jmodel) const
+    {
+      return jmodel.id() == id()
+              && jmodel.idx_q() == idx_q()
+              && jmodel.idx_v() == idx_v();
+    }
+
+    // see http://en.cppreference.com/w/cpp/language/copy_assignment#Copy-and-swap_idiom
+    void swap(JointModelComposite & other) {
+      max_joints   = other.max_joints;
+      nq_composite = other.nq_composite;
+      nv_composite = other.nv_composite;
+
+      joints.swap(other.joints);
+    }
+
+    JointModelComposite& operator=(JointModelComposite other)
+    {
+        swap(other);
+        return *this;
+    }
+
+    template<typename D>
+    typename SizeDepType<NQ>::template SegmentReturn<D>::ConstType
+    jointConfigSelector(const Eigen::MatrixBase<D>& a) const { return a.segment(i_q,nq_composite); }
+    template<typename D>
+    typename SizeDepType<NQ>::template SegmentReturn<D>::Type
+    jointConfigSelector( Eigen::MatrixBase<D>& a) const { return a.segment(i_q,nq_composite); }
+
+    template<typename D>
+    typename SizeDepType<NV>::template SegmentReturn<D>::ConstType
+    jointVelocitySelector(const Eigen::MatrixBase<D>& a) const { return a.segment(i_v,nv_composite);  }
+    template<typename D>
+    typename SizeDepType<NV>::template SegmentReturn<D>::Type
+    jointVelocitySelector( Eigen::MatrixBase<D>& a) const { return a.segment(i_v,nv_composite);  }
+
+    template<typename D>
+    typename SizeDepType<NV>::template ColsReturn<D>::ConstType 
+    jointCols(const Eigen::MatrixBase<D>& A) const { return A.segment(i_v,nv_composite);  }
+    template<typename D>
+    typename SizeDepType<NV>::template ColsReturn<D>::Type 
+    jointCols(Eigen::MatrixBase<D>& A) const { return A.segment(i_v,nv_composite);  }
+
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template SegmentReturn<D>::ConstType
+    jointConfigSelector_impl(const Eigen::MatrixBase<D>& a) const { return a.segment(i_q,nq_composite); }
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template SegmentReturn<D>::Type
+    jointConfigSelector_impl(Eigen::MatrixBase<D>& a) const { return a.segment(i_q,nq_composite); }
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template SegmentReturn<D>::ConstType
+    jointVelocitySelector_impl(const Eigen::MatrixBase<D>& a) const { return a.segment(i_v,nv_composite); }
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template SegmentReturn<D>::Type
+    jointVelocitySelector_impl(Eigen::MatrixBase<D>& a) const { return a.segment(i_v,nv_composite); }
+
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template ColsReturn<D>::ConstType 
+    jointCols_impl(const Eigen::MatrixBase<D>& A) const { return A.middleCols(i_v,nv_composite); }
+    template<typename D>
+    typename SizeDepType<Eigen::Dynamic>::template ColsReturn<D>::Type 
+    jointCols_impl(Eigen::MatrixBase<D>& A) const { return A.middleCols(i_v,nv_composite); }
+
+  };
+  
+
+    inline std::ostream & operator << (std::ostream & os, const JointModelComposite & jmodel)
+    {
+      os << "JointModelComposite containing following models:\n" ;
+      for (JointModelVector::const_iterator i = jmodel.joints.begin(); i != jmodel.joints.end(); ++i)
+      {
+        os << shortname(*i) << std::endl;
+      }
+      return os;
+    }
+
+} // namespace se3
+
+
+#endif // ifndef __se3_joint_composite_hpp__
diff --git a/src/multibody/joint/joint-free-flyer.hpp b/src/multibody/joint/joint-free-flyer.hpp
index da0228de63b4079f40b013f9c90402dce0995b79..f5f9e444c2442cf95e27ebb7c0de4037810829a6 100644
--- a/src/multibody/joint/joint-free-flyer.hpp
+++ b/src/multibody/joint/joint-free-flyer.hpp
@@ -21,6 +21,7 @@
 
 #include "pinocchio/spatial/inertia.hpp"
 #include "pinocchio/multibody/joint/joint-base.hpp"
+#include "pinocchio/multibody/joint/joint-dense.hpp"
 #include "pinocchio/multibody/constraint.hpp"
 #include "pinocchio/spatial/explog.hpp"
 #include "pinocchio/math/fwd.hpp"
@@ -207,11 +208,11 @@ namespace se3
     template<typename V>
     inline void forwardKinematics(Transformation_t & M, const Eigen::MatrixBase<V> & q_joint) const
     {
+      EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,V);
       using std::sqrt;
       typedef Eigen::Map<const Motion_t::Quaternion_t> ConstQuaternionMap_t;
-      typename Eigen::MatrixBase<V>::template ConstFixedSegmentReturnType<NQ>::Type & q = q_joint.template segment<NQ> (idx_q ());
 
-      ConstQuaternionMap_t quat(q.template tail<4>().data());
+      ConstQuaternionMap_t quat(q_joint.template tail<4>().data());
       assert(std::fabs(quat.coeffs().norm()-1.) <= sqrt(Eigen::NumTraits<typename V::Scalar>::epsilon()));
       
       M.rotation(quat.matrix());
@@ -274,12 +275,17 @@ namespace se3
       res.head<3>() = M1.translation();
       QuaternionMap_t res_quat(res.tail<4>().data());
       res_quat = M1.rotation();
+      // Norm of qs might be epsilon-different to 1, so M1.rotation might be epsilon-different to a rotation matrix.
+      // It is then safer to re-normalized after converting M1.rotation to quaternion.
+      firstOrderNormalize(res_quat);
       
       return res;
     } 
 
     ConfigVector_t interpolate_impl(const Eigen::VectorXd & q0, const Eigen::VectorXd & q1, const double u) const
     {
+      typedef Eigen::Map<Motion_t::Quaternion_t> QuaternionMap_t;
+      
       Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_0 = q0.segment<NQ> (idx_q ());
       Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_1 = q1.segment<NQ> (idx_q ());
 
@@ -287,8 +293,21 @@ namespace se3
       else if( u == 1.) return q_1;
       else
       {
+        // TODO: If integrate takes an arguments (ConfigVector_t, TangentVector_t), then we can merely do:
+        // TangentVector_t nu(u*difference(q0, q1));
+        // return integrate(q0, nu);
+
         TangentVector_t nu(u*difference(q0, q1));
-        return integrate(q0, nu);
+        Transformation_t M0; forwardKinematics(M0,q_0);
+        Transformation_t M1(M0*exp6(Motion_t(nu)));
+
+        ConfigVector_t res;
+        res.head<3>() = M1.translation();
+        QuaternionMap_t res_quat(res.tail<4>().data());
+        res_quat = M1.rotation();
+        firstOrderNormalize(res_quat);
+        
+        return res;
       }
     }
 
@@ -337,8 +356,8 @@ namespace se3
 
     TangentVector_t difference_impl(const Eigen::VectorXd & q0, const Eigen::VectorXd & q1) const
     {
-      Transformation_t M0(Transformation_t::Identity()); forwardKinematics(M0, q0);
-      Transformation_t M1(Transformation_t::Identity()); forwardKinematics(M1, q1);
+      Transformation_t M0(Transformation_t::Identity()); forwardKinematics(M0, q0.segment<NQ> (idx_q ()));
+      Transformation_t M1(Transformation_t::Identity()); forwardKinematics(M1, q1.segment<NQ> (idx_q ()));
 
       return se3::log6(M0.inverse()*M1);
     } 
diff --git a/src/multibody/joint/joint-prismatic-unaligned.hpp b/src/multibody/joint/joint-prismatic-unaligned.hpp
index 0be8e5522736996632dcec087318f8aeaa5b620d..01668ed0d8b2b87397c991fcab8560a82478abdf 100644
--- a/src/multibody/joint/joint-prismatic-unaligned.hpp
+++ b/src/multibody/joint/joint-prismatic-unaligned.hpp
@@ -341,10 +341,7 @@ namespace se3
     {
       const double & q = qs[idx_q()];
 
-      /* It should not be necessary to copy axis in jdata, however a current bug
-       * in the fusion visitor prevents a proper access to jmodel::axis. A
-       * by-pass is to access to a copy of it in jdata. */
-      data.M.translation() = data.S.axis * q;
+      data.M.translation() = axis * q;
     }
 
     void calc(JointDataDerived & data,
@@ -354,17 +351,14 @@ namespace se3
       const Scalar & q = qs[idx_q()];
       const Scalar & v = vs[idx_v()];
 
-      /* It should not be necessary to copy axis in jdata, however a current bug
-       * in the fusion visitor prevents a proper access to jmodel::axis. A
-       * by-pass is to access to a copy of it in jdata. */
-      data.M.translation() = data.S.axis * q;
+      data.M.translation() = axis * q;
       data.v.v = v;
     }
     
     void calc_aba(JointDataDerived & data, Inertia::Matrix6 & I, const bool update_I) const
     {
-      data.U = I.block<6,3> (0,Inertia::LINEAR) * data.S.axis;
-      data.Dinv[0] = 1./data.S.axis.dot(data.U.segment <3> (Inertia::LINEAR));
+      data.U = I.block<6,3> (0,Inertia::LINEAR) * axis;
+      data.Dinv[0] = 1./axis.dot(data.U.segment <3> (Inertia::LINEAR));
       data.UDinv = data.U * data.Dinv;
       
       if (update_I)
diff --git a/src/multibody/joint/joint-prismatic.hpp b/src/multibody/joint/joint-prismatic.hpp
index 10a806addf1085e313137f8611a58e2a669bfab1..fc6d001d82387774b74a88434ef2573c2c37a96e 100644
--- a/src/multibody/joint/joint-prismatic.hpp
+++ b/src/multibody/joint/joint-prismatic.hpp
@@ -482,7 +482,7 @@ namespace se3
       const Scalar & q_0 = q0[idx_q()];
       const Scalar & q_1 = q1[idx_q()];
 
-      ConfigVector_t result;
+      TangentVector_t result;
       result << (q_1 - q_0);
       return result; 
     } 
diff --git a/src/multibody/joint/joint-revolute-unaligned.hpp b/src/multibody/joint/joint-revolute-unaligned.hpp
index 6dd3817ea8699b29ead71a3fa6a5d8ed9b5a2464..2e122a07d88c1ec7e5ef1625319d66a3e3923cc3 100644
--- a/src/multibody/joint/joint-revolute-unaligned.hpp
+++ b/src/multibody/joint/joint-revolute-unaligned.hpp
@@ -289,7 +289,6 @@ namespace se3
     Bias_t c;
 
     F_t F;
-    Eigen::AngleAxisd angleaxis;
     
     // [ABA] specific data
     U_t U;
@@ -298,13 +297,11 @@ namespace se3
 
     JointDataRevoluteUnaligned() 
       : M(1),S(Eigen::Vector3d::Constant(NAN)),v(Eigen::Vector3d::Constant(NAN),NAN)
-      , angleaxis( NAN,Eigen::Vector3d::Constant(NAN))
       , U(), Dinv(), UDinv()
     {}
     
     JointDataRevoluteUnaligned(const Motion::Vector3 & axis) 
       : M(1),S(axis),v(axis,NAN)
-      , angleaxis(NAN,axis)
       , U(), Dinv(), UDinv()
     {}
 
@@ -342,12 +339,8 @@ namespace se3
 	       const Eigen::VectorXd & qs ) const
     {
       const double & q = qs[idx_q()];
-
-      /* It should not be necessary to copy axis in jdata, however a current bug
-       * in the fusion visitor prevents a proper access to jmodel::axis. A
-       * by-pass is to access to a copy of it in jdata. */
-      data.angleaxis.angle() = q;
-      data.M.rotation(data.angleaxis.toRotationMatrix());
+      
+      data.M.rotation(Eigen::AngleAxisd(q, axis).toRotationMatrix());
     }
 
     void calc( JointDataDerived& data, 
@@ -357,18 +350,15 @@ namespace se3
       const double & q = qs[idx_q()];
       const double & v = vs[idx_v()];
 
-      /* It should not be necessary to copy axis in jdata, however a current bug
-       * in the fusion visitor prevents a proper access to jmodel::axis. A
-       * by-pass is to access to a copy of it in jdata. */
-      data.angleaxis.angle() = q;
-      data.M.rotation(data.angleaxis.toRotationMatrix());
+      data.M.rotation(Eigen::AngleAxisd(q, axis).toRotationMatrix());
+
       data.v.w = v;
     }
     
     void calc_aba(JointDataDerived & data, Inertia::Matrix6 & I, const bool update_I) const
     {
-      data.U = I.block<6,3> (0,Inertia::ANGULAR) * data.angleaxis.axis();
-      data.Dinv[0] = 1./data.angleaxis.axis().dot(data.U.segment <3> (Inertia::ANGULAR));
+      data.U = I.block<6,3> (0,Inertia::ANGULAR) * axis;
+      data.Dinv[0] = 1./axis.dot(data.U.segment <3> (Inertia::ANGULAR));
       data.UDinv = data.U * data.Dinv;
       
       if (update_I)
diff --git a/src/multibody/joint/joint-revolute-unbounded.hpp b/src/multibody/joint/joint-revolute-unbounded.hpp
index 69089ef9caf9a555c7da4cf428f7766ba7a21fc3..259ad52583577bb8f4702c6bdc6eb75aa754ffa6 100644
--- a/src/multibody/joint/joint-revolute-unbounded.hpp
+++ b/src/multibody/joint/joint-revolute-unbounded.hpp
@@ -18,6 +18,7 @@
 #ifndef __se3_joint_revolute_unbounded_hpp__
 #define __se3_joint_revolute_unbounded_hpp__
 
+#include "pinocchio/math/fwd.hpp"
 #include "pinocchio/math/sincos.hpp"
 #include "pinocchio/spatial/inertia.hpp"
 #include "pinocchio/multibody/joint/joint-base.hpp"
@@ -157,10 +158,11 @@ namespace se3
       double cosOmega,sinOmega; SINCOS(omega, &sinOmega, &cosOmega);
       // TODO check the cost of atan2 vs SINCOS
 
-      ConfigVector_t result;
-      result <<
-      cosOmega * ca - sinOmega * sa,
-      sinOmega * ca + cosOmega * sa;
+      ConfigVector_t result (cosOmega * ca - sinOmega * sa,
+                             sinOmega * ca + cosOmega * sa);
+      const double norm2 = q.squaredNorm();
+      result *= (3 - norm2) / 2;
+
       return result;
     }
 
diff --git a/src/multibody/joint/joint-spherical.hpp b/src/multibody/joint/joint-spherical.hpp
index f299cf1bb9f13518afaf8f5c5e7093b068e9d766..fdbf086c5a3d9e412cf443f081ee93ad368423f4 100644
--- a/src/multibody/joint/joint-spherical.hpp
+++ b/src/multibody/joint/joint-spherical.hpp
@@ -271,10 +271,10 @@ namespace se3
     template<typename V>
     inline void forwardKinematics(Transformation_t & M, const Eigen::MatrixBase<V> & q_joint) const
     {
+      EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,V);
       using std::sqrt;
-      typename Eigen::MatrixBase<V>::template ConstFixedSegmentReturnType<NQ>::Type & q = q_joint.template segment<NQ> (idx_q ());
 
-      ConstQuaternionMap_t quat(q.data());
+      ConstQuaternionMap_t quat(q_joint.derived().data());
       assert(std::fabs(quat.coeffs().norm()-1.) <= sqrt(Eigen::NumTraits<typename V::Scalar>::epsilon()));
       
       M.rotation(quat.matrix());
@@ -335,6 +335,7 @@ namespace se3
 
       Motion_t::Quaternion_t pOmega(se3::exp3(q_dot));
       Motion_t::Quaternion_t quaternion_result(q*pOmega);
+      firstOrderNormalize(quaternion_result);
       
       return quaternion_result.coeffs();
     }
@@ -385,8 +386,8 @@ namespace se3
 
     TangentVector_t difference_impl(const Eigen::VectorXd & q0,const Eigen::VectorXd & q1) const
     {
-      Transformation_t M0; forwardKinematics(M0, q0);
-      Transformation_t M1; forwardKinematics(M1, q1);
+      Transformation_t M0; forwardKinematics(M0, q0.segment<NQ>(idx_q()));
+      Transformation_t M1; forwardKinematics(M1, q1.segment<NQ>(idx_q()));
 
       return se3::log3((M0.rotation().transpose()*M1.rotation()).eval());
       
diff --git a/src/multibody/joint/joint-variant.hpp b/src/multibody/joint/joint-variant.hpp
index c748da1819a5db60a405ea0deb6ddff08572f821..b1e2b43c278cd683229d7d33b618e4bdd9a67f26 100644
--- a/src/multibody/joint/joint-variant.hpp
+++ b/src/multibody/joint/joint-variant.hpp
@@ -31,16 +31,33 @@
 #include "pinocchio/multibody/joint/joint-spherical.hpp"
 #include "pinocchio/multibody/joint/joint-translation.hpp"
 
-#include <Eigen/StdVector>
 #include <boost/variant.hpp>
+#include <boost/variant/recursive_wrapper.hpp>
 
 namespace se3
 {
   enum { MAX_JOINT_NV = 6 };
 
-  typedef boost::variant< JointModelRX, JointModelRY, JointModelRZ, JointModelRevoluteUnaligned, JointModelSpherical, JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ, JointModelPrismaticUnaligned, JointModelFreeFlyer, JointModelPlanar, JointModelTranslation, JointModelDense<-1,-1>, JointModelRUBX, JointModelRUBY, JointModelRUBZ > JointModelVariant;
-  typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ, JointDataRevoluteUnaligned, JointDataSpherical, JointDataSphericalZYX, JointDataPX, JointDataPY, JointDataPZ, JointDataPrismaticUnaligned, JointDataFreeFlyer, JointDataPlanar, JointDataTranslation, JointDataDense<-1,-1>, JointDataRUBX, JointDataRUBY, JointDataRUBZ > JointDataVariant;
-  
+  struct JointComposite;
+  struct JointModelComposite;
+  struct JointDataComposite;
+
+  // The JointModelComposite contains several JointModel (which are JointModelVariant). Hence there is a circular
+  // dependency between JointModelComposite and JointModelVariant that can be resolved with the use of boost::recursive_variant
+  // For more details, see http://www.boost.org/doc/libs/1_58_0/doc/html/variant/tutorial.html#variant.tutorial.recursive 
+  //
+  // The same applies for JointDataComposite
+  typedef boost::variant< JointModelRX, JointModelRY, JointModelRZ, JointModelRevoluteUnaligned, JointModelSpherical,
+                          JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ,
+                          JointModelPrismaticUnaligned, JointModelFreeFlyer, JointModelPlanar, JointModelTranslation,
+                          JointModelDense<-1,-1> ,JointModelRUBX, JointModelRUBY, JointModelRUBZ,
+                          boost::recursive_wrapper<JointModelComposite> >JointModelVariant;
+  typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ, JointDataRevoluteUnaligned, JointDataSpherical,
+                          JointDataSphericalZYX, JointDataPX, JointDataPY, JointDataPZ, JointDataPrismaticUnaligned,
+                          JointDataFreeFlyer, JointDataPlanar, JointDataTranslation, JointDataDense<-1,-1>,
+                          JointDataRUBX, JointDataRUBY, JointDataRUBZ,
+                          boost::recursive_wrapper<JointDataComposite> > JointDataVariant;
+
 } // namespace se3
 
 #endif // ifndef __se3_joint_variant_hpp__
diff --git a/src/multibody/joint/joint.hpp b/src/multibody/joint/joint.hpp
index 84f2637d437996b16e871c3b46baad7acdfb6a2a..34b8f2074ece0f9719556c9bec3234c805e89a94 100644
--- a/src/multibody/joint/joint.hpp
+++ b/src/multibody/joint/joint.hpp
@@ -20,7 +20,7 @@
 
 #include "pinocchio/assert.hpp"
 #include "pinocchio/multibody/joint/joint-variant.hpp"
-#include "pinocchio/multibody/joint/joint-basic-visitors.hpp"
+#include "pinocchio/multibody/joint/joint-basic-visitors.hxx"
 
 namespace se3
 {
diff --git a/src/multibody/model.hpp b/src/multibody/model.hpp
index 8e38896c6bccaafe4278f5ca088f422822008077..a11b2218cb91df1c205c8b7b4499d5b9213c7721 100644
--- a/src/multibody/model.hpp
+++ b/src/multibody/model.hpp
@@ -26,16 +26,15 @@
 #include "pinocchio/spatial/inertia.hpp"
 #include "pinocchio/multibody/fwd.hpp"
 #include "pinocchio/multibody/frame.hpp"
-#include "pinocchio/multibody/joint/joint.hpp"
+#include "pinocchio/multibody/joint/joint-composite.hpp"
 #include "pinocchio/deprecated.hh"
+#include "pinocchio/tools/string-generator.hpp"
 
 #include <iostream>
 #include <Eigen/Cholesky>
 
-EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::SE3)
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::Inertia)
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::Force)
-EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::Motion)
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix<double,6,Eigen::Dynamic>)
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix<double,6,6>)
 EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(se3::SE3::Vector3)
@@ -58,13 +57,13 @@ namespace se3
     int nv;
     
     /// \brief Number of joints.
-    int njoint;
+    int njoints;
 
     /// \brief Number of bodies.
-    int nbody;
+    int nbodies;
     
     /// \brief Number of operational frames.
-    int nFrames;
+    int nframes;
 
     /// \brief Spatial inertias of the body <i> expressed in the supporting joint frame <i>.
     std::vector<Inertia> inertias;
@@ -112,23 +111,62 @@ namespace se3
     Model()
       : nq(0)
       , nv(0)
-      , njoint(1)
-      , nbody(1)
-      , nFrames(0)
+      , njoints(1)
+      , nbodies(1)
+      , nframes(0)
       , inertias(1)
-      , jointPlacements(1)
+      , jointPlacements(1, SE3::Identity())
       , joints(1)
-      , parents(1)
+      , parents(1, 0)
       , names(1)
       , subtrees(1)
       , gravity( gravity981,Eigen::Vector3d::Zero() )
     {
       names[0]     = "universe";     // Should be "universe joint (trivial)"
+      // FIXME Should the universe joint be a FIXED_JOINT even if it is
+      // in the list of joints ? See comment in definition of
+      // Model::addJointFrame and Model::addBodyFrame
+      addFrame(Frame("universe", 0, 0, SE3::Identity(), FIXED_JOINT));
+      // Inertia of universe has no sense.
+      inertias[0].mass() = std::numeric_limits<double>::quiet_NaN();
+      inertias[0].lever().fill (std::numeric_limits<double>::quiet_NaN());
+      inertias[0].inertia().fill (std::numeric_limits<double>::quiet_NaN());
     }
     ~Model() {} // std::cout << "Destroy model" << std::endl; }
     
     ///
-    /// \brief Add a joint to the kinematic tree.
+    /// \brief Add a joint to the kinematic tree with given bounds.
+    ///
+    /// \remark This method does not add a Frame of same name to the vector of frames.
+    ///         Use Model::addJointFrame.
+    /// \remark The inertia supported by the joint is set to Zero.
+    ///
+    /// \tparam JointModelDerived The type of the joint model.
+    ///
+    /// \param[in] parent Index of the parent joint.
+    /// \param[in] joint_model The joint model.
+    /// \param[in] joint_placement Placement of the joint inside its parent joint.
+    /// \param[in] joint_name Name of the joint. If empty, the name is random.
+    /// \param[in] max_effort Maximal joint torque.
+    /// \param[in] max_velocity Maximal joint velocity.
+    /// \param[in] min_config Lower joint configuration.
+    /// \param[in] max_config Upper joint configuration.
+    ///
+    /// \return The index of the new joint.
+    ///
+    /// \sa Model::appendBodyToJoint, Model::addJointFrame
+    ///
+    template<typename JointModelDerived>
+    JointIndex addJoint(const JointIndex parent, const JointModelBase<JointModelDerived> & joint_model, const SE3 & joint_placement,
+                        const Eigen::VectorXd & max_effort,
+                        const Eigen::VectorXd & max_velocity,
+                        const Eigen::VectorXd & min_config,
+                        const Eigen::VectorXd & max_config,
+                        const std::string & joint_name = ""
+                        );
+
+    ///
+    /// \brief Add a joint to the kinematic tree with infinite bounds.
     ///
     /// \remark This method also adds a Frame of same name to the vector of frames.
     /// \remark The inertia supported by the joint is set to Zero.
@@ -139,10 +177,6 @@ namespace se3
     /// \param[in] joint_model The joint model.
     /// \param[in] joint_placement Placement of the joint inside its parent joint.
     /// \param[in] joint_name Name of the joint. If empty, the name is random.
-    /// \param[in] max_effort Maximal joint torque. (Default set to infinity).
-    /// \param[in] max_velocity Maximal joint velocity. (Default set to infinity).
-    /// \param[in] min_config Lower joint configuration. (Default set to infinity).
-    /// \param[in] max_config Upper joint configuration. (Default set to infinity).
     ///
     /// \return The index of the new joint.
     ///
@@ -150,28 +184,48 @@ namespace se3
     ///
     template<typename JointModelDerived>
     JointIndex addJoint(const JointIndex parent, const JointModelBase<JointModelDerived> & joint_model, const SE3 & joint_placement,
-                        const std::string & joint_name = "",
-                        const Eigen::VectorXd & max_effort = Eigen::VectorXd::Constant(JointModelDerived::NV,std::numeric_limits<double>::max()),
-                        const Eigen::VectorXd & max_velocity = Eigen::VectorXd::Constant(JointModelDerived::NV,std::numeric_limits<double>::max()),
-                        const Eigen::VectorXd & min_config = Eigen::VectorXd::Constant(JointModelDerived::NQ,std::numeric_limits<double>::min()),
-                        const Eigen::VectorXd & max_config = Eigen::VectorXd::Constant(JointModelDerived::NQ,std::numeric_limits<double>::max())
+                        const std::string & joint_name = ""
                         );
 
     ///
-    /// \brief Append a body to a given joint of the kinematic tree.
+    /// \brief Add a joint to the frame tree.
     ///
-    /// \remark This method also adds a Frame of same name to the vector of frames.
+    /// \param[in] jointIndex Index of the joint.
+    /// \param[in] frameIndex Index of the parent frame. If negative,
+    ///            the parent frame is the frame of the parent joint.
+    ///
+    /// \return The index of the new frame or -1 in case of error.
+    ///
+    int addJointFrame (const JointIndex& jointIndex,
+                             int         frameIndex = -1);
+
+    ///
+    /// \brief Append a body to a given joint of the kinematic tree.
     ///
     /// \param[in] joint_index Index of the supporting joint.
     /// \param[in] Y Spatial inertia of the body.
     /// \param[in] body_placement The relative placement of the body regarding to the parent joint. Set default to the Identity placement.
-    /// \param[in] body_name Name of the body. If empty, the name is random.
     ///
     /// \sa Model::addJoint
     ///
     void appendBodyToJoint(const JointIndex joint_index, const Inertia & Y,
-                           const SE3 & body_placement = SE3::Identity(),
-                           const std::string & body_name = "");
+                           const SE3 & body_placement = SE3::Identity());
+
+    ///
+    /// \brief Add a body to the frame tree.
+    ///
+    /// \param[in] body_name Name of the body.
+    /// \param[in] parentJoint Index of the parent joint.
+    /// \param[in] body_placement The relative placement of the body regarding to the parent joint. Set default to the Identity placement.
+    /// \param[in] previousFrame Index of the parent frame. If negative,
+    ///            the parent frame is the frame of the parent joint.
+    ///
+    /// \return The index of the new frame or -1 in case of error.
+    ///
+    int addBodyFrame (const std::string & body_name,
+                      const JointIndex  & parentJoint,
+                      const SE3         & body_placement = SE3::Identity(),
+                            int           previousFrame  = -1);
 
     ///
     /// \brief Return the index of a body given by its name.
@@ -195,14 +249,6 @@ namespace se3
     ///
     bool existBodyName(const std::string & name) const;
     
-    ///
-    /// \brief Get the name of a body given by its index.
-    ///
-    /// \param[in] index Index of the body.
-    ///
-    /// \return Name of the body.
-    ///
-    const std::string & getBodyName(const JointIndex index) const;
     
     ///
     /// \brief Return the index of a joint given by its name.
@@ -232,7 +278,7 @@ namespace se3
     ///
     /// \return Name of the joint.
     ///
-    const std::string & getJointName(const JointIndex index) const;
+    PINOCCHIO_DEPRECATED const std::string & getJointName(const JointIndex index) const;
 
     ///
     /// \brief Returns the index of a frame given by its name.
@@ -243,103 +289,32 @@ namespace se3
     /// (for example to get the id of a parent frame).
     /// 
     /// \param[in] name Name of the frame.
+    /// \param[in] type Type of the frame.
     ///
     /// \return Index of the frame.
     ///
-    FrameIndex getFrameId (const std::string & name) const;
+    FrameIndex getFrameId (const std::string & name, const FrameType& type = (FrameType) (JOINT | FIXED_JOINT | BODY | OP_FRAME | SENSOR )) const;
     
     ///
     /// \brief Checks if a frame given by its name exists.
     ///
     /// \param[in] name Name of the frame.
+    /// \param[in] type Type of the frame.
     ///
     /// \return Returns true if the frame exists.
     ///
-    bool existFrame (const std::string & name) const;
-    
-    ///
-    /// \brief Get the name of a frame given by its index.
-    ///
-    /// \param[in] index Index of the frame.
-    ///
-    /// \return The name of the frame.
-    ///
-    PINOCCHIO_DEPRECATED const std::string & getFrameName (const FrameIndex index) const;
-    
-    ///
-    /// \brief Get the index of the joint supporting the frame given by its name.
-    ///
-    /// \param[in] name Name of the frame.
-    ///
-    /// \return
-    ///
-    PINOCCHIO_DEPRECATED JointIndex getFrameParent(const std::string & name) const;
+    bool existFrame (const std::string & name, const FrameType& type = (FrameType) (JOINT | FIXED_JOINT | BODY | OP_FRAME | SENSOR )) const;
     
-    ///
-    /// \brief Get the index of the joint supporting the frame given by its index.
-    ///
-    /// \param[in] index Index of the frame.
-    ///
-    /// \return
-    ///
-    PINOCCHIO_DEPRECATED JointIndex getFrameParent(const FrameIndex index) const;
-
-    ///
-    /// \brief Get the type of the frame given by its index.
-    ///
-    /// \param[in] name Name of the frame.
-    ///
-    /// \return
-    ///
-    PINOCCHIO_DEPRECATED FrameType getFrameType(const std::string & name) const;
     
-    ///
-    /// \brief Get the type of the frame given by its index.
-    ///
-    /// \param[in] index Index of the frame.
-    ///
-    /// \return
-    ///
-    PINOCCHIO_DEPRECATED FrameType getFrameType(const FrameIndex index) const;
-    
-    ///
-    /// \brief Return the relative placement between a frame and its supporting joint.
-    ///
-    /// \param[in] name Name of the frame.
-    ///
-    /// \return The frame placement regarding the supporing joint.
-    ///
-    PINOCCHIO_DEPRECATED const SE3 & getFramePlacement(const std::string & name) const;
-    
-    ///
-    /// \brief Return the relative placement between a frame and its supporting joint.
-    ///
-    /// \param[in] index Index of the frame.
-    ///
-    /// \return The frame placement regarding the supporing joint.
-    ///
-    PINOCCHIO_DEPRECATED const SE3 & getFramePlacement(const FrameIndex index) const;
-
     ///
     /// \brief Adds a frame to the kinematic tree.
     ///
     /// \param[in] frame The frame to add to the kinematic tree.
     ///
-    /// \return Returns true if the frame has been successfully added.
-    ///
-    bool addFrame(const Frame & frame);
-    
-    ///
-    /// \brief Creates and adds a frame to the kinematic tree.
-    ///
-    /// \param[in] name Name of the frame.
-    /// \param[in] parent Index of the supporting joint.
-    /// \param[in] placement Placement of the frame regarding to the joint frame.
-    /// \param[in] type The type of the frame
-    ///
-    /// \return Returns true if the frame has been successfully added.
+    /// \return Returns the index of the frame if it has been successfully added,
+    ///         -1 otherwise.
     ///
-    PINOCCHIO_DEPRECATED bool addFrame(const std::string & name, const JointIndex parent, const SE3 & placement, const FrameType type = OP_FRAME);
+    int addFrame(const Frame & frame);
 
     /// Check the validity of the attributes of Model with respect to the specification of some
     /// algorithms.
@@ -530,7 +505,7 @@ namespace se3
     ///
     /// \param[in] model The model structure of the rigid body system.
     ///
-    Data (const Model & model);
+    explicit Data (const Model & model);
 
   private:
     void computeLastChild(const Model& model);
diff --git a/src/multibody/model.hxx b/src/multibody/model.hxx
index cee1244d40aa2ff1b7125739c832d8783357cff7..8b21b59a1c91f307feda2860778161c1352fa726 100644
--- a/src/multibody/model.hxx
+++ b/src/multibody/model.hxx
@@ -23,15 +23,28 @@
 #include "pinocchio/tools/string-generator.hpp"
 
 #include <boost/bind.hpp>
+#include <boost/utility.hpp>
 
 /// @cond DEV
 
 namespace se3
 {
+  namespace details
+  {
+    struct FilterFrame {
+      const std::string& name;
+      const FrameType & typeMask;
+      FilterFrame (const std::string& name, const FrameType& typeMask)
+        : name (name), typeMask (typeMask) {}
+      bool operator() (const Frame& frame) const
+      { return (typeMask & frame.type) && (name == frame.name); }
+    };
+  }
+
   inline std::ostream& operator<< (std::ostream & os, const Model & model)
   {
-    os << "Nb joints = " << model.njoint << " (nq="<< model.nq<<",nv="<<model.nv<<")" << std::endl;
-    for(Model::Index i=0;i<(Model::Index)(model.njoint);++i)
+    os << "Nb joints = " << model.njoints << " (nq="<< model.nq<<",nv="<<model.nv<<")" << std::endl;
+    for(Model::Index i=0;i<(Model::Index)(model.njoints);++i)
     {
       os << "  Joint "<< model.names[i] << ": parent=" << model.parents[i]  << std::endl;
     }
@@ -43,24 +56,24 @@ namespace se3
   Model::JointIndex Model::addJoint(const Model::JointIndex parent,
                                     const JointModelBase<JointModelDerived> & joint_model,
                                     const SE3 & joint_placement,
-                                    const std::string & joint_name,
                                     const Eigen::VectorXd & max_effort,
                                     const Eigen::VectorXd & max_velocity,
                                     const Eigen::VectorXd & min_config,
-                                    const Eigen::VectorXd & max_config
+                                    const Eigen::VectorXd & max_config,
+                                    const std::string & joint_name
                                     )
   {
     typedef JointModelDerived D;
-    assert( (njoint==(int)joints.size())&&(njoint==(int)inertias.size())
-           &&(njoint==(int)parents.size())&&(njoint==(int)jointPlacements.size()) );
+    assert( (njoints==(int)joints.size())&&(njoints==(int)inertias.size())
+           &&(njoints==(int)parents.size())&&(njoints==(int)jointPlacements.size()) );
     assert((joint_model.nq()>=0) && (joint_model.nv()>=0));
-    
+
     assert(max_effort.size() == joint_model.nv()
            && max_velocity.size() == joint_model.nv()
            && min_config.size() == joint_model.nq()
            && max_config.size() == joint_model.nq());
     
-    Model::JointIndex idx = (Model::JointIndex) (njoint++);
+    Model::JointIndex idx = (Model::JointIndex) (njoints++);
     
     joints         .push_back(JointModel(joint_model.derived()));
     boost::get<JointModelDerived>(joints.back()).setIndexes(idx,nq,nv);
@@ -71,18 +84,18 @@ namespace se3
     names          .push_back((joint_name!="")?joint_name:randomStringGenerator(8));
     nq += joint_model.nq();
     nv += joint_model.nv();
-    
-    effortLimit.conservativeResize(nv);effortLimit.bottomRows<D::NV>() = max_effort;
-    velocityLimit.conservativeResize(nv);velocityLimit.bottomRows<D::NV>() = max_velocity;
-    lowerPositionLimit.conservativeResize(nq);lowerPositionLimit.bottomRows<D::NQ>() = min_config;
-    upperPositionLimit.conservativeResize(nq);upperPositionLimit.bottomRows<D::NQ>() = max_config;
+
+    // Optimal efficiency here would be using the static-dim bottomRows, while specifying the dimension in argument in the case where D::NV is Eigen::Dynamic.
+    // However, this option is not compiling in Travis (why?).
+    // As efficiency of Model::addJoint is not critical, the dynamic bottomRows is used here.
+    effortLimit.conservativeResize(nv);effortLimit.bottomRows(joint_model.nv()) = max_effort;
+    velocityLimit.conservativeResize(nv);velocityLimit.bottomRows(joint_model.nv()) = max_velocity;
+    lowerPositionLimit.conservativeResize(nq);lowerPositionLimit.bottomRows(joint_model.nq()) = min_config;
+    upperPositionLimit.conservativeResize(nq);upperPositionLimit.bottomRows(joint_model.nq()) = max_config;
     
     neutralConfiguration.conservativeResize(nq);
     neutralConfiguration.tail(joint_model.nq()) = joint_model.neutralConfiguration();
     
-    // Add a the joint frame attached to itself to the frame vector - redundant information but useful.
-    addFrame(names[idx],idx,SE3::Identity(),JOINT);
-    
     // Init and add joint index to its parent subtrees.
     subtrees.push_back(IndexVector(1));
     subtrees[idx][0] = idx;
@@ -90,33 +103,71 @@ namespace se3
     return idx;
   }
 
+  template<typename JointModelDerived>
+  Model::JointIndex Model::addJoint(const Model::JointIndex parent,
+                                    const JointModelBase<JointModelDerived> & joint_model,
+                                    const SE3 & joint_placement,
+                                    const std::string & joint_name
+                                    )
+  {
+    typedef JointModelDerived D;
+    Eigen::VectorXd max_effort, max_velocity, min_config, max_config;
+
+    max_effort = Eigen::VectorXd::Constant(joint_model.nv(), std::numeric_limits<double>::max());
+    max_velocity = Eigen::VectorXd::Constant(joint_model.nv(), std::numeric_limits<double>::max());
+    min_config = Eigen::VectorXd::Constant(joint_model.nq(), std::numeric_limits<double>::max());
+    max_config = Eigen::VectorXd::Constant(joint_model.nq(), std::numeric_limits<double>::max());
+
+    return addJoint(parent, joint_model, joint_placement, max_effort, max_velocity, min_config, max_config, joint_name);
+  }
+  
+  inline int Model::addJointFrame (const JointIndex& jidx,
+                                         int         fidx)
+  {
+    if (fidx < 0) {
+      // FIXED_JOINT is required because the parent can be the universe and its
+      // type is FIXED_JOINT
+      fidx = getFrameId(names[parents[jidx]], (FrameType)(JOINT | FIXED_JOINT));
+    }
+    assert(fidx < frames.size() && "Frame index out of bound");
+    // Add a the joint frame attached to itself to the frame vector - redundant information but useful.
+    return addFrame(Frame(names[jidx],jidx,fidx,SE3::Identity(),JOINT));
+  }
+
+
   inline void Model::appendBodyToJoint(const Model::JointIndex joint_index,
                                        const Inertia & Y,
-                                       const SE3 & body_placement,
-                                       const std::string & body_name)
+                                       const SE3 & body_placement)
   {
     const Inertia & iYf = Y.se3Action(body_placement);
     inertias[joint_index] += iYf;
+    nbodies++;
+  }
 
-    addFrame((body_name!="")?body_name:randomStringGenerator(8), joint_index, body_placement, BODY);
-    nbody++;
+  inline int Model::addBodyFrame (const std::string & body_name,
+                                  const JointIndex  & parentJoint,
+                                  const SE3         & body_placement,
+                                        int           previousFrame)
+  {
+    if (previousFrame < 0) {
+      // FIXED_JOINT is required because the parent can be the universe and its
+      // type is FIXED_JOINT
+      previousFrame = getFrameId(names[parentJoint], (FrameType)(JOINT | FIXED_JOINT));
+    }
+    assert(previousFrame < frames.size() && "Frame index out of bound");
+    return addFrame(Frame(body_name, parentJoint, previousFrame, body_placement, BODY));
   }
   
   inline Model::JointIndex Model::getBodyId (const std::string & name) const
   {
-    return getFrameId(name);
+    return getFrameId(name, BODY);
   }
   
   inline bool Model::existBodyName (const std::string & name) const
   {
-    return existFrame(name);
+    return existFrame(name, BODY);
   }
 
-  inline const std::string& Model::getBodyName (const Model::JointIndex index) const
-  {
-    assert( index < (Model::Index)nbody );
-    return getFrameName(index);
-  }
 
   inline Model::JointIndex Model::getJointId (const std::string & name) const
   {
@@ -138,97 +189,38 @@ namespace se3
     return names[index];
   }
 
-  inline Model::FrameIndex Model::getFrameId ( const std::string & name ) const
+  inline Model::FrameIndex Model::getFrameId ( const std::string & name, const FrameType & type ) const
   {
     std::vector<Frame>::const_iterator it = std::find_if( frames.begin()
                                                         , frames.end()
-                                                        , boost::bind(&Frame::name, _1) == name
+                                                        , details::FilterFrame (name, type)
                                                         );
+    assert (it != frames.end() && "Frame not found");
+    assert ((std::find_if( boost::next(it), frames.end(), details::FilterFrame (name, type)) == frames.end())
+        && "Several frames match the filter");
     return Model::FrameIndex(it - frames.begin());
   }
 
-  inline bool Model::existFrame ( const std::string & name ) const
+  inline bool Model::existFrame ( const std::string & name, const FrameType & type) const
   {
-    return std::find_if( frames.begin(), frames.end(), boost::bind(&Frame::name, _1) == name) != frames.end();
+    return std::find_if( frames.begin(), frames.end(),
+        details::FilterFrame (name, type)) != frames.end();
   }
 
-  inline const std::string & Model::getFrameName ( const FrameIndex index ) const
-  {
-    return frames[index].name;
-  }
 
-  inline Model::JointIndex Model::getFrameParent( const std::string & name ) const
+  inline int Model::addFrame ( const Frame & frame )
   {
-    assert(existFrame(name) && "The Frame you requested does not exist");
-    std::vector<Frame>::const_iterator it = std::find_if( frames.begin()
-                                                        , frames.end()
-                                                        , boost::bind(&Frame::name, _1) == name
-                                                        );
-    
-    std::vector<Frame>::iterator::difference_type it_diff = it - frames.begin();
-    return getFrameParent(Model::JointIndex(it_diff));
-  }
-
-  inline Model::JointIndex Model::getFrameParent( const FrameIndex index ) const
-  {
-    return frames[index].parent;
-  }
-
-  inline FrameType Model::getFrameType( const std::string & name ) const
-  {
-    assert(existFrame(name) && "The Frame you requested does not exist");
-    std::vector<Frame>::const_iterator it = std::find_if( frames.begin()
-                                                        , frames.end()
-                                                        , boost::bind(&Frame::name, _1) == name
-                                                        );
-    
-    std::vector<Frame>::iterator::difference_type it_diff = it - frames.begin();
-    return getFrameType(Model::JointIndex(it_diff));
-  }
-
-  inline FrameType Model::getFrameType( const FrameIndex index ) const
-  {
-    return frames[index].type;
-  }
-
-  inline const SE3 & Model::getFramePlacement( const std::string & name) const
-  {
-    assert(existFrame(name) && "The Frame you requested does not exist");
-    std::vector<Frame>::const_iterator it = std::find_if( frames.begin()
-                                                        , frames.end()
-                                                        , boost::bind(&Frame::name, _1) == name
-                                                        );
-    
-    std::vector<Frame>::iterator::difference_type it_diff = it - frames.begin();
-    return getFramePlacement(Model::Index(it_diff));
-  }
-
-  inline const SE3 & Model::getFramePlacement( const FrameIndex index ) const
-  {
-    return frames[index].placement;
-  }
-
-  inline bool Model::addFrame ( const Frame & frame )
-  {
-    if( !existFrame(frame.name) )
+    if( !existFrame(frame.name, frame.type) )
     {
       frames.push_back(frame);
-      nFrames++;
-      return true;
+      nframes++;
+      return nframes - 1;
     }
     else
     {
-      return false;
+      return -1;
     }
   }
-
-  inline bool Model::addFrame ( const std::string & name, JointIndex index, const SE3 & placement, const FrameType type)
-  {
-    if( !existFrame(name) )
-      return addFrame(Frame(name, index, placement, type));
-    else
-      return false;
-  }
   
   inline void Model::addJointIndexToParentSubtrees(const JointIndex joint_id)
   {
@@ -239,35 +231,35 @@ namespace se3
 
   inline Data::Data (const Model & model)
     :joints(0)
-    ,a((std::size_t)model.njoint)
-    ,a_gf((std::size_t)model.njoint)
-    ,v((std::size_t)model.njoint)
-    ,f((std::size_t)model.njoint)
-    ,oMi((std::size_t)model.njoint)
-    ,liMi((std::size_t)model.njoint)
+    ,a((std::size_t)model.njoints)
+    ,a_gf((std::size_t)model.njoints)
+    ,v((std::size_t)model.njoints)
+    ,f((std::size_t)model.njoints)
+    ,oMi((std::size_t)model.njoints)
+    ,liMi((std::size_t)model.njoints)
     ,tau(model.nv)
     ,nle(model.nv)
-    ,oMf((std::size_t)model.nFrames)
-    ,Ycrb((std::size_t)model.njoint)
+    ,oMf((std::size_t)model.nframes)
+    ,Ycrb((std::size_t)model.njoints)
     ,M(model.nv,model.nv)
     ,ddq(model.nv)
-    ,Yaba((std::size_t)model.njoint)
+    ,Yaba((std::size_t)model.njoints)
     ,u(model.nv)
     ,Ag(6,model.nv)
-    ,Fcrb((std::size_t)model.njoint)
-    ,lastChild((std::size_t)model.njoint)
-    ,nvSubtree((std::size_t)model.njoint)
+    ,Fcrb((std::size_t)model.njoints)
+    ,lastChild((std::size_t)model.njoints)
+    ,nvSubtree((std::size_t)model.njoints)
     ,U(model.nv,model.nv)
     ,D(model.nv)
     ,tmp(model.nv)
     ,parents_fromRow((std::size_t)model.nv)
     ,nvSubtree_fromRow((std::size_t)model.nv)
     ,J(6,model.nv)
-    ,iMf((std::size_t)model.njoint)
-    ,com((std::size_t)model.njoint)
-    ,vcom((std::size_t)model.njoint)
-    ,acom((std::size_t)model.njoint)
-    ,mass((std::size_t)model.njoint)
+    ,iMf((std::size_t)model.njoints)
+    ,com((std::size_t)model.njoints)
+    ,vcom((std::size_t)model.njoints)
+    ,acom((std::size_t)model.njoints)
+    ,mass((std::size_t)model.njoints)
     ,Jcom(3,model.nv)
     ,JMinvJt()
     ,llt_JMinvJt()
@@ -278,12 +270,12 @@ namespace se3
     ,impulse_c()
   {
     /* Create data strcture associated to the joints */
-    for(Model::Index i=0;i<(Model::JointIndex)(model.njoint);++i) 
+    for(Model::Index i=0;i<(Model::JointIndex)(model.njoints);++i) 
       joints.push_back(CreateJointData::run(model.joints[i]));
 
     /* Init for CRBA */
     M.fill(0);
-    for(Model::Index i=0;i<(Model::Index)(model.njoint);++i ) { Fcrb[i].resize(6,model.nv); }
+    for(Model::Index i=0;i<(Model::Index)(model.njoints);++i ) { Fcrb[i].resize(6,model.nv); }
     computeLastChild(model);
 
     /* Init for Cholesky */
@@ -308,7 +300,7 @@ namespace se3
   {
     typedef Model::Index Index;
     std::fill(lastChild.begin(),lastChild.end(),-1);
-    for( int i=model.njoint-1;i>=0;--i )
+    for( int i=model.njoints-1;i>=0;--i )
     {
       if(lastChild[(Index)i] == -1) lastChild[(Index)i] = i;
       const Index & parent = model.parents[(Index)i];
@@ -322,7 +314,7 @@ namespace se3
 
   inline void Data::computeParents_fromRow (const Model & model)
   {
-    for( Model::Index joint=1;joint<(Model::Index)(model.njoint);joint++)
+    for( Model::Index joint=1;joint<(Model::Index)(model.njoints);joint++)
     {
       const Model::Index & parent = model.parents[joint];
       const int nvj    = nv   (model.joints[joint]);
diff --git a/src/parsers/lua.cpp b/src/parsers/lua.cpp
index 48dbcbda30c27a51fb58ca20db15cf3ee2ca6d57..085ba645fddc3d3632d166ff50a8346c287bf25b 100644
--- a/src/parsers/lua.cpp
+++ b/src/parsers/lua.cpp
@@ -142,8 +142,10 @@ namespace se3
       
       idx = model.addJoint(parent_id,jmodel,
                            joint_placement,joint_name);
-      model.appendBodyToJoint(idx,Y,SE3::Identity(),body_name);
-      
+      model.addJointFrame(idx);
+      model.appendBodyToJoint(idx,Y);
+      model.addBodyFrame(body_name, idx);
+
       return idx;
     }
     
@@ -295,9 +297,13 @@ namespace se3
         }
         else if (joint_type == "JointTypeFixed")
         {
-          model.appendBodyToJoint(parent_id, Y, global_placement, "");
+          model.appendBodyToJoint(parent_id, Y, global_placement);
+          // TODO Why not
+          // model.addBodyFrame(body_name, parent_id, global_placement);
+          // ???
+          model.addBodyFrame(randomStringGenerator(8), parent_id, global_placement);
 
-          joint_id = (Model::JointIndex)model.njoint;
+          joint_id = (Model::JointIndex)model.njoints;
           
           fixed_body_table_id_map[body_name] = parent_id;
           fixed_placement_map[body_name] = global_placement;
diff --git a/src/parsers/sample-models.cpp b/src/parsers/sample-models.cpp
index c46a64f310d684baf2f44318bf5a6a86f7e4a493..9ebf0496bcffeb804076c03088d7b09f1cc11387 100644
--- a/src/parsers/sample-models.cpp
+++ b/src/parsers/sample-models.cpp
@@ -22,112 +22,92 @@ namespace se3
 {
   namespace buildModels
   {
+    const SE3 Id = SE3::Identity();
+
     
     template<typename JointModel>
     static void addJointAndBody(Model & model,
                                 const JointModelBase<JointModel> & joint,
                                 const std::string & parent_name,
-                                const std::string & name)
+                                const std::string & name,
+                                const SE3 placement = SE3::Random(),
+                                bool setRandomLimits = true)
     {
       typedef typename JointModel::ConfigVector_t CV;
       typedef typename JointModel::TangentVector_t TV;
       
       Model::JointIndex idx;
       
-      idx = model.addJoint(model.getJointId(parent_name),joint,
-                           SE3::Random(),name + "_joint",
+      if (setRandomLimits)
+        idx = model.addJoint(model.getJointId(parent_name),joint,
+                           SE3::Random(),
                            TV::Random() + TV::Constant(1),
                            TV::Random() + TV::Constant(1),
                            CV::Random() - CV::Constant(1),
-                           CV::Random() + CV::Constant(1));
+                           CV::Random() + CV::Constant(1),
+                           name + "_joint");
+      else
+        idx = model.addJoint(model.getJointId(parent_name),joint,
+                             placement, name + "_joint");
+        
+        model.addJointFrame(idx);
       
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),name + "_body");
+        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity());
+        model.addBodyFrame(name + "_body", idx);
     }
 
     void humanoid2d(Model & model)
     {
-      Model::JointIndex idx;
-      
       // root
-      idx = model.addJoint(model.getJointId("universe"),JointModelRX(),SE3::Identity(),"ff1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff1_body");
-      
-      idx = model.addJoint(model.getJointId("ff1_joint"),JointModelRY(),SE3::Identity(),"root_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"root_body");
+      addJointAndBody(model, JointModelRX(), "universe", "ff1", Id, false);
+      addJointAndBody(model, JointModelRY(), "ff1_joint", "root", Id, false);
 
       // lleg
-      idx = model.addJoint(model.getJointId("root_joint"),JointModelRZ(),SE3::Identity(),"lleg1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"lleg1_body");
-      
-      idx = model.addJoint(model.getJointId("lleg1_joint"),JointModelRY(),SE3::Identity(),"lleg2_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"lleg2_body");
+      addJointAndBody(model, JointModelRZ(), "root_joint", "lleg1", Id, false);
+      addJointAndBody(model, JointModelRY(), "lleg1_joint", "lleg2", Id, false);
 
       // rlgg
-      idx = model.addJoint(model.getJointId("root_joint"),JointModelRZ(),SE3::Identity(),"rleg1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"rleg1_body");
-
-      idx = model.addJoint(model.getJointId("rleg1_joint"),JointModelRY(),SE3::Identity(),"rleg2_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"rleg2_body");
+      addJointAndBody(model, JointModelRZ(), "root_joint", "rleg1", Id, false);
+      addJointAndBody(model, JointModelRY(), "lleg1_joint", "rleg2", Id, false);
 
       // torso
-      idx = model.addJoint(model.getJointId("root_joint"),JointModelRY(),SE3::Identity(),"torso1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"torso1_body");
-
-      idx = model.addJoint(model.getJointId("torso1_joint"),JointModelRZ(),SE3::Identity(),"chest_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"chest_body");
+      addJointAndBody(model, JointModelRY(), "root_joint", "torso1", Id, false);
+      addJointAndBody(model, JointModelRZ(), "torso1_joint", "chest", Id, false);
 
       // rarm
-      idx = model.addJoint(model.getJointId("chest_joint"),JointModelRX(),SE3::Identity(),"rarm1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"rarm1_body");
-
-      idx = model.addJoint(model.getJointId("rarm1_joint"),JointModelRZ(),SE3::Identity(),"rarm2_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"rarm2_body");
+      addJointAndBody(model, JointModelRX(), "chest_joint", "rarm1", Id, false);
+      addJointAndBody(model, JointModelRZ(), "rarm1_joint", "rarm2", Id, false);
 
       // larm
-      idx = model.addJoint(model.getJointId("chest_joint"),JointModelRX(),SE3::Identity(),"larm1_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"larm1_body");
-
-      idx = model.addJoint(model.getJointId("larm1_joint"),JointModelRZ(),SE3::Identity(),"larm2_joint");
-      model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"larm2_body");
+      addJointAndBody(model, JointModelRX(), "root_joint", "larm1", Id, false);
+      addJointAndBody(model, JointModelRZ(), "larm1_joint", "larm2", Id, false);
 
     }
 
     void humanoidSimple(Model & model, bool usingFF)
     {
-      Model::JointIndex idx;
-      
       // root
       if(! usingFF )
       {
-        idx = model.addJoint(model.getJointId("universe"),JointModelRX(),SE3::Identity(),"ff1_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff1_body");
-        
-        idx = model.addJoint(model.getJointId("ff1_joint"),JointModelRY(),SE3::Identity(),"ff2_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff2_body");
-        
-        idx = model.addJoint(model.getJointId("ff2_joint"),JointModelRZ(),SE3::Identity(),"ff3_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff3_body");
-        
-        idx = model.addJoint(model.getJointId("ff3_joint"),JointModelRZ(),SE3::Random(),"ff4_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff4_body");
-        
-        idx = model.addJoint(model.getJointId("ff4_joint"),JointModelRY(),SE3::Identity(),"ff5_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"ff5_body");
-        
-        idx = model.addJoint(model.getJointId("ff5_joint"),JointModelRX(),SE3::Identity(),"root_joint");
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"root_body");
+        addJointAndBody(model, JointModelRX(), "universe", "ff1", Id, false);
+        addJointAndBody(model, JointModelRY(), "ff1_joint", "ff2", Id, false);
+        addJointAndBody(model, JointModelRZ(), "ff2_joint", "ff3", Id, false);
+        addJointAndBody(model, JointModelRZ(), "ff3_joint", "ff4", Id, false);
+        addJointAndBody(model, JointModelRY(), "ff4_joint", "ff5", Id, false);
+        addJointAndBody(model, JointModelRX(), "ff5_joint", "root", Id, false);
       }
       else
       {
-        typedef JointModelFreeFlyer::ConfigVector_t CV;
-        typedef JointModelFreeFlyer::TangentVector_t TV;
+        // typedef JointModelFreeFlyer::ConfigVector_t CV;
+        // typedef JointModelFreeFlyer::TangentVector_t TV;
         
-        idx = model.addJoint(model.getJointId("universe"),JointModelFreeFlyer(),
-                             SE3::Identity(),"root_joint",
-                             TV::Zero(), 1e3 * (TV::Random() + TV::Constant(1.)),
-                             1e3 * (CV::Random() - CV::Constant(1)),
-                             1e3 * (CV::Random() + CV::Constant(1)));
-        model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"root_body");
+        addJointAndBody(model, JointModelFreeFlyer(), "universe", "root", Id, false);
+        // idx = model.addJoint(model.getJointId("universe"),JointModelFreeFlyer(),
+                             // SE3::Identity(),"root_joint",
+                             // TV::Zero(), 1e3 * (TV::Random() + TV::Constant(1.)),
+                             // 1e3 * (CV::Random() - CV::Constant(1)),
+                             // 1e3 * (CV::Random() + CV::Constant(1)));
+        // model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"root_body");
       }
 
       // lleg
diff --git a/src/parsers/srdf.hpp b/src/parsers/srdf.hpp
index 6c03878f20636e2365a6b7006b34d93872cf411a..e6cfd0202cef6fcabd5373bc27322a674c55188b 100644
--- a/src/parsers/srdf.hpp
+++ b/src/parsers/srdf.hpp
@@ -39,13 +39,13 @@ namespace se3
     ///        It throws if the SRDF file is incorrect.
     ///
     /// \param[in] model Model of the kinematic tree.
-    /// \param[in] model_geom Model of the geometries.
+    /// \param[in] geomModel Model of the geometries.
     /// \param[out] data_geom Data containing the active collision pairs.
     /// \param[in] filename The complete path to the SRDF file.
     /// \param[in] verbose Verbosity mode (print removed collision pairs and undefined link inside the model).
     ///
     inline void removeCollisionPairsFromSrdf(const Model& model,
-                                             GeometryModel & model_geom,
+                                             GeometryModel & geomModel,
                                              const std::string & filename,
                                              const bool verbose) throw (std::invalid_argument)
     {
@@ -90,24 +90,38 @@ namespace se3
           const Model::JointIndex joint_id1 = model.frames[frame_id1].parent;
           const Model::JointIndex frame_id2 = model.getBodyId(link2);
           const Model::JointIndex joint_id2 = model.frames[frame_id2].parent;
-          
-          typedef GeometryModel::GeomIndexList GeomIndexList;
-          const GeomIndexList & innerObject1 = model_geom.innerObjects.at(joint_id1);
-          const GeomIndexList & innerObject2 = model_geom.innerObjects.at(joint_id2);
-          
-          for(GeomIndexList::const_iterator it1 = innerObject1.begin();
-              it1 != innerObject1.end();
-              ++it1)
+
+          // Malformed SRDF
+          if (frame_id1 == frame_id2)
           {
-            for(GeomIndexList::const_iterator it2 = innerObject2.begin();
-                it2 != innerObject2.end();
-                ++it2)
-            {
-              model_geom.removeCollisionPair(CollisionPair(*it1, *it2));
-              if(verbose)
-                std::cout << "Remove collision pair (" << joint_id1 << "," << joint_id2 << ")" << std::endl;
+            if (verbose)
+              std::cout << "Cannot disable collision between " << link1 << " and " << link2 << std::endl;
+            continue;
+          }
+          
+          typedef std::vector<CollisionPair> CollisionPairs_t;
+          bool didRemove = false;
+          for(CollisionPairs_t::iterator _colPair = geomModel.collisionPairs.begin();
+              _colPair != geomModel.collisionPairs.end(); ) {
+            const CollisionPair& colPair (*_colPair);
+            bool remove =
+              (
+                  (geomModel.geometryObjects[colPair.first ].parentFrame == frame_id1)
+               && (geomModel.geometryObjects[colPair.second].parentFrame == frame_id2)
+              ) || (
+                   (geomModel.geometryObjects[colPair.second].parentFrame == frame_id1)
+                && (geomModel.geometryObjects[colPair.first ].parentFrame == frame_id2)
+              );
+
+            if (remove) {
+              _colPair = geomModel.collisionPairs.erase(_colPair);
+              didRemove = true;
+            } else {
+              ++_colPair;
             }
           }
+          if(didRemove && verbose)
+            std::cout << "Remove collision pair (" << link1 << "," << link2 << ")" << std::endl;
           
         }
       } // BOOST_FOREACH
diff --git a/src/parsers/urdf.hpp b/src/parsers/urdf.hpp
index 4eb54c72ffe211b1a60bfb912d3fa3190e05e629..01955134ebd97098a9db84e3a034d2672a3bac9e 100644
--- a/src/parsers/urdf.hpp
+++ b/src/parsers/urdf.hpp
@@ -48,31 +48,16 @@ namespace se3
     /// the model given as reference argument.
     ///
     /// \param[in] filemane The URDF complete file path.
-    /// \param[in] root_joint The joint at the root of the model tree.
+    /// \param[in] rootJoint The joint at the root of the model tree.
     /// \param[in] verbose Print parsing info.
     /// \param[out] model Reference model where to put the parsed information.
     /// \return Return the reference on argument model for convenience.
     /// 
     Model& buildModel (const std::string & filename,
-                       const JointModelVariant & root_joint,
+                       const JointModelVariant & rootJoint,
                        Model & model, 
                        const bool verbose = false) throw (std::invalid_argument);
 
-    ///
-    /// \brief Build the model from a URDF file with a particular joint as root of the model tree.
-    ///
-    /// \param[in] filemane The URDF complete file path.
-    /// \param[in] root_joint The joint at the root of the model tree.
-    /// \param[in] verbose Print parsing info.
-    ///
-    /// \return The se3::Model of the URDF file.
-    ///
-    PINOCCHIO_DEPRECATED
-    inline Model buildModel (const std::string & filename,
-                             const JointModelVariant & root_joint,
-                             const bool verbose = false) 
-      throw (std::invalid_argument)
-    { Model m; return buildModel(filename,root_joint,m,verbose); }
 
     ///
     /// \brief Build the model from a URDF file with a fixed joint as root of the model tree.
@@ -86,20 +71,6 @@ namespace se3
                         Model & model,
                         const bool verbose = false) throw (std::invalid_argument);
 
-    ///
-    /// \brief Build the model from a URDF file with a fixed joint as root of the model tree.
-    ///
-    /// \param[in] filemane The URDF complete file path.
-    /// \param[in] verbose Print parsing info.
-    ///
-    /// \return The se3::Model of the URDF file.
-    ///
-    PINOCCHIO_DEPRECATED
-    inline Model buildModel (const std::string & filename,
-                             const bool verbose = false)
-      throw (std::invalid_argument)
-    { Model m; return buildModel(filename,m,verbose);  }
-
 
     /**
      * @brief      Build The GeometryModel from a URDF file. Search for meshes
@@ -109,7 +80,7 @@ namespace se3
      * @param[in]  model         The model of the robot, built with
      *                           urdf::buildModel
      * @param[in]  filename      The URDF complete (absolute) file path
-     * @param[in]  package_dirs  A vector containing the different directories
+     * @param[in]  packageDirs  A vector containing the different directories
      *                           where to search for models and meshes, typically 
      *                           obtained from calling se3::rosPaths()
      *
@@ -125,33 +96,9 @@ namespace se3
                              const std::string & filename,
                              const GeometryType type,
                              GeometryModel & geomModel,
-                             const std::vector<std::string> & package_dirs = std::vector<std::string> ())
+                             const std::vector<std::string> & packageDirs = std::vector<std::string> ())
     throw (std::invalid_argument);
 
-    /**
-     * @brief      Inline call to the previous method (deprecated).
-     *
-     * @param[in]  model         The model of the robot, built with
-     *                           urdf::buildModel
-     * @param[in]  filename      The URDF complete (absolute) file path
-     * @param[in]  package_dirs  A vector containing the different directories
-     *                           where to search for models and meshes, typically 
-     *                           obtained from calling se3::rosPaths()
-     *
-     *@param[in]   type          The type of objects that must be loaded ( can be VISUAL or COLLISION, or NONE)
-     *
-     * @return     The GeometryModel associated to the urdf file and the given Model.
-     *
-     * \warning    If hpp-fcl has not been found during compilation, COLLISION types can not be loaded
-     */
-    PINOCCHIO_DEPRECATED 
-    inline  GeometryModel buildGeom(const Model & model,
-                                   const std::string & filename,
-                                   const std::vector<std::string> & package_dirs = std::vector<std::string> (),
-                                   const GeometryType type = NONE)
-      throw (std::invalid_argument)
-    { GeometryModel g; return buildGeom (model,filename,type,g,package_dirs); }
-
 
   } // namespace urdf
 } // namespace se3
diff --git a/src/parsers/urdf/geometry.cpp b/src/parsers/urdf/geometry.cpp
index 91abef569daf1a44fc804a11d4993816def0b8fb..96fd20a6c8cdcac30e8bc9dec7de310ff8127b14 100644
--- a/src/parsers/urdf/geometry.cpp
+++ b/src/parsers/urdf/geometry.cpp
@@ -48,13 +48,13 @@ namespace se3
      *
      * @param[in]  urdf_geometry  A shared pointer on the input urdf Geometry
      * @param[in]  package_dirs   A vector containing the different directories where to search for packages
-     * @param[out] mesh_path      The Absolute path of the mesh currently read
+     * @param[out] meshPath      The Absolute path of the mesh currently read
      *
      * @return     A shared pointer on the he geometry converted as a fcl::CollisionGeometry
      */
      boost::shared_ptr<fcl::CollisionGeometry> retrieveCollisionGeometry(const boost::shared_ptr< ::urdf::Geometry> urdf_geometry,
                                                                          const std::vector<std::string> & package_dirs,
-                                                                         std::string & mesh_path)
+                                                                         std::string & meshPath)
       {
         boost::shared_ptr<fcl::CollisionGeometry> geometry;
 
@@ -64,7 +64,7 @@ namespace se3
           boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry);
           std::string collisionFilename = collisionGeometry->filename;
 
-          mesh_path = retrieveResourcePath(collisionFilename, package_dirs);
+          meshPath = retrieveResourcePath(collisionFilename, package_dirs);
 
           fcl::Vec3f scale = fcl::Vec3f(collisionGeometry->scale.x,
                                               collisionGeometry->scale.y,
@@ -74,7 +74,7 @@ namespace se3
           // Create FCL mesh by parsing Collada file.
           PolyhedronPtrType polyhedron (new PolyhedronType);
 
-          fcl::loadPolyhedronFromResource (mesh_path, scale, polyhedron);
+          fcl::loadPolyhedronFromResource (meshPath, scale, polyhedron);
           geometry = polyhedron;
         }
 
@@ -82,7 +82,7 @@ namespace se3
         // Use FCL capsules for cylinders
         else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER)
         {
-          mesh_path = "CYLINDER";
+          meshPath = "CYLINDER";
           boost::shared_ptr < ::urdf::Cylinder> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry);
     
           double radius = collisionGeometry->radius;
@@ -94,7 +94,7 @@ namespace se3
         // Handle the case where collision geometry is a box.
         else if (urdf_geometry->type == ::urdf::Geometry::BOX) 
         {
-          mesh_path = "BOX";
+          meshPath = "BOX";
           boost::shared_ptr < ::urdf::Box> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Box> (urdf_geometry);
     
           double x = collisionGeometry->dim.x;
@@ -106,7 +106,7 @@ namespace se3
         // Handle the case where collision geometry is a sphere.
         else if (urdf_geometry->type == ::urdf::Geometry::SPHERE)
         {
-          mesh_path = "SPHERE";
+          meshPath = "SPHERE";
           boost::shared_ptr < ::urdf::Sphere> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry);
 
           double radius = collisionGeometry->radius;
@@ -181,60 +181,63 @@ namespace se3
       template<typename T>
       inline void addLinkGeometryToGeomModel(::urdf::LinkConstPtr link,
                                              const Model & model,
-                                             GeometryModel & geom_model,
+                                             GeometryModel & geomModel,
                                              const std::vector<std::string> & package_dirs) throw (std::invalid_argument)
       {
         if(getLinkGeometry<T>(link))
         {
-          std::string mesh_path = "";
+          std::string meshPath = "";
         
           std::string link_name = link->name;
 
-          assert(link->getParent()!=NULL);
-          if (link->getParent() == NULL)
-          {
-            const std::string exception_message (link->name + " - joint information missing.");
-            throw std::invalid_argument(exception_message);
-          }
           std::vector< boost::shared_ptr< T > > geometries_array = getLinkGeometryArray<T>(link);
 
+          if (!model.existFrame(link_name, BODY))
+            throw std::invalid_argument("No link " + link_name + " in model");
+          FrameIndex frame_id = model.getFrameId(link_name, BODY);
+          SE3 body_placement = model.frames[frame_id].placement;
+          assert(model.frames[frame_id].type == BODY);
+
           std::size_t objectId = 0;
           for (typename std::vector< boost::shared_ptr< T > >::const_iterator i = geometries_array.begin();i != geometries_array.end(); ++i)
           {
+            meshPath.clear();
 #ifdef WITH_HPP_FCL
-            const boost::shared_ptr<fcl::CollisionGeometry> geometry = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path);
+            const boost::shared_ptr<fcl::CollisionGeometry> geometry = retrieveCollisionGeometry((*i)->geometry, package_dirs, meshPath);
 #else
             boost::shared_ptr < ::urdf::Mesh> urdf_mesh = boost::dynamic_pointer_cast< ::urdf::Mesh> ((*i)->geometry);
-            if (urdf_mesh) mesh_path = retrieveResourcePath(urdf_mesh->filename, package_dirs);
+            if (urdf_mesh) meshPath = retrieveResourcePath(urdf_mesh->filename, package_dirs);
             
             const boost::shared_ptr<fcl::CollisionGeometry> geometry(new fcl::CollisionGeometry());
 #endif // WITH_HPP_FCL            
             
-            SE3 geomPlacement = convertFromUrdf((*i)->origin);
+            SE3 geomPlacement = body_placement * convertFromUrdf((*i)->origin);
             std::ostringstream geometry_object_suffix;
             geometry_object_suffix << "_" << objectId;
             const std::string & geometry_object_name = std::string(link_name + geometry_object_suffix.str());
-            geom_model.addGeometryObject(model.getFrameParent(link_name), geometry, geomPlacement, geometry_object_name, mesh_path);
-            ++objectId; 
+            geomModel.addGeometryObject(GeometryObject(geometry_object_name,
+                                                       frame_id, model.frames[frame_id].parent, 
+                                                       geometry,
+                                                       geomPlacement, meshPath),
+                                        model);
+            ++objectId;
           }
         }
       }
 
-
-
     /**
      * @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 GeometryModel associated
-     * @param      model_geom      The GeometryModel where the Collision Objects must be added
+     * @param      geomModel      The GeometryModel where the Collision Objects must be added
      * @param[in]  package_dirs    A vector containing the different directories where to search for packages
      * @param[in]  type            The type of objects that must be loaded ( can be VISUAL or COLLISION)
      */
      void parseTreeForGeom(::urdf::LinkConstPtr link,
                            const Model & model,
-                           GeometryModel & geom_model,
+                           GeometryModel & geomModel,
                            const std::vector<std::string> & package_dirs,
                            const GeometryType type) throw (std::invalid_argument)
       {
@@ -242,10 +245,10 @@ namespace se3
         switch(type)
         {
           case COLLISION:
-            addLinkGeometryToGeomModel< ::urdf::Collision >(link, model, geom_model, package_dirs);
+            addLinkGeometryToGeomModel< ::urdf::Collision >(link, model, geomModel, package_dirs);
           break;
           case VISUAL:
-            addLinkGeometryToGeomModel< ::urdf::Visual >(link, model, geom_model, package_dirs);
+            addLinkGeometryToGeomModel< ::urdf::Visual >(link, model, geomModel, package_dirs);
           break;
           default:
           break;
@@ -253,7 +256,7 @@ namespace se3
         
         BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
         {
-          parseTreeForGeom(child, model, geom_model, package_dirs,type);
+          parseTreeForGeom(child, model, geomModel, package_dirs,type);
         }
 
       }
@@ -265,16 +268,10 @@ namespace se3
     GeometryModel& buildGeom(const Model & model,
                              const std::string & filename,
                              const GeometryType type,
-                             GeometryModel & model_geom,
+                             GeometryModel & geomModel,
                              const std::vector<std::string> & package_dirs)
       throw(std::invalid_argument)
     {
-      if (type == NONE)
-      {
-        const std::string exception_message ("You must specify if you want to load VISUAL or COLLISION meshes");
-        throw std::invalid_argument(exception_message);
-      }
-
       std::vector<std::string> hint_directories(package_dirs);
 
       // Append the ROS_PACKAGE_PATH
@@ -287,8 +284,8 @@ namespace se3
       }
 
       ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
-      details::parseTreeForGeom(urdfTree->getRoot(), model, model_geom, hint_directories,type);
-      return model_geom;
+      details::parseTreeForGeom(urdfTree->getRoot(), model, geomModel, hint_directories,type);
+      return geomModel;
     }
 
   } // namespace urdf
diff --git a/src/parsers/urdf/model.cpp b/src/parsers/urdf/model.cpp
index 47bcb230488148187027f8572a43e40f3be69593..d7799c7c3995ab80d659e4059f0ac62ec83fe19d 100644
--- a/src/parsers/urdf/model.cpp
+++ b/src/parsers/urdf/model.cpp
@@ -16,6 +16,7 @@
 // Pinocchio If not, see
 // <http://www.gnu.org/licenses/>.
 
+#include "pinocchio/math/matrix.hpp"
 #include "pinocchio/parsers/urdf.hpp"
 #include "pinocchio/parsers/urdf/utils.hpp"
 #include "pinocchio/multibody/model.hpp"
@@ -33,41 +34,121 @@ namespace se3
   {
     namespace details
     {
+      const FrameType JOINT_OR_FIXED_JOINT = (FrameType) (JOINT | FIXED_JOINT);
+
+      FrameIndex getParentJointFrame(::urdf::LinkConstPtr link, Model & model)
+      {
+        assert(link!=NULL && link->getParent()!=NULL);
+
+        FrameIndex id;
+        if (link->getParent()->parent_joint==NULL) {
+          if (model.existFrame("root_joint",  JOINT_OR_FIXED_JOINT))
+            id = model.getFrameId ("root_joint", JOINT_OR_FIXED_JOINT);
+          else
+            id = 0;
+        } else {
+          if (model.existFrame(link->getParent()->parent_joint->name, JOINT_OR_FIXED_JOINT))
+            id = model.getFrameId (link->getParent()->parent_joint->name, JOINT_OR_FIXED_JOINT);
+          else
+            throw std::invalid_argument ("Model does not have any joints named "
+                + link->getParent()->parent_joint->name);
+        }
+
+        Frame& f = model.frames[id];
+        if (f.type == JOINT || f.type == FIXED_JOINT)
+          return id;
+        throw std::invalid_argument ("Parent frame is not a JOINT neither a FIXED_JOINT");
+      }
+
+      void appendBodyToJoint(Model& model, const FrameIndex fid,
+                             const boost::shared_ptr< ::urdf::Inertial> Y,
+                             const SE3 & placement,
+                             const std::string & body_name)
+      {
+        const Frame& frame = model.frames[fid];
+        const SE3& p = frame.placement * placement;
+        if (frame.parent > 0
+            && Y != NULL
+            && Y->mass > Eigen::NumTraits<double>::epsilon()) {
+          model.appendBodyToJoint(frame.parent, convertFromUrdf(*Y), p);
+        }
+        model.addBodyFrame(body_name, frame.parent, p, (int)fid);
+        // Reference to model.frames[fid] can has changed because the vector
+        // may have been reallocated.
+        if (model.frames[fid].parent > 0) {
+          assert (!hasNaN(model.inertias[model.frames[fid].parent].lever())
+              &&  !hasNaN(model.inertias[model.frames[fid].parent].inertia().data()));
+        }
+      }
+
       ///
       /// \brief Shortcut for adding a joint and directly append a body to it.
       ///
       template<typename JointModel>
-      void addJointAndBody(Model & model, const JointModelBase<JointModel> & jmodel, const Model::JointIndex parent_id,
+      void addJointAndBody(Model & model, const JointModelBase<JointModel> & jmodel, const FrameIndex& parentFrameId,
                            const SE3 & joint_placement, const std::string & joint_name,
-                           const Inertia & Y, const std::string & body_name,
+                           const boost::shared_ptr< ::urdf::Inertial> Y,
+                           const std::string & body_name,
                            const typename JointModel::TangentVector_t & max_effort = JointModel::TangentVector_t::Constant(std::numeric_limits<double>::max()),
                            const typename JointModel::TangentVector_t & max_velocity = JointModel::TangentVector_t::Constant(std::numeric_limits<double>::max()),
                            const typename JointModel::ConfigVector_t & min_config = JointModel::ConfigVector_t::Constant(-std::numeric_limits<double>::min()),
                            const typename JointModel::ConfigVector_t & max_config = JointModel::ConfigVector_t::Constant(std::numeric_limits<double>::max()))
       {
         Model::JointIndex idx;
+        Frame& frame = model.frames[parentFrameId];
         
-        idx = model.addJoint(parent_id,jmodel,
-                             joint_placement,joint_name,
-                             max_effort,max_velocity,
-                             min_config,max_config);
-        
-        model.appendBodyToJoint(idx,Y,SE3::Identity(),body_name);
+        idx = model.addJoint(frame.parent,jmodel,
+                             frame.placement * joint_placement,
+                             max_effort,max_velocity,min_config,max_config,
+                             joint_name);
+        FrameIndex jointFrameId = (FrameIndex) model.addJointFrame(idx, (int)parentFrameId); // C-style cast to remove polluting compilation warning. This is Bad practice. See issue #323 (rework indexes)
+        appendBodyToJoint(model, jointFrameId, Y, SE3::Identity(), body_name);
       }
       
       ///
       /// \brief Handle the case of JointModelDense which is dynamic.
       ///
-      void addJointAndBody(Model & model, const JointModelBase< JointModelDense<-1,-1> > & jmodel, const Model::JointIndex parent_id,
+      void addJointAndBody(Model & , const JointModelBase< JointModelDense<-1,-1> > & , const FrameIndex& ,
+                           const SE3 & , const std::string & ,
+                           const boost::shared_ptr< ::urdf::Inertial> ,
+                           const std::string & )
+      {
+        assert(false && "Cannot add a joint of type JointModelDense");
+      }
+
+      ///
+      /// \brief Shortcut for adding a fixed joint and directly append a body to it.
+      ///
+      void addFixedJointAndBody(Model & model, const FrameIndex& parentFrameId,
+                                const SE3 & joint_placement, const std::string & joint_name,
+                                const boost::shared_ptr< ::urdf::Inertial> Y,
+                                const std::string & body_name)
+      {
+        Model::JointIndex idx;
+        Frame& frame = model.frames[parentFrameId];
+
+        int fid = model.addFrame(
+            Frame (joint_name, frame.parent, parentFrameId,
+              frame.placement * joint_placement, FIXED_JOINT)
+            );
+        if (fid < 0)
+          throw std::invalid_argument ("Fixed joint " + joint_name + " could not be added.");
+        appendBodyToJoint(model, (FrameIndex)fid, Y, SE3::Identity(), body_name);
+      }
+
+      ///
+      /// \brief Handle the case of JointModelComposite which is dynamic.
+      ///
+      void addJointAndBody(Model & model, const JointModelBase< JointModelComposite > & jmodel, const Model::JointIndex parent_id,
                            const SE3 & joint_placement, const std::string & joint_name,
-                           const Inertia & Y, const std::string & body_name)
+                           const boost::shared_ptr< ::urdf::Inertial> Y, const std::string & body_name)
       {
         Model::JointIndex idx;
         
         idx = model.addJoint(parent_id,jmodel,
                              joint_placement,joint_name);
         
-        model.appendBodyToJoint(idx,Y,SE3::Identity(),body_name);
+        appendBodyToJoint(model,idx,Y,SE3::Identity(),body_name);
       }
 
       ///
@@ -76,17 +157,13 @@ namespace se3
       ///
       /// \param[in] link The current URDF link.
       /// \param[in] model The model where the link must be added.
-      /// \param[in] placementOffset The relative placement of the link relative to the closer non fixed joint in the tree.
       ///
-      void parseTree(::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, bool verbose) throw (std::invalid_argument)
+      void parseTree(::urdf::LinkConstPtr link, Model & model, bool verbose) throw (std::invalid_argument)
       {
         
         // Parent joint of the current body
         ::urdf::JointConstPtr joint = link->parent_joint;
         
-        // OffSet of the next link. In case we encounter a fixed joint, we need to propagate the offset placement of its attached body to next joint.
-        SE3 nextPlacementOffset = SE3::Identity();
-        
         if(joint != NULL) // if the link is not the root of the tree
         {
           assert(link->getParent()!=NULL);
@@ -96,21 +173,12 @@ namespace se3
           const std::string & parent_link_name = link->getParent()->name;
           std::ostringstream joint_info;
           
-          // check if inertial information is provided
-          if (!link->inertial && joint->type != ::urdf::Joint::FIXED)
-          {
-            const std::string exception_message (link->name + " - spatial inertial information missing.");
-            throw std::invalid_argument(exception_message);
-          }
-          
-          Model::JointIndex parent_joint_id = (link->getParent()->parent_joint==NULL) ? (model.existJointName("root_joint") ? model.getJointId("root_joint") : 0) :
-          model.getJointId( link->getParent()->parent_joint->name );
+          FrameIndex parentFrameId = getParentJointFrame(link, model);
           
           // Transformation from the parent link to the joint origin
-          const SE3 & jointPlacement = placementOffset*convertFromUrdf(joint->parent_to_joint_origin_transform);
-          
-          const Inertia & Y = (link->inertial)?convertFromUrdf(*link->inertial):Inertia::Zero();
+          const SE3 jointPlacement = convertFromUrdf(joint->parent_to_joint_origin_transform);
           
+          const boost::shared_ptr< ::urdf::Inertial> Y = link->inertial;
          
           switch(joint->type)
           {
@@ -118,7 +186,7 @@ namespace se3
             {
               joint_info << "joint FreeFlyer";
               addJointAndBody(model,JointModelFreeFlyer(),
-                              parent_joint_id,jointPlacement,joint->name,
+                              parentFrameId,jointPlacement,joint->name,
                               Y,link->name);
               
               break;
@@ -153,7 +221,7 @@ namespace se3
                 {
                   joint_info << " along X";
                   addJointAndBody(model,JointModelRX(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -163,7 +231,7 @@ namespace se3
                 {
                   joint_info << " along Y";
                   addJointAndBody(model,JointModelRY(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -173,7 +241,7 @@ namespace se3
                 {
                   joint_info << " along Z";
                   addJointAndBody(model,JointModelRZ(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -186,7 +254,7 @@ namespace se3
                   joint_info << " unaligned along (" << joint_axis.transpose() << ")";
                   
                   addJointAndBody(model,JointModelRevoluteUnaligned(joint_axis.normalized()),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -228,7 +296,7 @@ namespace se3
                   {
                     joint_info << " along X";
                     addJointAndBody(model,JointModelRX(),
-                                    parent_joint_id,jointPlacement,joint->name,
+                                    parentFrameId,jointPlacement,joint->name,
                                     Y,link->name,
                                     max_effort,max_velocity,
                                     lower_position, upper_position);
@@ -238,7 +306,7 @@ namespace se3
                   {
                     joint_info << " along Y";
                     addJointAndBody(model,JointModelRY(),
-                                    parent_joint_id,jointPlacement,joint->name,
+                                    parentFrameId,jointPlacement,joint->name,
                                     Y,link->name,
                                     max_effort,max_velocity,
                                     lower_position, upper_position);
@@ -248,7 +316,7 @@ namespace se3
                   {
                     joint_info << " along Z";
                     addJointAndBody(model,JointModelRZ(),
-                                    parent_joint_id,jointPlacement,joint->name,
+                                    parentFrameId,jointPlacement,joint->name,
                                     Y,link->name,
                                     max_effort,max_velocity,
                                     lower_position, upper_position);
@@ -261,7 +329,7 @@ namespace se3
                     joint_info << " unaligned along (" << joint_axis.transpose() << ")";
                     
                     addJointAndBody(model,JointModelRevoluteUnaligned(joint_axis.normalized()),
-                                    parent_joint_id,jointPlacement,joint->name,
+                                    parentFrameId,jointPlacement,joint->name,
                                     Y,link->name,
                                     max_effort,max_velocity,
                                     lower_position, upper_position);
@@ -302,7 +370,7 @@ namespace se3
                 {
                   joint_info << " along X";
                   addJointAndBody(model,JointModelPX(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -312,7 +380,7 @@ namespace se3
                 {
                   joint_info << " along Y";
                   addJointAndBody(model,JointModelPY(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -322,7 +390,7 @@ namespace se3
                 {
                   joint_info << " along Z";
                   addJointAndBody(model,JointModelPZ(),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -335,7 +403,7 @@ namespace se3
                   joint_info << " unaligned along (" << joint_axis.transpose() << ")";
                   
                   addJointAndBody(model,JointModelPrismaticUnaligned(joint_axis.normalized()),
-                                  parent_joint_id,jointPlacement,joint->name,
+                                  parentFrameId,jointPlacement,joint->name,
                                   Y,link->name,
                                   max_effort,max_velocity,
                                   lower_position, upper_position);
@@ -370,7 +438,7 @@ namespace se3
               }
               
               addJointAndBody(model,JointModelPlanar(),
-                              parent_joint_id,jointPlacement,joint->name,
+                              parentFrameId,jointPlacement,joint->name,
                               Y,link->name,
                               max_effort,max_velocity,
                               lower_position, upper_position);
@@ -388,23 +456,9 @@ namespace se3
               //    -add fixed body in model to display it in gepetto-viewer
               
               joint_info << "fixed joint";
-              if (link->inertial)
-                model.appendBodyToJoint(parent_joint_id, Y, jointPlacement, link->name); //Modify the parent inertia in the model
-              else
-                model.addFrame(link->name, parent_joint_id, nextPlacementOffset, BODY);
-              
-              //transformation of the current placement offset
-              nextPlacementOffset = jointPlacement;
-              
-              // Add a frame in the model to keep trace of this fixed joint
-              model.addFrame(joint->name, parent_joint_id, nextPlacementOffset, FIXED_JOINT);
-              
-              //for the children of the current link, set their parent to be
-              //the the parent of the current link.
-              BOOST_FOREACH(::urdf::LinkPtr child_link, link->child_links)
-              {
-                child_link->setParent(link->getParent() );
-              }
+              addFixedJointAndBody(model, parentFrameId, jointPlacement,
+                  joint_name, Y, link_name);
+
               break;
             }
             default:
@@ -417,14 +471,15 @@ namespace se3
           
           if (verbose)
           {
+            const Inertia YY = (Y==NULL) ? Inertia::Zero() : convertFromUrdf(*Y);
             std::cout << "Adding Body" << std::endl;
             std::cout << "\"" << link_name << "\" connected to " << "\"" << parent_link_name << "\" throw joint " << "\"" << joint_name << "\"" << std::endl;
             std::cout << "joint type: " << joint_info << std::endl;
             std::cout << "joint placement:\n" << jointPlacement;
             std::cout << "body info: " << std::endl;
-            std::cout << "  " << "mass: " << Y.mass() << std::endl;
-            std::cout << "  " << "lever: " << Y.lever().transpose() << std::endl;
-            std::cout << "  " << "inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << Y.inertia().data().transpose() << std::endl << std::endl;
+            std::cout << "  " << "mass: " << YY.mass() << std::endl;
+            std::cout << "  " << "lever: " << YY.lever().transpose() << std::endl;
+            std::cout << "  " << "inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << YY.inertia().data().transpose() << std::endl << std::endl;
           }
         }
         else if (link->getParent() != NULL)
@@ -436,7 +491,7 @@ namespace se3
         
         BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
         {
-          parseTree(child, model, nextPlacementOffset, verbose);
+          parseTree(child, model, verbose);
         }
       }
 
@@ -450,66 +505,17 @@ namespace se3
       ///
       void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const bool verbose) throw (std::invalid_argument)
       {
-        // If the root link has no inertial info, it may be because it is a base_link.
-        // In this case, we look for its child links which indeed contribute to the dynamics, they are not fixed to the universe.
-        // TODO: it may be necessary to compute joint placement variable instead of setting it to SE3::Identity()
-        if (!root_link->inertial)
-        {
-          typedef std::vector< ::urdf::LinkPtr > LinkSharedPtrVector_t;
-          LinkSharedPtrVector_t movable_child_links;
-          LinkSharedPtrVector_t direct_child_links(root_link->child_links);
-          LinkSharedPtrVector_t next_direct_child_links; // next child to visit
-          LinkSharedPtrVector_t pathologic_child_links; // children which have inertial info but rigidly attached to the world
-          do
-          {
-            next_direct_child_links.clear();
-            BOOST_FOREACH(::urdf::LinkPtr child, direct_child_links)
-            {
-              if (child->parent_joint->type != ::urdf::Joint::FIXED)
-                movable_child_links.push_back(child);
-              else
-              {
-                if (child->inertial)
-                  pathologic_child_links.push_back(child);
-                next_direct_child_links.insert (next_direct_child_links.end(), child->child_links.begin(), child->child_links.end());
-              }
-              
-            }
-            direct_child_links = next_direct_child_links;
-          }
-          while (!direct_child_links.empty());
-          
-          if (!pathologic_child_links.empty())
-          {
-            std::cout << "[INFO] The links:" << std::endl;
-            for (LinkSharedPtrVector_t::iterator it = pathologic_child_links.begin();
-                 it < pathologic_child_links.end(); ++it)
-            {
-              std::cout << "  - " << (*it)->name << std::endl;
-            }
-            std::cout << "are fixed regarding to the universe (base_link) and convey inertial info. They won't affect the dynamics of the output model. Maybe, a root joint is missing connecting this links to the universe." << std::endl;
-            
-          }
-          
-          BOOST_FOREACH(::urdf::LinkPtr child, movable_child_links)
-          {
-            child->getParent()->parent_joint->name = model.names[0];
-            parseTree(child, model, SE3::Identity(), verbose);
-          }
-          
-        }
-        else // Otherwise, we have to rase an exception because the first link will no be added to the model.
-          // It seems a root joint is missing.
+        appendBodyToJoint(model, 0, root_link->inertial, SE3::Identity(), root_link->name);
+
+        BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links)
         {
-          std::cout << "[INFO] The root link " << root_link->name << " of the model tree contains inertial information. It seems that a root joint is missing connecting this root link to the universe. The root link won't affect the dynamics of the model." << std::endl;
-          
-          BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links)
-          {
-            parseTree(child, model, SE3::Identity(), verbose);
-          }
+          parseTree(child, model, verbose);
         }
-        
-        
+
+        // Inertias might be zero due to the URDF file. This is not a bug. However, it would lead to some
+        // algorithms of Pinocchio not to work.
+        // TODO: add an algorithm or a method in model to check the validity of the value wrt to the algorithms the user want to use.
+        // See also #306 on GitHub.
       }
 
       ///
@@ -524,48 +530,16 @@ namespace se3
       template <typename D>
       void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const JointModelBase<D> & root_joint, const bool verbose) throw (std::invalid_argument)
       {
-        // If the root link has no inertial info (because it is a base_link for example),
-        // we have to merge its inertial info with all its children connected to it with fixed joints
-        if (!root_link->inertial)
-        {
-          // If the root link has only one child
-          if (root_link->child_links.size() == 1)
-          {
-            ::urdf::LinkPtr child_link = root_link->child_links[0];
-            assert(child_link->inertial != NULL && "Inertial information missing for parsing the root link.");
-            const Inertia & Y = convertFromUrdf(*child_link->inertial);
-            addJointAndBody(model,root_joint,
-                            0,SE3::Identity(),"root_joint",
-                            Y,child_link->name);
-          
-            // Change the name of the parent joint in the URDF tree
-            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 (root_link->name + " has no inertial information and has more than one child link. It corresponds to a disjoint tree.");
-            throw std::invalid_argument(exception_message);
-          }
-        
-        }
-        else // otherwise, it is a plain body with inertial info. It processes as usual.
+        addJointAndBody(model,root_joint,
+            0,SE3::Identity(),"root_joint",
+            root_link->inertial,root_link->name);
+
+        BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links)
         {
-          const Inertia & Y = convertFromUrdf(*root_link->inertial);
-          addJointAndBody(model,root_joint,
-                          0,SE3::Identity(),"root_joint",
-                          Y,root_link->name);
-        
-          BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links)
-          {
-            parseTree(child, model, SE3::Identity(), verbose);
-          }
+          parseTree(child, model, verbose);
         }
 
+        // FIXME: See fixme in previous parseRootTree definition
       }
     } // namespace details
               
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
index 023d1b3db9153233922030630e9554e9a3d798a4..caaf613985a090492a6a6476227d2a7b82c3161c 100644
--- a/unittest/CMakeLists.txt
+++ b/unittest/CMakeLists.txt
@@ -115,3 +115,5 @@ ADD_UNIT_TEST(explog eigen3)
 ADD_UNIT_TEST(finite-differences eigen3)
 ADD_UNIT_TEST(visitor eigen3)
 ADD_UNIT_TEST(algo-check eigen3)
+ADD_UNIT_TEST(joint-composite eigen3)
+
diff --git a/unittest/compute-all-terms.cpp b/unittest/compute-all-terms.cpp
index 368db7155c4f9ca2a3edc2c3f93aa564192642dd..9f8c9cb9c38dffd790600170549a5a9ccf6c6b90 100644
--- a/unittest/compute-all-terms.cpp
+++ b/unittest/compute-all-terms.cpp
@@ -73,7 +73,7 @@ BOOST_AUTO_TEST_CASE ( test_against_algo )
   BOOST_CHECK (data.J.isApprox(data_other.J, 1e-12));
   BOOST_CHECK (data.Jcom.isApprox(data_other.Jcom, 1e-12));
   
-  for (int k=0; k<model.njoint; ++k)
+  for (int k=0; k<model.njoints; ++k)
   {
     BOOST_CHECK (data.com[(size_t)k].isApprox(data_other.com[(size_t)k], 1e-12));
     BOOST_CHECK (data.vcom[(size_t)k].isApprox(data_other.vcom[(size_t)k], 1e-12));
@@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE ( test_against_algo )
   BOOST_CHECK (data.J.isApprox(data_other.J, 1e-12));
   BOOST_CHECK (data.Jcom.isApprox(data_other.Jcom, 1e-12));
   
-  for (int k=0; k<model.njoint; ++k)
+  for (int k=0; k<model.njoints; ++k)
   {
     BOOST_CHECK (data.com[(size_t)k].isApprox(data_other.com[(size_t)k], 1e-12));
     BOOST_CHECK (data.vcom[(size_t)k].isApprox(data_other.vcom[(size_t)k], 1e-12));
@@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE ( test_against_algo )
   BOOST_CHECK (data.J.isApprox(data_other.J, 1e-12));
   BOOST_CHECK (data.Jcom.isApprox(data_other.Jcom, 1e-12));
   
-  for (int k=0; k<model.njoint; ++k)
+  for (int k=0; k<model.njoints; ++k)
   {
     BOOST_CHECK (data.com[(size_t)k].isApprox(data_other.com[(size_t)k], 1e-12));
     BOOST_CHECK (data.vcom[(size_t)k].isApprox(data_other.vcom[(size_t)k], 1e-12));
@@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE ( test_against_algo )
   BOOST_CHECK (data.J.isApprox(data_other.J, 1e-12));
   BOOST_CHECK (data.Jcom.isApprox(data_other.Jcom, 1e-12));
   
-  for (int k=0; k<model.njoint; ++k)
+  for (int k=0; k<model.njoints; ++k)
   {
     BOOST_CHECK (data.com[(size_t)k].isApprox(data_other.com[(size_t)k], 1e-12));
     BOOST_CHECK (data.vcom[(size_t)k].isApprox(data_other.vcom[(size_t)k], 1e-12));
diff --git a/unittest/finite-differences.cpp b/unittest/finite-differences.cpp
index 23fb794562d399c1e1d00f5f8622cbc7cd6e208b..deaf7b9b2ae02c7071c0bacb6d75a7ad39610305 100644
--- a/unittest/finite-differences.cpp
+++ b/unittest/finite-differences.cpp
@@ -129,6 +129,49 @@ void FiniteDiffJoint::init<JointModelPrismaticUnaligned>(JointModelBase<JointMod
 template<>
 void FiniteDiffJoint::operator()< JointModelDense<-1,-1> > (JointModelBase< JointModelDense<-1,-1> > & /*jmodel*/) const {}
 
+template<>
+void FiniteDiffJoint::operator()< JointModelComposite > (JointModelBase<JointModelComposite> & ) const
+{
+  typedef typename JointModel::ConfigVector_t CV;
+  typedef typename JointModel::TangentVector_t TV;
+  
+  se3::JointModelComposite jmodel((se3::JointModelRX())/*, (se3::JointModelRY())*/);
+  jmodel.setIndexes(0,0,0);
+  jmodel.updateComponentsIndexes();
+
+  se3::JointModelComposite::JointDataDerived jdata = jmodel.createData();
+
+  CV q = jmodel.random();
+  jmodel.calc(jdata,q);
+  SE3 M_ref(jdata.M);
+  
+  CV q_int;
+  TV v(Eigen::VectorXd::Random(jmodel.nv())); v.setZero();
+  double eps = 1e-4;
+  
+  assert(q.size() == jmodel.nq()&& "nq false");
+  assert(v.size() == jmodel.nv()&& "nv false");
+  Eigen::MatrixXd S(6,jmodel.nv()), S_ref(ConstraintXd(jdata.S).matrix());
+
+  eps = jmodel.finiteDifferenceIncrement();
+  for(int k=0;k<jmodel.nv();++k)
+  {
+    v[k] = eps;
+    q_int = jmodel.integrate(q,v);
+    jmodel.calc(jdata,q_int);
+    SE3 M_int = jdata.M;
+    
+    S.col(k) = log6(M_ref.inverse()*M_int).toVector();
+    S.col(k) /= eps;
+    
+    v[k] = 0.;
+  }
+  
+  std::cout << "S\n" << S << std::endl;
+  std::cout << "S_ref\n" << S_ref << std::endl;
+  // BOOST_CHECK(S.isApprox(S_ref,eps*1e1)); //@TODO Uncomment to test once JointComposite maths are ok
+}
+
 BOOST_AUTO_TEST_SUITE(FiniteDifferences)
 
 BOOST_AUTO_TEST_CASE(increment)
@@ -165,7 +208,7 @@ BOOST_AUTO_TEST_CASE (test_jacobian_vs_finit_diff)
   q.segment<4>(3).normalize();
   computeJacobians(model,data,q);
 
-  Model::Index idx = model.existJointName("rarm2")?model.getJointId("rarm2"):(Model::Index)(model.njoint-1);
+  Model::Index idx = model.existJointName("rarm2")?model.getJointId("rarm2"):(Model::Index)(model.njoints-1);
   Data::Matrix6x Jrh(6,model.nv); Jrh.fill(0);
   
   getJacobian<false>(model,data,idx,Jrh);
diff --git a/unittest/frames.cpp b/unittest/frames.cpp
index 1b305cf0d40c9e4100427f9c5fa8b16a92461d6d..7b08529aeed99103f18a769ebd4e797b6d36353d 100644
--- a/unittest/frames.cpp
+++ b/unittest/frames.cpp
@@ -39,10 +39,10 @@ BOOST_AUTO_TEST_CASE ( test_kinematics )
 
   se3::Model model;
   se3::buildModels::humanoidSimple(model);
-  Model::Index parent_idx = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoint-1);
-  const std::string & frame_name = std::string( model.getJointName(parent_idx)+ "_frame");
+  Model::Index parent_idx = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoints-1);
+  const std::string & frame_name = std::string( model.names[parent_idx]+ "_frame");
   const SE3 & framePlacement = SE3::Random();
-  model.addFrame(frame_name, parent_idx, framePlacement);
+  model.addFrame(Frame (frame_name, parent_idx, -1, framePlacement, OP_FRAME));
   se3::Data data(model);
 
   VectorXd q = VectorXd::Ones(model.nq);
@@ -61,10 +61,10 @@ BOOST_AUTO_TEST_CASE ( test_jacobian )
 
   Model model;
   buildModels::humanoidSimple(model);
-  Model::Index parent_idx = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoint-1);
-  const std::string & frame_name = std::string( model.getJointName(parent_idx)+ "_frame");
+  Model::Index parent_idx = model.existJointName("rarm2_joint")?model.getJointId("rarm2_joint"):(Model::Index)(model.njoints-1);
+  const std::string & frame_name = std::string( model.names[parent_idx]+ "_frame");
   const SE3 & framePlacement = SE3::Random();
-  model.addFrame(frame_name, parent_idx, framePlacement);
+  model.addFrame(Frame (frame_name, parent_idx, -1, framePlacement, OP_FRAME));
   se3::Data data(model);
 
   VectorXd q = VectorXd::Ones(model.nq);
diff --git a/unittest/geom.cpp b/unittest/geom.cpp
index 434cd996f2c8b947e156926e92f5a5cc92bd4b59..3ed7e473c4c09c0e238e41cf266458c618fcff2d 100644
--- a/unittest/geom.cpp
+++ b/unittest/geom.cpp
@@ -48,7 +48,8 @@ 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::Model& model, const se3::Data & data);
-GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryData & data_geom);
+GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryModel & geomModel,
+                                                      const se3::GeometryData & geomData);
 #ifdef WITH_HPP_MODEL_URDF
 JointPositionsMap_t fillHppJointPositions(const hpp::model::HumanoidRobotPtr_t robot);
 GeometryPositionsMap_t fillHppGeometryPositions(const hpp::model::HumanoidRobotPtr_t robot);
@@ -145,53 +146,68 @@ BOOST_AUTO_TEST_CASE ( simple_boxes )
 {
   using namespace se3;
   Model model;
-  GeometryModel model_geom;
+  GeometryModel geomModel;
 
   Model::JointIndex idx;
   idx = model.addJoint(model.getJointId("universe"),JointModelPlanar(),SE3::Identity(),"planar1_joint");
-  model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"planar1_body");
+  model.addJointFrame(idx);
+  model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity());
+  model.addBodyFrame("planar1_body", idx, SE3::Identity());
   
   idx = model.addJoint(model.getJointId("universe"),JointModelPlanar(),SE3::Identity(),"planar2_joint");
-  model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity(),"planar2_body");
+  model.addJointFrame(idx);
+  model.appendBodyToJoint(idx,Inertia::Random(),SE3::Identity());
+  model.addBodyFrame("planar2_body", idx, SE3::Identity());
   
   boost::shared_ptr<fcl::Box> sample(new fcl::Box(1));
-  model_geom.addGeometryObject(model.getJointId("planar1_joint"),sample, SE3::Identity(),  "ff1_collision_object", "");
+  geomModel.addGeometryObject(GeometryObject("ff1_collision_object",
+                                             model.getBodyId("planar1_body"),0,
+                                             sample,SE3::Identity(), ""),
+                              model,true);
   
   boost::shared_ptr<fcl::Box> sample2(new fcl::Box(1));
-  model_geom.addGeometryObject(model.getJointId("planar2_joint"),sample2, SE3::Identity(),  "ff2_collision_object", "");
+  geomModel.addGeometryObject(GeometryObject("ff2_collision_object",
+                                             model.getBodyId("planar2_body"),0,
+                                             sample2,SE3::Identity(), ""),
+                              model,true);
 
+  geomModel.addAllCollisionPairs();
   se3::Data data(model);
-  se3::GeometryData data_geom(model_geom);
+  se3::GeometryData geomData(geomModel);
+
+  BOOST_CHECK(CollisionPair(0,1) == geomModel.collisionPairs[0]);
 
   std::cout << "------ Model ------ " << std::endl;
   std::cout << model;
   std::cout << "------ Geom ------ " << std::endl;
-  std::cout << model_geom;
+  std::cout << geomModel;
   std::cout << "------ DataGeom ------ " << std::endl;
-  std::cout << data_geom;
-  BOOST_CHECK(data_geom.computeCollision(CollisionPair(0,1)).fcl_collision_result.isCollision() == true);
+  std::cout << geomData;
 
   Eigen::VectorXd q(model.nq);
+  q <<  0, 0, 0,
+        0, 0, 0 ;
+
+  se3::updateGeometryPlacements(model, data, geomModel, geomData, q);
+  BOOST_CHECK(computeCollision(geomModel,geomData,0) == true);
+
   q <<  2, 0, 0,
         0, 0, 0 ;
 
-  se3::updateGeometryPlacements(model, data, model_geom, data_geom, q);
-  std::cout << data_geom;
-  BOOST_CHECK(data_geom.computeCollision(CollisionPair(0,1)).fcl_collision_result.isCollision() == false);
+  se3::updateGeometryPlacements(model, data, geomModel, geomData, q);
+  BOOST_CHECK(computeCollision(geomModel,geomData,0) == false);
 
   q <<  0.99, 0, 0,
         0, 0, 0 ;
 
-  se3::updateGeometryPlacements(model, data, model_geom, data_geom, q);
-  std::cout << data_geom;
-  BOOST_CHECK(data_geom.computeCollision(CollisionPair(0,1)).fcl_collision_result.isCollision() == true);
+  se3::updateGeometryPlacements(model, data, geomModel, geomData, q);
+  BOOST_CHECK(computeCollision(geomModel,geomData,0) == true);
 
   q <<  1.01, 0, 0,
         0, 0, 0 ;
 
-  se3::updateGeometryPlacements(model, data, model_geom, data_geom, q);
-  std::cout << data_geom;
-  BOOST_CHECK(data_geom.computeCollision(CollisionPair(0,1)).fcl_collision_result.isCollision() == false);
+  se3::updateGeometryPlacements(model, data, geomModel, geomData, q);
+  BOOST_CHECK(computeCollision(geomModel,geomData,0) == false);
 }
 
 BOOST_AUTO_TEST_CASE ( loading_model )
@@ -203,44 +219,48 @@ BOOST_AUTO_TEST_CASE ( loading_model )
 
 
   std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
-  std::vector < std::string > package_dirs;
+  std::vector < std::string > packageDirs;
   std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
-  package_dirs.push_back(meshDir);
+  packageDirs.push_back(meshDir);
 
   Model model;
   se3::urdf::buildModel(filename, se3::JointModelFreeFlyer(),model);
-  GeometryModel geometry_model = se3::urdf::buildGeom(model, filename, package_dirs, se3::COLLISION);
+  GeometryModel geomModel;
+  se3::urdf::buildGeom(model, filename, se3::COLLISION, geomModel, packageDirs );
+  geomModel.addAllCollisionPairs();
 
   Data data(model);
-  GeometryData geometry_data(geometry_model);
+  GeometryData geomData(geomModel);
+  fcl::CollisionResult result;
 
   Eigen::VectorXd q(model.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::updateGeometryPlacements(model, data, geometry_model, geometry_data, q);
-  BOOST_CHECK(geometry_data.computeCollision(CollisionPair(1,10)).fcl_collision_result.isCollision() == false);
+  se3::updateGeometryPlacements(model, data, geomModel, geomData, q);
+  se3::Index idx = geomModel.findCollisionPair(CollisionPair(1,10));
+  BOOST_CHECK(computeCollision(geomModel,geomData,idx) == false);
 }
 
 
 #if defined(WITH_URDFDOM) && defined(WITH_HPP_FCL)
 BOOST_AUTO_TEST_CASE (radius)
 {
+  std::vector < std::string > packageDirs;
 #ifdef ROMEO_DESCRIPTION_MODEL_DIR
   std::string filename = ROMEO_DESCRIPTION_MODEL_DIR"/romeo_description/urdf/romeo_small.urdf";
-  std::vector < std::string > package_dirs;
-  package_dirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
+  packageDirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
 #else
   std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
-  std::vector < std::string > package_dirs;
   std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
-  package_dirs.push_back(meshDir);
+  packageDirs.push_back(meshDir);
 #endif // ROMEO_DESCRIPTION_MODEL_DIR
 
   se3::Model model;
   se3::urdf::buildModel(filename, se3::JointModelFreeFlyer(),model);
-  se3::GeometryModel geom = se3::urdf::buildGeom(model, filename, package_dirs, se3::COLLISION);
+  se3::GeometryModel geom;
+  se3::urdf::buildGeom(model, filename, se3::COLLISION, geom, packageDirs);
   Data data(model);
   GeometryData geomData(geom);
 
@@ -276,7 +296,8 @@ BOOST_AUTO_TEST_CASE (radius)
       std::string bodyName = body->name();
       if(bodyName != "base_link")
       {
-        double radius_pino = geomData.radius[model.getFrameParent(bodyName)];
+        FrameIndex fid = model.getFrameId(bodyName, BODY);
+        double radius_pino = geomData.radius[model.frames[fid].parent];
         BOOST_CHECK_MESSAGE(radius_hpp - radius_pino < 1e-6, "Radius of body " << bodyName << " are not equals between hpp and pinocchio");
       }
 
@@ -296,9 +317,6 @@ BOOST_AUTO_TEST_CASE ( romeo_joints_meshes_positions )
   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;
 
 
 
@@ -306,18 +324,25 @@ BOOST_AUTO_TEST_CASE ( romeo_joints_meshes_positions )
   /// ********************************* ///
 
   // Building the model in pinocchio and compute kinematics/geometry for configuration q_pino
+  std::vector < std::string > packageDirs;
+#ifdef ROMEO_DESCRIPTION_MODEL_DIR
   std::string filename = ROMEO_DESCRIPTION_MODEL_DIR"/romeo_description/urdf/romeo_small.urdf";
-  std::vector < std::string > package_dirs;
-  package_dirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
+  packageDirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
+#else
+  std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  packageDirs.push_back(meshDir);
+#endif // ROMEO_DESCRIPTION_MODEL_DIR
 
-  se3::Model model;
+  Model model;
   se3::urdf::buildModel(filename, se3::JointModelFreeFlyer(),model);
-  se3::GeometryModel geom = se3::urdf::buildGeom(model, filename, package_dirs, se3::COLLISION);
+  se3::GeometryModel geom;
+  se3::urdf::buildGeom(model, filename, se3::COLLISION, geom, packageDirs);
   std::cout << model << std::endl;
 
 
   Data data(model);
-  GeometryData data_geom(geom);
+  GeometryData geomData(geom);
 
   // Configuration to be tested
   
@@ -332,7 +357,7 @@ BOOST_AUTO_TEST_CASE ( romeo_joints_meshes_positions )
 
   BOOST_CHECK_MESSAGE(q_pino.size() == model.nq , "wrong config size" );
 
-  se3::updateGeometryPlacements(model, data, geom, data_geom, q_pino);
+  se3::updateGeometryPlacements(model, data, geom, geomData, q_pino);
 
 
   /// *************  HPP  ************* /// 
@@ -357,7 +382,7 @@ BOOST_AUTO_TEST_CASE ( romeo_joints_meshes_positions )
   // retrieve all joint and geometry objects positions
   JointPositionsMap_t joints_pin  = fillPinocchioJointPositions(model, data);
   JointPositionsMap_t joints_hpp  = fillHppJointPositions(humanoidRobot);
-  GeometryPositionsMap_t geom_pin = fillPinocchioGeometryPositions(data_geom);
+  GeometryPositionsMap_t geom_pin = fillPinocchioGeometryPositions(geom, geomData);
   GeometryPositionsMap_t geom_hpp = fillHppGeometryPositions(humanoidRobot);
 
 
@@ -403,28 +428,32 @@ BOOST_AUTO_TEST_CASE ( hrp2_mesh_distance)
   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::vector < std::string > packageDirs;
+#ifdef ROMEO_DESCRIPTION_MODEL_DIR
   std::string filename = ROMEO_DESCRIPTION_MODEL_DIR"/romeo_description/urdf/romeo_small.urdf";
-  std::vector < std::string > package_dirs;
-  package_dirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
+  packageDirs.push_back(ROMEO_DESCRIPTION_MODEL_DIR);
+#else
+  std::string filename = PINOCCHIO_SOURCE_DIR"/models/romeo.urdf";
+  std::string meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
+  packageDirs.push_back(meshDir);
+#endif // ROMEO_DESCRIPTION_MODEL_DIR
 
-  se3::Model model;
+  Model model;
   se3::urdf::buildModel(filename, se3::JointModelFreeFlyer(),model);
-  se3::GeometryModel geom = se3::urdf::buildGeom(model, filename, package_dirs, se3::COLLISION);
+  se3::GeometryModel geom;
+  se3::urdf::buildGeom(model, filename, se3::COLLISION, geom, packageDirs);
+  geom.addAllCollisionPairs();
   std::cout << model << std::endl;
 
 
   Data data(model);
-  GeometryData data_geom(geom);
+  GeometryData geomData(geom);
 
   // Configuration to be tested
   
@@ -439,7 +468,7 @@ BOOST_AUTO_TEST_CASE ( hrp2_mesh_distance)
 
   BOOST_CHECK_MESSAGE(q_pino.size() == model.nq , "wrong config size");
 
-  se3::updateGeometryPlacements(model, data, geom, data_geom, q_pino);
+  se3::updateGeometryPlacements(model, data, geom, geomData, q_pino);
 
 
   /// *************  HPP  ************* /// 
@@ -482,12 +511,14 @@ BOOST_AUTO_TEST_CASE ( hrp2_mesh_distance)
 
 
         std::cout << "comparison between " << body1 << " and " << body2 << std::endl;
+        se3::CollisionPair pair (geom.getGeometryId(body1),
+                                 geom.getGeometryId(body2));
+        BOOST_REQUIRE (geom.existCollisionPair(pair));
 
-        se3::DistanceResult dist_pin
-          = data_geom.computeDistance( CollisionPair(geom.getGeometryId(body1),
-                                                     geom.getGeometryId(body2)) );
+        fcl::DistanceResult dist_pin
+          = se3::computeDistance( geom, geomData, geom.findCollisionPair(pair));
 
-        Distance_t distance_pin(dist_pin.fcl_distance_result);
+        Distance_t distance_pin(dist_pin);
         distance_hpp.checkClose(distance_pin);
       }
     }
@@ -500,19 +531,20 @@ BOOST_AUTO_TEST_SUITE_END ()
 JointPositionsMap_t fillPinocchioJointPositions(const se3::Model& model, const se3::Data & data)
 {
   JointPositionsMap_t result;
-  for (se3::Model::Index i = 0; i < (se3::Model::Index)model.njoint; ++i)
+  for (se3::Model::Index i = 0; i < (se3::Model::Index)model.njoints; ++i)
   {
-    result[model.getJointName(i)] = data.oMi[i];
+    result[model.names[i]] = data.oMi[i];
   }
   return result;
 }
 
-GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryData & data_geom)
+GeometryPositionsMap_t fillPinocchioGeometryPositions(const se3::GeometryModel & geomModel,
+                                                      const se3::GeometryData & geomData)
 {
   GeometryPositionsMap_t result;
-  for (std::size_t i = 0; i < data_geom.model_geom.ngeoms ; ++i)
+  for (std::size_t i = 0; i < geomModel.ngeoms ; ++i)
   {
-    result[data_geom.model_geom.getGeometryName(i)] = data_geom.oMg[i];
+    result[geomModel.getGeometryName(i)] = geomData.oMg[i];
   }
   return result;
 }
diff --git a/unittest/jacobian.cpp b/unittest/jacobian.cpp
index 9c6e4b855610a773d2fc08bfd04613e8c79e98c0..c664eed8c5ef903a746c0893310a730da178c201 100644
--- a/unittest/jacobian.cpp
+++ b/unittest/jacobian.cpp
@@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE ( test_jacobian )
   VectorXd q = VectorXd::Zero(model.nq);
   computeJacobians(model,data,q);
 
-  Model::Index idx = model.existJointName("rarm2")?model.getJointId("rarm2"):(Model::Index)(model.njoint-1); 
+  Model::Index idx = model.existJointName("rarm2")?model.getJointId("rarm2"):(Model::Index)(model.njoints-1); 
   Data::Matrix6x Jrh(6,model.nv); Jrh.fill(0);
   getJacobian<false>(model,data,idx,Jrh);
 
@@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE ( test_timings )
   if( flag >> 1 & 1 )
   {
     computeJacobians(model,data,q);
-    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoint-1); 
+    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoints-1); 
     Data::Matrix6x Jrh(6,model.nv); Jrh.fill(0);
 
     timer.tic();
@@ -125,7 +125,7 @@ BOOST_AUTO_TEST_CASE ( test_timings )
   if( flag >> 2 & 1 )
   {
     computeJacobians(model,data,q);
-    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoint-1); 
+    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoints-1); 
     Data::Matrix6x Jrh(6,model.nv); Jrh.fill(0);
 
     timer.tic();
@@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE ( test_timings )
   if( flag >> 3 & 1 )
   {
     computeJacobians(model,data,q);
-    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoint-1); 
+    Model::Index idx = model.existJointName("rarm6")?model.getJointId("rarm6"):(Model::Index)(model.njoints-1); 
     Data::Matrix6x Jrh(6,model.nv); Jrh.fill(0);
 
     timer.tic();
diff --git a/unittest/joint-composite.cpp b/unittest/joint-composite.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef342624c57d04a13a3e4f07510deb88f3619b56
--- /dev/null
+++ b/unittest/joint-composite.cpp
@@ -0,0 +1,318 @@
+//
+// Copyright (c) 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/tools/timer.hpp"
+
+// #include "pinocchio/multibody/joint/joint-accessor.hpp"
+#include "pinocchio/multibody/joint/joint-composite.hpp"
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/algorithm/aba.hpp"
+#include "pinocchio/algorithm/joint-configuration.hpp"
+#include "pinocchio/algorithm/compute-all-terms.hpp"
+#include "pinocchio/algorithm/jacobian.hpp"
+
+#include <iostream>
+#include <cmath>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE JointCompositeTest
+#include <boost/test/unit_test.hpp>
+#include <boost/utility/binary.hpp>
+
+
+template <typename T>
+void test_joint_methods (T & jmodel)
+{
+  using namespace se3;
+
+  typename T::JointDataDerived jdata = jmodel.createData();
+
+  JointModelComposite jmodel_composite(jmodel);
+  jmodel_composite.setIndexes(jmodel.id(), jmodel.idx_q(), jmodel.idx_v());
+  jmodel_composite.updateComponentsIndexes();
+
+  JointDataComposite jdata_composite = jmodel_composite.createData();
+
+  Eigen::VectorXd q1(Eigen::VectorXd::Random (jmodel.nq()));jmodel_composite.normalize(q1);
+  Eigen::VectorXd q1_dot(Eigen::VectorXd::Random (jmodel.nv()));
+  Eigen::VectorXd q2(Eigen::VectorXd::Random (jmodel.nq()));jmodel_composite.normalize(q2);
+  double u = 0.3;
+  se3::Inertia::Matrix6 Ia(se3::Inertia::Random().matrix());
+  bool update_I = false;
+
+  jmodel.calc(jdata, q1, q1_dot);
+  jmodel_composite.calc(jdata_composite, q1, q1_dot);
+
+
+  std::string error_prefix("Joint Model Composite on " + jmodel.shortname());
+
+  BOOST_CHECK_MESSAGE(jmodel.nq() == jmodel_composite.nq() ,std::string(error_prefix + " - nq "));
+  BOOST_CHECK_MESSAGE(jmodel.nv() == jmodel_composite.nv() ,std::string(error_prefix + " - nv "));
+
+  BOOST_CHECK_MESSAGE(jmodel.idx_q() == jmodel_composite.idx_q() ,std::string(error_prefix + " - Idx_q "));
+  BOOST_CHECK_MESSAGE(jmodel.idx_v() == jmodel_composite.idx_v() ,std::string(error_prefix + " - Idx_v "));
+  BOOST_CHECK_MESSAGE(jmodel.id() == jmodel_composite.id() ,std::string(error_prefix + " - JointId "));
+
+  BOOST_CHECK_MESSAGE(jmodel.integrate(q1,q1_dot).isApprox(jmodel_composite.integrate(q1,q1_dot)) ,std::string(error_prefix + " - integrate "));
+  BOOST_CHECK_MESSAGE(jmodel.interpolate(q1,q2,u).isApprox(jmodel_composite.interpolate(q1,q2,u)) ,std::string(error_prefix + " - interpolate "));
+  BOOST_CHECK_MESSAGE(jmodel.randomConfiguration( -1 * Eigen::VectorXd::Ones(jmodel.nq()),
+                                              Eigen::VectorXd::Ones(jmodel.nq())).size()
+                                  == jmodel_composite.randomConfiguration(-1 * Eigen::VectorXd::Ones(jmodel.nq()),
+                                                            Eigen::VectorXd::Ones(jmodel.nq())).size()
+                      ,std::string(error_prefix + " - RandomConfiguration dimensions "));
+
+  BOOST_CHECK_MESSAGE(jmodel.difference(q1,q2).isApprox(jmodel_composite.difference(q1,q2)) ,std::string(error_prefix + " - difference "));
+  BOOST_CHECK_MESSAGE(fabs(jmodel.distance(q1,q2) - jmodel_composite.distance(q1,q2)) <= 1e-6 ,std::string(error_prefix + " - distance "));
+
+  BOOST_CHECK_MESSAGE(((ConstraintXd)jdata.S).matrix().isApprox((jdata_composite.S.matrix())),std::string(error_prefix + " - ConstraintXd "));
+  BOOST_CHECK_MESSAGE(jdata.M == jdata_composite.M, std::string(error_prefix + " - Joint transforms ")); // ==  or isApprox ?
+  BOOST_CHECK_MESSAGE((Motion)jdata.v == jdata_composite.v, std::string(error_prefix + " - Joint motions "));
+  BOOST_CHECK_MESSAGE((Motion)jdata.c == jdata_composite.c, std::string(error_prefix + " - Joint bias "));
+  
+  jmodel.calc_aba(jdata, Ia, update_I);
+  jmodel_composite.calc_aba(jdata_composite, Ia, update_I);
+
+  BOOST_CHECK_MESSAGE((jdata.U).isApprox(jdata_composite.U), std::string(error_prefix + " - Joint U inertia matrix decomposition "));
+  BOOST_CHECK_MESSAGE((jdata.Dinv).isApprox(jdata_composite.Dinv), std::string(error_prefix + " - Joint DInv inertia matrix decomposition "));
+  BOOST_CHECK_MESSAGE((jdata.UDinv).isApprox(jdata_composite.UDinv), std::string(error_prefix + " - Joint UDInv inertia matrix decomposition "));
+
+ 
+}
+
+struct TestJointComposite{
+
+  template <typename T>
+  void operator()(const T ) const
+  {
+    T jmodel;
+    jmodel.setIndexes(0,0,0);
+
+    test_joint_methods(jmodel);    
+  }
+
+  template <int NQ, int NV>
+  void operator()(const se3::JointModelDense<NQ,NV> & ) const
+  {
+    // Not yet correctly implemented, test has no meaning for the moment
+  }
+
+  void operator()(const se3::JointModelComposite & ) const
+  {
+    se3::JointModelComposite jmodel_composite_rx(2);
+    jmodel_composite_rx.addJointModel(se3::JointModelRX());
+    jmodel_composite_rx.addJointModel(se3::JointModelRY());
+    jmodel_composite_rx.setIndexes(1,0,0);
+    jmodel_composite_rx.updateComponentsIndexes();
+
+    test_joint_methods(jmodel_composite_rx);
+
+  }
+
+  void operator()(const se3::JointModelRevoluteUnaligned & ) const
+  {
+    se3::JointModelRevoluteUnaligned jmodel(1.5, 1., 0.);
+    jmodel.setIndexes(0,0,0);
+
+    test_joint_methods(jmodel);
+  }
+
+  void operator()(const se3::JointModelPrismaticUnaligned & ) const
+  {
+    se3::JointModelPrismaticUnaligned jmodel(1.5, 1., 0.);
+    jmodel.setIndexes(0,0,0);
+
+    test_joint_methods(jmodel);
+  }
+
+};
+
+
+
+
+BOOST_AUTO_TEST_SUITE ( JointCompositeTest)
+
+// Test that a composite joint can contain any type of joint
+BOOST_AUTO_TEST_CASE ( test_all_joints )
+{
+  using namespace Eigen;
+  using namespace se3;
+
+  boost::mpl::for_each<JointModelVariant::types>(TestJointComposite());
+
+}
+
+
+
+BOOST_AUTO_TEST_CASE ( test_recursive_variant)
+{
+  // functional test. Test if one can create a composite joint containing composite joint
+
+  using namespace Eigen;
+  using namespace se3;
+
+  /// Create joint composite with two joints,
+  JointModelComposite jmodel_composite_two_rx(2);
+  jmodel_composite_two_rx.addJointModel(JointModelRX());
+  jmodel_composite_two_rx.addJointModel(JointModelRY());
+
+  /// Create Joint composite with three joints, and add a composite in it, to test the recursive_wrapper
+  JointModelComposite jmodel_composite_recursive(3);
+  jmodel_composite_recursive.addJointModel(JointModelFreeFlyer());
+  jmodel_composite_recursive.addJointModel(JointModelPlanar());
+  jmodel_composite_recursive.addJointModel(jmodel_composite_two_rx);
+  
+}
+
+
+BOOST_AUTO_TEST_CASE (TestCopyComposite)
+{
+
+  using namespace Eigen;
+  using namespace se3;
+
+  JointModelComposite jmodel_composite_planar(3);
+  jmodel_composite_planar.addJointModel(JointModelPX());
+  jmodel_composite_planar.addJointModel(JointModelPY());
+  jmodel_composite_planar.addJointModel(JointModelRZ());
+  jmodel_composite_planar.setIndexes(1,0,0);
+  jmodel_composite_planar.updateComponentsIndexes();
+
+
+  JointDataComposite jdata_composite_planar = jmodel_composite_planar.createData();
+
+  Eigen::VectorXd q1(Eigen::VectorXd::Random(3));
+  Eigen::VectorXd q1_dot(Eigen::VectorXd::Random(3));
+
+  JointModelComposite model_copy = jmodel_composite_planar;
+  JointDataComposite data_copy = model_copy.createData();
+  
+  BOOST_CHECK_MESSAGE( model_copy.max_joints == jmodel_composite_planar.max_joints, "Test Copy Composite, max_joints are differents");
+  BOOST_CHECK_MESSAGE( model_copy.nq() == jmodel_composite_planar.nq(), "Test Copy Composite, nq are differents");
+  BOOST_CHECK_MESSAGE( model_copy.nv() == jmodel_composite_planar.nv(), "Test Copy Composite, nv are differents");
+
+  BOOST_CHECK_MESSAGE( model_copy.max_joints == jmodel_composite_planar.max_joints, "Test Copy Composite, max_joints are differents");
+
+  jmodel_composite_planar.calc(jdata_composite_planar,q1, q1_dot);
+  model_copy.calc(data_copy,q1, q1_dot);
+
+}
+
+
+BOOST_AUTO_TEST_CASE ( test_R3xSO3)
+{
+  std::cout << " Testing R3xSO3 vs jointcomposite<R3 - SO3>" << std::endl;
+  using namespace Eigen;
+  using namespace se3;
+
+  Model model_composite;
+  Model model_zero_mass;
+  Model model_ff;
+
+
+
+  Inertia body_inertia(Inertia::Random());
+  SE3 placement(SE3::Identity());
+
+  model_zero_mass.addJoint(model_zero_mass.getJointId("universe"),JointModelTranslation(), placement, "R3_joint");
+  model_zero_mass.addJoint(model_zero_mass.getJointId("R3_joint"), JointModelSpherical(), SE3::Identity(), "SO3_joint");
+  model_zero_mass.appendBodyToJoint(model_zero_mass.getJointId("SO3_joint"), body_inertia, SE3::Identity());
+
+  JointModelComposite jmodel_composite(2);
+  jmodel_composite.addJointModel(JointModelTranslation());
+  jmodel_composite.addJointModel(JointModelSpherical());
+  
+  model_composite.addJoint(model_composite.getJointId("universe"),jmodel_composite, placement, "composite_R3xSO3_joint");
+  model_composite.appendBodyToJoint(model_composite.getJointId("composite_R3xSO3_joint"), body_inertia, SE3::Identity());
+
+  model_ff.addJoint(model_ff.getJointId("universe"),JointModelFreeFlyer(), placement, "ff_joint");
+  model_ff.appendBodyToJoint(model_ff.getJointId("ff_joint"), body_inertia, SE3::Identity());
+
+  BOOST_CHECK_MESSAGE(model_composite.nq == model_zero_mass.nq ,"Model with R3 - SO3 vs composite <R3xSO3> - dimensions nq are not equal");
+  BOOST_CHECK_MESSAGE(model_composite.nq == model_zero_mass.nq ,"Model with R3 - SO3 vs composite <R3xSO3> - dimensions nv are not equal");
+
+
+  Data data_zero_mass(model_zero_mass);
+  Data data_composite(model_composite);
+  Data data_ff(model_ff);
+
+  Eigen::VectorXd q(Eigen::VectorXd::Random(model_zero_mass.nq));normalize(model_zero_mass,q);
+  Eigen::VectorXd q_dot(Eigen::VectorXd::Random(model_zero_mass.nv));
+  Eigen::VectorXd q_ddot(Eigen::VectorXd::Random(model_zero_mass.nv));
+  Eigen::VectorXd q1(Eigen::VectorXd::Random(model_zero_mass.nq));normalize(model_zero_mass,q1);
+  Eigen::VectorXd q2(Eigen::VectorXd::Random(model_zero_mass.nq));normalize(model_zero_mass,q2);
+  Eigen::VectorXd tau(Eigen::VectorXd::Random(model_zero_mass.nq));
+  double u = 0.3;
+
+
+
+  aba(model_composite,data_composite, q,q_dot, tau);
+  centerOfMass(model_composite, data_composite,q,q_dot,q_ddot,true,false);
+  forwardKinematics(model_composite,data_composite, q, q_dot, q_ddot);
+  computeAllTerms(model_zero_mass,data_zero_mass,q,q_dot);
+
+  forwardKinematics(model_zero_mass, data_zero_mass, q, q_dot, q_ddot);
+  computeAllTerms(model_composite,data_composite,q,q_dot);
+
+
+  Model::Index index_joint_R3xSO3 = (Model::Index) model_zero_mass.njoints-1;
+  Model::Index index_joint_composite = (Model::Index) model_composite.njoints-1;
+
+
+  BOOST_CHECK_MESSAGE(data_composite.oMi[index_joint_composite]
+                          .isApprox(data_zero_mass.oMi[index_joint_R3xSO3]) , "composite<R3xSO3> vs R3-SO3 - oMi last joint not equal");
+
+
+  BOOST_CHECK_MESSAGE(data_composite.v[index_joint_composite]
+                          == data_zero_mass.v[index_joint_R3xSO3] , "composite<R3xSO3> vs R3-SO3 - v last joint not equal");
+
+  // BOOST_CHECK_MESSAGE(data_composite.a[index_joint_composite] //@TODO Uncommente to test once JointComposite maths are ok
+  //                         == data_zero_mass.a[index_joint_R3xSO3] , "composite planar joint vs PxPyRz - a last joint not equal");
+
+  // BOOST_CHECK_MESSAGE(data_composite.f[index_joint_composite] //@TODO Uncommente to test once JointComposite maths are ok
+  //                         == data_zero_mass.f[index_joint_R3xSO3] , "composite planar joint vs PxPyRz - f last joint not equal");
+
+  BOOST_CHECK_MESSAGE(data_composite.com[index_joint_composite]
+                          .isApprox(data_zero_mass.com[index_joint_R3xSO3]) , "composite<R3xSO3> vs R3-SO3 - com last joint not equal");
+
+  BOOST_CHECK_MESSAGE(data_composite.vcom[index_joint_composite]
+                          .isApprox(data_zero_mass.vcom[index_joint_R3xSO3]) , "composite<R3xSO3> vs R3-SO3 - vcom last joint not equal");
+
+  BOOST_CHECK_MESSAGE(data_composite.mass[index_joint_composite]
+                          == data_zero_mass.mass[index_joint_R3xSO3] , "composite<R3xSO3> vs R3-SO3 - mass last joint not equal"); 
+
+  BOOST_CHECK_MESSAGE(data_composite.kinetic_energy
+                          == data_zero_mass.kinetic_energy , "composite<R3xSO3> vs R3-SO3 - kinetic energy not equal");
+
+  BOOST_CHECK_MESSAGE(data_composite.potential_energy
+                          == data_zero_mass.potential_energy , "composite<R3xSO3> vs R3-SO3 - potential energy not equal");                          
+
+  // BOOST_CHECK_MESSAGE(data_composite.nle //@TODO Uncommente to test once JointComposite maths are ok
+  //                         .isApprox(data_zero_mass.nle) , "composite planar joint vs PxPyRz - nle not equal");
+
+  // BOOST_CHECK_MESSAGE(data_composite.M //@TODO Uncommente to test once JointComposite maths are ok
+  //                         .isApprox(data_zero_mass.M) , "composite planar joint vs PxPyRz - Mass Matrix not equal");
+
+  
+  BOOST_CHECK_MESSAGE(integrate(model_composite, q,q_dot).isApprox(integrate(model_zero_mass ,q,q_dot)) ,std::string(" composite<R3xSO3> vs R3-SO3 - integrate model error "));
+  BOOST_CHECK_MESSAGE(interpolate(model_composite, q1,q2,u).isApprox(interpolate(model_zero_mass ,q1,q2,u)) ,std::string(" composite<R3xSO3> vs R3-SO3 - interpolate model error "));
+  BOOST_CHECK_MESSAGE(differentiate(model_composite, q1,q2).isApprox(differentiate(model_zero_mass ,q1,q2)) ,std::string(" composite<R3xSO3> vs R3-SO3 - differentiate model error "));
+  BOOST_CHECK_MESSAGE(fabs(distance(model_composite, q1,q2).norm() - distance(model_zero_mass ,q1,q2).norm()) <= 1e-6 ,std::string(" composite<R3xSO3> vs R3-SO3 - distance model error "));
+
+}
+
+BOOST_AUTO_TEST_SUITE_END ()
+
diff --git a/unittest/joint-configurations.cpp b/unittest/joint-configurations.cpp
index d6ba8a1632488bd801c51b38d91f5f8761fda78b..c46942b603220332564a8c07fc29cfd854ea6257 100644
--- a/unittest/joint-configurations.cpp
+++ b/unittest/joint-configurations.cpp
@@ -47,14 +47,15 @@ void addJointAndBody(Model & model, const JointModelBase<D> & jmodel, const Mode
   typedef typename D::TangentVector_t TV;
   typedef typename D::ConfigVector_t CV;
   
-  idx = model.addJoint(parent_id,jmodel,joint_placement,name + "_joint",
+  idx = model.addJoint(parent_id,jmodel,joint_placement,
                        TV::Zero(),
                        1e3 * (TV::Random() + TV::Constant(1)),
                        1e3 * (CV::Random() - CV::Constant(1)),
-                       1e3 * (CV::Random() + CV::Constant(1))
+                       1e3 * (CV::Random() + CV::Constant(1)),
+                       name + "_joint"
                        );
   
-  model.appendBodyToJoint(idx,Y,SE3::Identity(),name + "_body");
+  model.appendBodyToJoint(idx,Y,SE3::Identity());
 }
 
 void buildModel(Model & model)
@@ -101,7 +102,7 @@ struct TestIntegrationJoint
     SE3 M1 = jdata.M;
     
     SE3 M1_exp = M0*exp6(v0);
-    BOOST_CHECK(M1.isApprox(M1_exp));
+    BOOST_CHECK_MESSAGE(M1.isApprox(M1_exp), std::string("Error when integrating1 " + jmodel.shortname()));
     
     qdot *= -1;
 
@@ -114,7 +115,7 @@ struct TestIntegrationJoint
     M1 = jdata.M;
     
     M1_exp = M0*exp6(v0);
-    BOOST_CHECK(M1.isApprox(M1_exp));
+    BOOST_CHECK_MESSAGE(M1.isApprox(M1_exp), std::string("Error when integrating2 " + jmodel.shortname()));
   }
   
 };
@@ -125,6 +126,35 @@ void TestIntegrationJoint::operator()< JointModelDense<-1,-1> >(JointModelBase<
 template<>
 void TestIntegrationJoint::operator()< JointModelSphericalZYX >(JointModelBase< JointModelSphericalZYX > & /*jmodel*/) {}
 
+template<>
+void TestIntegrationJoint::operator()< JointModelComposite >(JointModelBase< JointModelComposite > & /*jmodel*/)
+{
+  se3::JointModelComposite jmodel((se3::JointModelRX()), (se3::JointModelRY()));
+  jmodel.setIndexes(1,0,0);
+  jmodel.updateComponentsIndexes();
+
+  se3::JointModelComposite::JointDataDerived jdata = jmodel.createData();
+
+  typedef typename JointModel::ConfigVector_t CV;
+  typedef typename JointModel::TangentVector_t TV;
+  typedef typename JointModel::Transformation_t SE3;
+  
+  CV q0 = jmodel.random();
+  TV qdot(Eigen::VectorXd::Random(jmodel.nv()));
+  
+  jmodel.calc(jdata,q0,qdot);
+  SE3 M0 = jdata.M;
+  Motion v0 = jdata.v;
+  
+  CV q1 = jmodel.integrate(q0,qdot);
+  jmodel.calc(jdata,q1);
+  SE3 M1 = jdata.M;
+  
+  SE3 M1_exp = M0*exp6(v0);
+  // The computations in JointModelComposite::calc() may be wrong, this results cannot be tested yet.
+  // BOOST_CHECK_MESSAGE(M1.isApprox(M1_exp), std::string("Error when integrating " + jmodel.shortname()));
+}
+
 template<>
 void TestIntegrationJoint::init<JointModelRevoluteUnaligned>(JointModelBase<JointModelRevoluteUnaligned> & jmodel)
 {
@@ -186,48 +216,9 @@ struct TestDifferentiationJoint
 
     TV qdot = jmodel.difference(q0,q1);
 
-    BOOST_CHECK_MESSAGE( jmodel.integrate(q0, qdot).isApprox(q1), std::string("Error in difference for joint " + jmodel.shortname()));
+    BOOST_CHECK_MESSAGE( jmodel.isSameConfiguration(jmodel.integrate(q0, qdot), q1), std::string("Error in difference for joint " + jmodel.shortname()));
 
-    BOOST_CHECK_MESSAGE( jmodel.integrate(q1, -qdot).isApprox(q0), std::string("Error in difference for joint " + jmodel.shortname()));
-
-  }
-
-  void operator()(JointModelBase<JointModelFreeFlyer> & jmodel)
-  {
-    init(jmodel);
-    typedef JointModelFreeFlyer::ConfigVector_t CV;
-    typedef JointModelFreeFlyer::TangentVector_t TV;
-    typedef JointModelFreeFlyer::Transformation_t SE3;
-    
-    jmodel.setIndexes(0,0,0);
-    
-    CV q0 = jmodel.random();
-    CV q1 = jmodel.random();
-    
-    TV qdot = jmodel.difference(q0,q1);
-    
-    BOOST_CHECK_MESSAGE( jmodel.integrate(q0, qdot).head<3>().isApprox(q1.head<3>()), std::string("Error in difference for joint " + jmodel.shortname()));
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.integrate(q0, qdot).tail<4>()), Eigen::Quaterniond(q1.tail<4>()))
-                      , std::string("Error in difference for joint " + jmodel.shortname()));
-
-  }
-
-  void operator()(JointModelBase<JointModelSpherical> & jmodel)
-  {
-    init(jmodel);
-    typedef JointModelSpherical::ConfigVector_t CV;
-    typedef JointModelSpherical::TangentVector_t TV;
-    typedef JointModelSpherical::Transformation_t SE3;
-    
-    jmodel.setIndexes(0,0,0);
-    
-    CV q0 = jmodel.random();
-    CV q1 = jmodel.random();
-    
-    TV qdot = jmodel.difference(q0,q1);
-    
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.integrate(q0, qdot)), Eigen::Quaterniond(q1))
-                      , std::string("Error in difference for joint " + jmodel.shortname()));
+    BOOST_CHECK_MESSAGE( jmodel.isSameConfiguration(jmodel.integrate(q1, -qdot), q0), std::string("Error in difference for joint " + jmodel.shortname()));
 
   }
   
@@ -291,85 +282,21 @@ struct TestInterpolationJoint
 
     double u = 0;
     
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(q0, q1,u).isApprox(q0)
+    BOOST_CHECK_MESSAGE(jmodel.isSameConfiguration(jmodel.interpolate(q0, q1,u),q0)
                       , std::string("Error in interpolation with u = 0 for joint " + jmodel.shortname()));
 
     u = 0.3; 
     
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(jmodel.interpolate(q0, q1,u), q1, 1).isApprox(q1)
+    BOOST_CHECK_MESSAGE(jmodel.isSameConfiguration(jmodel.interpolate(jmodel.interpolate(q0, q1,u), q1, 1),q1)
                       , std::string("Error in double interpolation for joint " + jmodel.shortname()));
 
     u = 1;
     
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(q0, q1,u).isApprox(q1)
+    BOOST_CHECK_MESSAGE(jmodel.isSameConfiguration(jmodel.interpolate(q0, q1,u),q1)
                       , std::string("Error in interpolation with u = 1 for joint " + jmodel.shortname()));
 
   }
 
-  void operator()(JointModelBase<JointModelFreeFlyer> & jmodel)
-  {
-    init(jmodel);
-    typedef JointModelFreeFlyer::ConfigVector_t CV;
-    typedef JointModelFreeFlyer::TangentVector_t TV;
-    typedef JointModelFreeFlyer::Transformation_t SE3;
-    
-    jmodel.setIndexes(0,0,0);
-    
-    CV q0 = jmodel.random();
-    CV q1 = jmodel.random();
-
-    double u = 0;
-
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(q0, q1,u).head<3>().isApprox(q0.head<3>())
-                      , std::string("Error in interpolation with u = 0 for joint " + jmodel.shortname()));
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(q0, q1,u).tail<4>()), Eigen::Quaterniond(q0.tail<4>()) )
-                      , std::string("Error in interpolation with u = 0 for joint " + jmodel.shortname()));
-
-    u = 0.3; 
-    
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(jmodel.interpolate(q0, q1,u), q1, 1).head<3>().isApprox(q1.head<3>())
-                      , std::string("Error in double interpolation for joint " + jmodel.shortname()));
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(jmodel.interpolate(q0, q1,u), q1, 1).tail<4>()), Eigen::Quaterniond(q1.tail<4>()) )
-                      , std::string("Error in double interpolation for joint " + jmodel.shortname()));
-
-    u = 1;
-    
-    BOOST_CHECK_MESSAGE( jmodel.interpolate(q0, q1,u).head<3>().isApprox(q1.head<3>())
-                      , std::string("Error in interpolation with u = 1 for joint  " + jmodel.shortname()));
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(q0, q1,u).tail<4>()), Eigen::Quaterniond(q1.tail<4>()) )
-                      , std::string("Error in interpolation with u = 1 for joint  " + jmodel.shortname()));
-
-  }
-
-  
-
-  void operator()(JointModelBase<JointModelSpherical> & jmodel)
-  {
-    init(jmodel);
-    typedef JointModelSpherical::ConfigVector_t CV;
-    typedef JointModelSpherical::TangentVector_t TV;
-    typedef JointModelSpherical::Transformation_t SE3;
-    
-    jmodel.setIndexes(0,0,0);
-    
-    CV q0 = jmodel.random();
-    CV q1 = jmodel.random();
-
-    double u = 0;
-    
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(q0, q1,u)), Eigen::Quaterniond(q0))
-                      , std::string("Error in interpolation with u = 0 for joint " + jmodel.shortname()));
-
-    u = 0.3; 
-
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(jmodel.interpolate(q0, q1,u), q1, 1)), Eigen::Quaterniond(q1) )
-                      , std::string("Error in double interpolation for joint " + jmodel.shortname()));
-
-    u = 1;
-    
-    BOOST_CHECK_MESSAGE( defineSameRotation(Eigen::Quaterniond(jmodel.interpolate(q0, q1,u)), Eigen::Quaterniond(q1))
-                      , std::string("Error in interpolation with u = 1 for joint " + jmodel.shortname()));
-  }
   
 };
 
diff --git a/unittest/joint.cpp b/unittest/joint.cpp
index a191c8d7f91a49fbae4a87420f2a4892bc7ae40e..162c9fd39ca98be8af2a41c797345ad608adef85 100644
--- a/unittest/joint.cpp
+++ b/unittest/joint.cpp
@@ -15,6 +15,7 @@
 // Pinocchio If not, see
 // <http://www.gnu.org/licenses/>.
 
+#include "pinocchio/multibody/joint/joint-composite.hpp"
 #include "pinocchio/multibody/joint/joint.hpp"
 
 #define BOOST_TEST_DYN_LINK
@@ -25,6 +26,7 @@
 template <typename T>
 void test_joint_methods (T & jmodel, typename T::JointDataDerived & jdata)
 {
+    std::cout << "Testing Joint over " << jmodel.shortname() << std::endl;
     Eigen::VectorXd q1(Eigen::VectorXd::Random (jmodel.nq()));
     Eigen::VectorXd q1_dot(Eigen::VectorXd::Random (jmodel.nv()));
     Eigen::VectorXd q2(Eigen::VectorXd::Random (jmodel.nq()));
@@ -32,8 +34,9 @@ void test_joint_methods (T & jmodel, typename T::JointDataDerived & jdata)
     se3::Inertia::Matrix6 Ia(se3::Inertia::Random().matrix());
     bool update_I = false;
 
-  q1 = jmodel.random();
-  q2 = jmodel.random();
+    q1 = jmodel.random();
+    q2 = jmodel.random();
+
     jmodel.calc(jdata, q1, q1_dot);
     jmodel.calc_aba(jdata, Ia, update_I);
 
@@ -42,7 +45,6 @@ void test_joint_methods (T & jmodel, typename T::JointDataDerived & jdata)
     se3::JointModel jma(jmodel);
     se3::JointData jda(jdata);
 
-                                                            
     jma.calc(jda, q1, q1_dot);
     jma.calc_aba(jda, Ia, update_I); 
 
@@ -93,6 +95,21 @@ struct TestJoint{
     // JointModelDense will be removed soon
   }
 
+  void operator()(const se3::JointModelComposite & ) const
+  {
+    // se3::JointModelComposite jmodel(2);
+    // jmodel.addJointModel(se3::JointModelRX());
+    // jmodel.addJointModel(se3::JointModelRY());
+
+    se3::JointModelComposite jmodel((se3::JointModelRX()), (se3::JointModelRY()));
+    jmodel.setIndexes(0,0,0);
+    jmodel.updateComponentsIndexes();
+
+    se3::JointModelComposite::JointDataDerived jdata = jmodel.createData();
+
+    test_joint_methods(jmodel, jdata);
+  }
+
   void operator()(const se3::JointModelRevoluteUnaligned & ) const
   {
     se3::JointModelRevoluteUnaligned jmodel(1.5, 1., 0.);
diff --git a/unittest/model.cpp b/unittest/model.cpp
index 341a6aeb2e997b69852924c87d2ea2259a18a7c4..eac27fef59898e187fe406627a3f70cf6fb7c219 100644
--- a/unittest/model.cpp
+++ b/unittest/model.cpp
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(test_model_subtree)
   buildModels::humanoidSimple(model);
   
   Model::JointIndex idx_larm1 = model.getJointId("larm1_joint");
-  BOOST_CHECK(idx_larm1<model.njoint);
+  BOOST_CHECK(idx_larm1<model.njoints);
   Model::IndexVector subtree = model.subtrees[idx_larm1];
   BOOST_CHECK(subtree.size()==6);
   
diff --git a/unittest/urdf.cpp b/unittest/urdf.cpp
index 5f260b62db6885f03fe4fb38e84f1df8238cd563..a63dc41952d78dcf5f40dc9d68a45c352dea2d05 100644
--- a/unittest/urdf.cpp
+++ b/unittest/urdf.cpp
@@ -34,7 +34,8 @@ BOOST_AUTO_TEST_CASE ( buildModel )
   #ifndef NDEBUG
      std::cout << "Parse filename \"" << filename << "\"" << std::endl;
   #endif
-    se3::Model model = se3::urdf::buildModel(filename);
+    se3::Model model;
+    se3::urdf::buildModel(filename, model);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/unittest/visitor.cpp b/unittest/visitor.cpp
index bd4dfea3739ce54662cbf8cb48273a5d7d474b5d..30afec1d16005941541203aced37380934185444 100644
--- a/unittest/visitor.cpp
+++ b/unittest/visitor.cpp
@@ -17,7 +17,7 @@
 
 #include <iostream>
 
-#include <pinocchio/multibody/joint/joint.hpp>
+#include <pinocchio/multibody/joint/joint-composite.hpp>
 #include <pinocchio/multibody/model.hpp>
 #include "pinocchio/multibody/visitor.hpp"
 
@@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE ( test_runal )
   model.addJoint(0,se3::JointModelRevoluteUnaligned(0,0,1),se3::SE3::Random());
   Data data(model);
 
-  for( Model::JointIndex i=1;i<(Model::JointIndex)model.njoint;++i )
+  for( Model::JointIndex i=1;i<(Model::JointIndex)model.njoints;++i )
     {
       SimpleVisitor::run(model.joints[i],data.joints[i],
                          SimpleVisitor::ArgsType(model,data,i));