diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3798ed0d515edcf81fdef8c037986fed2aa7ec7..6421351d8c39bc360c77a26ce3f3e92e77331483 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,6 +119,7 @@ SET(${PROJECT_NAME}_MULTIBODY_HEADERS
   multibody/force-set.hpp
   multibody/joint.hpp
   multibody/model.hpp
+  multibody/model.hxx
   multibody/visitor.hpp
   )
 
@@ -173,6 +174,7 @@ IF(URDFDOM_FOUND)
   SET(${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS
     ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
     multibody/parser/urdf.hpp
+    multibody/parser/urdf.hxx
     )
   LIST(APPEND HEADERS
     ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS}
diff --git a/src/multibody/model.hpp b/src/multibody/model.hpp
index a2ace9e4d5120319736c251836c62a91c7affc1c..de7d12a8aecf20589d0bb66f97ee7eb80cc0684d 100644
--- a/src/multibody/model.hpp
+++ b/src/multibody/model.hpp
@@ -162,251 +162,11 @@ namespace se3
 
   };
 
-  
-
 } // namespace se3
 
-
-
 /* --- Details -------------------------------------------------------------- */
 /* --- Details -------------------------------------------------------------- */
 /* --- Details -------------------------------------------------------------- */
-namespace se3
-{
-  inline std::ostream& operator<< ( std::ostream & os, const Model& model )
-  {
-    os << "Nb bodies = " << model.nbody << " (nq="<< model.nq<<",nv="<<model.nv<<")" << std::endl;
-    for(Model::Index i=0;i<(Model::Index)(model.nbody);++i)
-      {
-	os << "  Joint "<<model.names[i] << ": parent=" << model.parents[i] 
-	   << ( model.hasVisual[i] ? " (has visual) " : "(doesnt have visual)" ) << std::endl;
-      }
-
-    return os;
-  }
-
-  inline std::string random(const int len)
-  {
-    std::string res;
-    static const char alphanum[] =
-        "0123456789"
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-        "abcdefghijklmnopqrstuvwxyz";
-
-    for (int i=0; i<len;++i)
-      res += alphanum[((size_t)std::rand() % (sizeof(alphanum) - 1))];
-    return res;
-}
-
-  template<typename D>
-  Model::Index Model::addBody( Index parent,const JointModelBase<D> & j,const SE3 & placement,
-             const Inertia & Y,const std::string & jointName, 
-             const std::string & bodyName, bool visual)
-  {
-    assert( (nbody==(int)joints.size())&&(nbody==(int)inertias.size())
-      &&(nbody==(int)parents.size())&&(nbody==(int)jointPlacements.size()) );
-    assert( (j.nq()>=0)&&(j.nv()>=0) );
-
-    Model::Index idx = (Model::Index) (nbody ++);
-
-    joints         .push_back(j.derived()); 
-    boost::get<D>(joints.back()).setIndexes((int)idx,nq,nv);
-
-    inertias       .push_back(Y);
-    parents        .push_back(parent);
-    jointPlacements.push_back(placement);
-    names          .push_back( (jointName!="")?jointName:random(8) );
-    hasVisual      .push_back(visual);
-    bodyNames      .push_back( (bodyName!="")?bodyName:random(8));
-    nq += j.nq();
-    nv += j.nv();
-    return idx;
-  }
-
-  template<typename D>
-  Model::Index Model::addBody( Index parent,const JointModelBase<D> & j,const SE3 & placement,
-			      const Inertia & Y,
-            const Eigen::VectorXd & effort, const Eigen::VectorXd & velocity,
-            const Eigen::VectorXd & lowPos, const Eigen::VectorXd & upPos,
-            const std::string & jointName, 
-			      const std::string & bodyName, bool visual)
-  {
-    assert( (nbody==(int)joints.size())&&(nbody==(int)inertias.size())
-	    &&(nbody==(int)parents.size())&&(nbody==(int)jointPlacements.size()) );
-    assert( (j.nq()>=0)&&(j.nv()>=0) );
-
-    Model::Index idx = (Model::Index) (nbody ++);
-
-    joints         .push_back(j.derived()); 
-    boost::get<D>(joints.back()).setIndexes((int)idx,nq,nv);
-
-    boost::get<D>(joints.back()).setMaxEffortLimit(effort);
-    boost::get<D>(joints.back()).setMaxVelocityLimit(velocity);
-
-    boost::get<D>(joints.back()).setLowerPositionLimit(lowPos);
-    boost::get<D>(joints.back()).setUpperPositionLimit(upPos);
-
-    inertias       .push_back(Y);
-    parents        .push_back(parent);
-    jointPlacements.push_back(placement);
-    names          .push_back( (jointName!="")?jointName:random(8) );
-    hasVisual      .push_back(visual);
-    bodyNames      .push_back( (bodyName!="")?bodyName:random(8));
-    nq += j.nq();
-    nv += j.nv();
-    return idx;
-  }
-
-  inline Model::Index Model::addFixedBody( Index lastMovingParent,
-                                           const SE3 & placementFromLastMoving,
-                                           const std::string & bodyName,
-                                           bool visual )
-  {
-
-    Model::Index idx = (Model::Index) (nFixBody++);
-    fix_lastMovingParent.push_back(lastMovingParent);
-    fix_lmpMi      .push_back(placementFromLastMoving);
-    fix_hasVisual  .push_back(visual);
-    fix_bodyNames  .push_back( (bodyName!="")?bodyName:random(8));
-    return idx;
-  }
-
-  inline void Model::mergeFixedBody(Index parent, const SE3 & placement, const Inertia & Y)
-  {
-    const Inertia & iYf = Y.se3Action(placement); //TODO
-    inertias[parent] += iYf;
-  }
-
-  inline Model::Index Model::getBodyId( const std::string & name ) const
-  {
-    std::vector<std::string>::iterator::difference_type
-      res = std::find(bodyNames.begin(),bodyNames.end(),name) - bodyNames.begin();
-    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
-    assert( (res>=0)&&(res<nbody)&&"The body name you asked do not exist" );
-    return Model::Index(res);
-  }
-  inline bool Model::existBodyName( const std::string & name ) const
-  {
-    return (bodyNames.end() != std::find(bodyNames.begin(),bodyNames.end(),name));
-  }
-
-  inline const std::string& Model::getBodyName( Model::Index index ) const
-  {
-    assert( index < (Model::Index)nbody );
-    return bodyNames[index];
-  }
-
-  inline Model::Index Model::getJointId( const std::string & name ) const
-  {
-    std::vector<std::string>::iterator::difference_type
-      res = std::find(names.begin(),names.end(),name) - names.begin();
-    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
-    assert( (res>=0)&&(res<joints.size())&&"The joint name you asked do not exist" );
-    return Model::Index(res);
-  }
-  inline bool Model::existJointName( const std::string & name ) const
-  {
-    return (names.end() != std::find(names.begin(),names.end(),name));
-  }
-
-  inline const std::string& Model::getJointName( Model::Index index ) const
-  {
-    assert( index < (Model::Index)joints.size() );
-    return names[index];
-  }
-
-  inline Data::Data( const Model& ref )
-    :model(ref)
-    ,joints(0)
-    ,a((std::size_t)ref.nbody)
-    ,v((std::size_t)ref.nbody)
-    ,f((std::size_t)ref.nbody)
-    ,oMi((std::size_t)ref.nbody)
-    ,liMi((std::size_t)ref.nbody)
-    ,tau(ref.nv)
-    ,nle(ref.nv)
-    ,Ycrb((std::size_t)ref.nbody)
-    ,M(ref.nv,ref.nv)
-    ,Fcrb((std::size_t)ref.nbody)
-    ,lastChild((std::size_t)ref.nbody)
-    ,nvSubtree((std::size_t)ref.nbody)
-    ,U(ref.nv,ref.nv)
-    ,D(ref.nv)
-    ,tmp(ref.nv)
-    ,parents_fromRow((std::size_t)ref.nv)
-    ,nvSubtree_fromRow((std::size_t)ref.nv)
-    ,J(6,ref.nv)
-    ,iMf((std::size_t)ref.nbody)
-    ,com((std::size_t)ref.nbody)
-    ,vcom((std::size_t)ref.nbody)
-    ,acom((std::size_t)ref.nbody)
-    ,mass((std::size_t)ref.nbody)
-    ,Jcom(3,ref.nv)
-    ,effortLimit(ref.nq)
-    ,velocityLimit(ref.nv)
-    ,lowerPositionLimit(ref.nq)
-    ,upperPositionLimit(ref.nq)
-  {
-    /* Create data strcture associated to the joints */
-    for(Model::Index i=0;i<(Model::Index)(model.nbody);++i) 
-      joints.push_back(CreateJointData::run(model.joints[i]));
-
-    /* Init for CRBA */
-    for(Model::Index i=0;i<(Model::Index)(ref.nbody);++i ) { Fcrb[i].resize(6,model.nv); }
-    computeLastChild(ref);
-
-    /* Init for Cholesky */
-    U = Eigen::MatrixXd::Identity(ref.nv,ref.nv);
-    computeParents_fromRow(ref);
-
-    /* Init Jacobian */
-    J.fill(0);
-    
-    /* Init universe states relatively to itself */
-    
-    a[0].setZero();
-    v[0].setZero();
-    f[0].setZero();
-    oMi[0].setIdentity();
-    liMi[0].setIdentity();
-  }
-
-  inline void Data::computeLastChild(const Model& model)
-  {
-    typedef Model::Index Index;
-    std::fill(lastChild.begin(),lastChild.end(),-1);
-    for( int i=model.nbody-1;i>=0;--i )
-      {
-	if(lastChild[(Model::Index)i] == -1) lastChild[(Model::Index)i] = i;
-	const Index & parent = model.parents[(Model::Index)i];
-	lastChild[parent] = std::max(lastChild[(Model::Index)i],lastChild[parent]);
-
-	nvSubtree[(Model::Index)i] 
-	  = idx_v(model.joints[(Model::Index)lastChild[(Model::Index)i]]) + nv(model.joints[(Model::Index)lastChild[(Model::Index)i]])
-	  - idx_v(model.joints[(Model::Index)i]);
-      }
-  }
-
-  inline void Data::computeParents_fromRow( const Model& model )
-  {
-    for( Model::Index joint=1;joint<(Model::Index)(model.nbody);joint++)
-      {
-	const Model::Index & parent = model.parents[joint];
-	const int nvj    = nv   (model.joints[joint]);
-	const int idx_vj = idx_v(model.joints[joint]);
-
-	if(parent>0) parents_fromRow[(Model::Index)idx_vj] = idx_v(model.joints[parent])+nv(model.joints[parent])-1;
-	else         parents_fromRow[(Model::Index)idx_vj] = -1;
-	nvSubtree_fromRow[(Model::Index)idx_vj] = nvSubtree[joint];
-
-    for( int row=1;row<nvj;++row)
-	  {
-	    parents_fromRow[(Model::Index)(idx_vj+row)] = idx_vj+row-1;
-	    nvSubtree_fromRow[(Model::Index)(idx_vj+row)] = nvSubtree[joint]-row;
-	  }
-      }
-  }
-
-} // namespace se3
+#include "pinocchio/multibody/model.hxx"
 
 #endif // ifndef __se3_model_hpp__
diff --git a/src/multibody/model.hxx b/src/multibody/model.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..8c91f6787359bc49f275c2257b1c27d720c11f48
--- /dev/null
+++ b/src/multibody/model.hxx
@@ -0,0 +1,271 @@
+//
+// Copyright (c) 2015 CNRS
+// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_model_hxx__
+#define __se3_model_hxx__
+
+#include "pinocchio/spatial/fwd.hpp"
+#include "pinocchio/spatial/se3.hpp"
+#include "pinocchio/spatial/force.hpp"
+#include "pinocchio/spatial/motion.hpp"
+#include "pinocchio/spatial/inertia.hpp"
+#include "pinocchio/multibody/joint/joint-variant.hpp"
+#include <iostream>
+
+namespace se3
+{
+  inline std::ostream& operator<< (std::ostream & os, const Model & model)
+  {
+    os << "Nb bodies = " << model.nbody << " (nq="<< model.nq<<",nv="<<model.nv<<")" << std::endl;
+    for(Model::Index i=0;i<(Model::Index)(model.nbody);++i)
+      {
+	os << "  Joint "<<model.names[i] << ": parent=" << model.parents[i] 
+	   << ( model.hasVisual[i] ? " (has visual) " : "(doesnt have visual)" ) << std::endl;
+      }
+
+    return os;
+  }
+
+  inline std::string random (const int len)
+  {
+    std::string res;
+    static const char alphanum[] =
+        "0123456789"
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+        "abcdefghijklmnopqrstuvwxyz";
+
+    for (int i=0; i<len;++i)
+      res += alphanum[((size_t)std::rand() % (sizeof(alphanum) - 1))];
+    return res;
+  }
+
+  template<typename D>
+  Model::Index Model::addBody (Index parent, const JointModelBase<D> & j, const SE3 & placement,
+                               const Inertia & Y, const std::string & jointName,
+                               const std::string & bodyName, bool visual)
+  {
+    assert( (nbody==(int)joints.size())&&(nbody==(int)inertias.size())
+      &&(nbody==(int)parents.size())&&(nbody==(int)jointPlacements.size()) );
+    assert( (j.nq()>=0)&&(j.nv()>=0) );
+
+    Model::Index idx = (Model::Index) (nbody ++);
+
+    joints         .push_back(j.derived()); 
+    boost::get<D>(joints.back()).setIndexes((int)idx,nq,nv);
+
+    inertias       .push_back(Y);
+    parents        .push_back(parent);
+    jointPlacements.push_back(placement);
+    names          .push_back( (jointName!="")?jointName:random(8) );
+    hasVisual      .push_back(visual);
+    bodyNames      .push_back( (bodyName!="")?bodyName:random(8));
+    nq += j.nq();
+    nv += j.nv();
+    return idx;
+  }
+
+  template<typename D>
+  Model::Index Model::addBody (Index parent, const JointModelBase<D> & j, const SE3 & placement,
+                               const Inertia & Y,
+                               const Eigen::VectorXd & effort, const Eigen::VectorXd & velocity,
+                               const Eigen::VectorXd & lowPos, const Eigen::VectorXd & upPos,
+                               const std::string & jointName,
+                               const std::string & bodyName, bool visual)
+  {
+    assert( (nbody==(int)joints.size())&&(nbody==(int)inertias.size())
+	    &&(nbody==(int)parents.size())&&(nbody==(int)jointPlacements.size()) );
+    assert( (j.nq()>=0)&&(j.nv()>=0) );
+
+    Model::Index idx = (Model::Index) (nbody ++);
+
+    joints         .push_back(j.derived()); 
+    boost::get<D>(joints.back()).setIndexes((int)idx,nq,nv);
+
+    boost::get<D>(joints.back()).setMaxEffortLimit(effort);
+    boost::get<D>(joints.back()).setMaxVelocityLimit(velocity);
+
+    boost::get<D>(joints.back()).setLowerPositionLimit(lowPos);
+    boost::get<D>(joints.back()).setUpperPositionLimit(upPos);
+
+    inertias       .push_back(Y);
+    parents        .push_back(parent);
+    jointPlacements.push_back(placement);
+    names          .push_back( (jointName!="")?jointName:random(8) );
+    hasVisual      .push_back(visual);
+    bodyNames      .push_back( (bodyName!="")?bodyName:random(8));
+    nq += j.nq();
+    nv += j.nv();
+    return idx;
+  }
+
+  inline Model::Index Model::addFixedBody (Index lastMovingParent,
+                                           const SE3 & placementFromLastMoving,
+                                           const std::string & bodyName,
+                                           bool visual)
+  {
+
+    Model::Index idx = (Model::Index) (nFixBody++);
+    fix_lastMovingParent.push_back(lastMovingParent);
+    fix_lmpMi      .push_back(placementFromLastMoving);
+    fix_hasVisual  .push_back(visual);
+    fix_bodyNames  .push_back( (bodyName!="")?bodyName:random(8));
+    return idx;
+  }
+
+  inline void Model::mergeFixedBody (Index parent, const SE3 & placement, const Inertia & Y)
+  {
+    const Inertia & iYf = Y.se3Action(placement); //TODO
+    inertias[parent] += iYf;
+  }
+
+  inline Model::Index Model::getBodyId (const std::string & name) const
+  {
+    std::vector<std::string>::iterator::difference_type
+      res = std::find(bodyNames.begin(),bodyNames.end(),name) - bodyNames.begin();
+    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
+    assert( (res>=0)&&(res<nbody) && "The body name you asked does not exist" );
+    return Model::Index(res);
+  }
+  
+  inline bool Model::existBodyName (const std::string & name) const
+  {
+    return (bodyNames.end() != std::find(bodyNames.begin(),bodyNames.end(),name));
+  }
+
+  inline const std::string& Model::getBodyName (Model::Index index) const
+  {
+    assert( index < (Model::Index)nbody );
+    return bodyNames[index];
+  }
+
+  inline Model::Index Model::getJointId (const std::string & name) const
+  {
+    std::vector<std::string>::iterator::difference_type
+      res = std::find(names.begin(),names.end(),name) - names.begin();
+    assert( (res<INT_MAX) && "Id superior to int range. Should never happen.");
+    assert( (res>=0)&&(res<joints.size()) && "The joint name you asked does not exist" );
+    return Model::Index(res);
+  }
+  
+  inline bool Model::existJointName (const std::string & name) const
+  {
+    return (names.end() != std::find(names.begin(),names.end(),name));
+  }
+
+  inline const std::string& Model::getJointName (Model::Index index) const
+  {
+    assert( index < (Model::Index)joints.size() );
+    return names[index];
+  }
+
+  inline Data::Data (const Model & ref)
+    :model(ref)
+    ,joints(0)
+    ,a((std::size_t)ref.nbody)
+    ,v((std::size_t)ref.nbody)
+    ,f((std::size_t)ref.nbody)
+    ,oMi((std::size_t)ref.nbody)
+    ,liMi((std::size_t)ref.nbody)
+    ,tau(ref.nv)
+    ,nle(ref.nv)
+    ,Ycrb((std::size_t)ref.nbody)
+    ,M(ref.nv,ref.nv)
+    ,Fcrb((std::size_t)ref.nbody)
+    ,lastChild((std::size_t)ref.nbody)
+    ,nvSubtree((std::size_t)ref.nbody)
+    ,U(ref.nv,ref.nv)
+    ,D(ref.nv)
+    ,tmp(ref.nv)
+    ,parents_fromRow((std::size_t)ref.nv)
+    ,nvSubtree_fromRow((std::size_t)ref.nv)
+    ,J(6,ref.nv)
+    ,iMf((std::size_t)ref.nbody)
+    ,com((std::size_t)ref.nbody)
+    ,vcom((std::size_t)ref.nbody)
+    ,acom((std::size_t)ref.nbody)
+    ,mass((std::size_t)ref.nbody)
+    ,Jcom(3,ref.nv)
+    ,effortLimit(ref.nq)
+    ,velocityLimit(ref.nv)
+    ,lowerPositionLimit(ref.nq)
+    ,upperPositionLimit(ref.nq)
+  {
+    /* Create data strcture associated to the joints */
+    for(Model::Index i=0;i<(Model::Index)(model.nbody);++i) 
+      joints.push_back(CreateJointData::run(model.joints[i]));
+
+    /* Init for CRBA */
+    M.fill(0);
+    for(Model::Index i=0;i<(Model::Index)(ref.nbody);++i ) { Fcrb[i].resize(6,model.nv); }
+    computeLastChild(ref);
+
+    /* Init for Cholesky */
+    U = Eigen::MatrixXd::Identity(ref.nv,ref.nv);
+    computeParents_fromRow(ref);
+
+    /* Init Jacobian */
+    J.fill(0);
+    
+    /* Init universe states relatively to itself */
+    
+    a[0].setZero();
+    v[0].setZero();
+    f[0].setZero();
+    oMi[0].setIdentity();
+    liMi[0].setIdentity();
+  }
+
+  inline void Data::computeLastChild (const Model & model)
+  {
+    typedef Model::Index Index;
+    std::fill(lastChild.begin(),lastChild.end(),-1);
+    for( int i=model.nbody-1;i>=0;--i )
+    {
+      if(lastChild[(Index)i] == -1) lastChild[(Index)i] = i;
+      const Index & parent = model.parents[(Index)i];
+      lastChild[parent] = std::max(lastChild[(Index)i],lastChild[parent]);
+      
+      nvSubtree[(Index)i]
+      = idx_v(model.joints[(Index)lastChild[(Index)i]]) + nv(model.joints[(Index)lastChild[(Index)i]])
+      - idx_v(model.joints[(Index)i]);
+    }
+  }
+
+  inline void Data::computeParents_fromRow (const Model & model)
+  {
+    for( Model::Index joint=1;joint<(Model::Index)(model.nbody);joint++)
+    {
+      const Model::Index & parent = model.parents[joint];
+      const int nvj    = nv   (model.joints[joint]);
+      const int idx_vj = idx_v(model.joints[joint]);
+      
+      if(parent>0) parents_fromRow[(Model::Index)idx_vj] = idx_v(model.joints[parent])+nv(model.joints[parent])-1;
+      else         parents_fromRow[(Model::Index)idx_vj] = -1;
+      nvSubtree_fromRow[(Model::Index)idx_vj] = nvSubtree[joint];
+      
+      for(int row=1;row<nvj;++row)
+      {
+        parents_fromRow[(Model::Index)(idx_vj+row)] = idx_vj+row-1;
+        nvSubtree_fromRow[(Model::Index)(idx_vj+row)] = nvSubtree[joint]-row;
+      }
+    }
+  }
+
+} // namespace se3
+
+#endif // ifndef __se3_model_hxx__
diff --git a/src/multibody/parser/urdf.hpp b/src/multibody/parser/urdf.hpp
index 6f9915636aaee9ecf850080b85fa088256f3627e..652279dfd046c78990272fc695fe04266a90e5da 100644
--- a/src/multibody/parser/urdf.hpp
+++ b/src/multibody/parser/urdf.hpp
@@ -52,19 +52,7 @@ namespace se3
     ///
     /// \return The converted Spatial Inertia se3::Inertia.
     ///
-    inline Inertia convertFromUrdf( const ::urdf::Inertial& Y )
-    {
-      const ::urdf::Vector3 & p = Y.origin.position;
-      const ::urdf::Rotation & q = Y.origin.rotation;
-
-      const Eigen::Vector3d com(p.x,p.y,p.z);
-      const Eigen::Matrix3d & R = Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix();
-
-      Eigen::Matrix3d I; I << Y.ixx,Y.ixy,Y.ixz
-			   ,  Y.ixy,Y.iyy,Y.iyz
-			   ,  Y.ixz,Y.iyz,Y.izz;
-      return Inertia(Y.mass,com,R*I*R.transpose());
-    }
+    inline Inertia convertFromUrdf (const ::urdf::Inertial & Y);
 
     ///
     /// \brief Convert URDF Pose quantity to SE3.
@@ -73,12 +61,7 @@ namespace se3
     ///
     /// \return The converted pose/transform se3::SE3.
     ///
-    inline SE3 convertFromUrdf( const ::urdf::Pose & M )
-    {
-      const ::urdf::Vector3 & p = M.position;
-      const ::urdf::Rotation & q = M.rotation;
-      return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z));
-    }
+    inline SE3 convertFromUrdf (const ::urdf::Pose & M);
 
     ///
     /// \brief The four possible cartesian types of an 3D axis.
@@ -93,17 +76,7 @@ namespace se3
     ///
     /// \return The property of the particular axis se3::urdf::AxisCartesian.
     ///
-    inline AxisCartesian extractCartesianAxis( const ::urdf::Vector3 & axis )
-    {
-      if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) )
-	return AXIS_X;
-      else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) )
-	return AXIS_Y;
-      else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) )
-	return AXIS_Z;
-      else
-	return AXIS_UNALIGNED;
-    }
+    inline AxisCartesian extractCartesianAxis (const ::urdf::Vector3 & axis);
 
     ///
     /// \brief Recursive procedure for reading the URDF tree.
@@ -113,347 +86,27 @@ namespace se3
     /// \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.
     ///
-    inline void parseTree(::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset = SE3::Identity(), bool verbose = false) 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);
-    
-    const std::string & joint_name = joint->name;
-    const std::string & link_name = link->name;
-    const std::string & parent_link_name = link->getParent()->name;
-    std::string 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::Index parent_joint_id = (link->getParent()->parent_joint==NULL) ? (model.existJointName("root_joint") ? model.getJointId("root_joint") : 0) :
-                                                                    model.getJointId( link->getParent()->parent_joint->name );
-
-    // 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 bool has_visual = (link->visual) ? true : false;
+    inline void parseTree (::urdf::LinkConstPtr link, 
+                           Model & model,
+                           const SE3 & placementOffset = SE3::Identity(),
+                           bool verbose = false) throw (std::invalid_argument);
 
-    switch(joint->type)
-    {
-      case ::urdf::Joint::FLOATING:
-      {
-        joint_info = "joint FreeFlyer";
-      
-        typedef JointModelFreeFlyer::ConfigVector_t ConfigVector_t;
-        typedef JointModelFreeFlyer::TangentVector_t TangentVector_t;
-        typedef ConfigVector_t::Scalar Scalar_t;
-      
-      
-        ConfigVector_t lower_position;
-        lower_position.fill(std::numeric_limits<Scalar_t>::min());
-      
-        ConfigVector_t upper_position;
-        upper_position.fill(std::numeric_limits<Scalar_t>::max());
-      
-        TangentVector_t max_effort;
-        max_effort.fill(std::numeric_limits<Scalar_t>::max());
-      
-        TangentVector_t max_velocity;
-        max_velocity.fill(std::numeric_limits<Scalar_t>::max());
-      
-        model.addBody(parent_joint_id, JointModelFreeFlyer(), jointPlacement, Y,
-                      max_effort, max_velocity, lower_position, upper_position,
-                      joint->name, link->name, has_visual);
-        break;
-      }
-      case ::urdf::Joint::REVOLUTE:
-      {
-        joint_info = "joint REVOLUTE with axis";
-      
-        typedef JointModelRX::ConfigVector_t ConfigVector_t;
-        typedef JointModelRX::TangentVector_t TangentVector_t;
-      
-        TangentVector_t max_effort;
-        TangentVector_t max_velocity;
-        ConfigVector_t lower_position;
-        ConfigVector_t upper_position;
-        
-        if (joint->limits)
-        {
-          max_effort << joint->limits->effort;
-          max_velocity << joint->limits->velocity;
-          lower_position << joint->limits->lower;
-          upper_position << joint->limits->upper;
-        }
-        
-        Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero());
-        AxisCartesian axis = extractCartesianAxis(joint->axis);
-          
-        switch(axis)
-        {
-          case AXIS_X:
-            joint_info += " along X";
-            model.addBody(  parent_joint_id, JointModelRX(), jointPlacement, Y,
-                          max_effort, max_velocity, lower_position, upper_position,
-                          joint->name,link->name, has_visual );
-            break;
-          case AXIS_Y:
-            joint_info += " along Y";
-            model.addBody(  parent_joint_id, JointModelRY(), jointPlacement, Y,
-                          max_effort, max_velocity, lower_position, upper_position,
-                          joint->name,link->name, has_visual );
-            break;
-          case AXIS_Z:
-            joint_info += " along Z";
-            model.addBody(  parent_joint_id, JointModelRZ(), jointPlacement, Y,
-                          max_effort, max_velocity, lower_position, upper_position,
-                          joint->name,link->name, has_visual );
-            break;
-          case AXIS_UNALIGNED:
-          {
-            
-            std::stringstream axis_value;
-            axis_value << std::setprecision(5);
-            axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
-            joint_info += " unaligned " + axis_value.str();
-        
-            jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z );
-            jointAxis.normalize();
-            model.addBody(  parent_joint_id, JointModelRevoluteUnaligned(jointAxis),
-                          jointPlacement, Y,
-                          max_effort, max_velocity, lower_position, upper_position,
-                          joint->name,link->name, has_visual );
-            break;
-          }
-          default:
-            assert( false && "Fatal Error while extracting revolute joint axis");
-            break;
-        }
-        break;
-      }
-      case ::urdf::Joint::CONTINUOUS: // Revolute with no joint limits
-      {
-        joint_info = "joint CONTINUOUS with axis";
-      
-        typedef JointModelRX::ConfigVector_t ConfigVector_t;
-        typedef JointModelRX::TangentVector_t TangentVector_t;
-        
-        TangentVector_t max_effort;
-        TangentVector_t max_velocity;
-        ConfigVector_t lower_position;
-        ConfigVector_t upper_position;
-
-        if (joint->limits)
-        {
-          max_effort << joint->limits->effort;
-          max_velocity << joint->limits->velocity;
-          lower_position << joint->limits->lower;
-          upper_position << joint->limits->upper;
-        }
-
-        Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero());
-        AxisCartesian axis = extractCartesianAxis(joint->axis);
-        
-        switch(axis)
-        {
-          case AXIS_X:
-            joint_info += " along X";
-            model.addBody(  parent_joint_id, JointModelRX(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_Y:
-            joint_info += " along Y";
-            model.addBody(  parent_joint_id, JointModelRY(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_Z:
-            joint_info += " along Z";
-            model.addBody(  parent_joint_id, JointModelRZ(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_UNALIGNED:
-          {
-            std::stringstream axis_value;
-            axis_value << std::setprecision(5);
-            axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
-            joint_info += " unaligned " + axis_value.str();
-            
-            jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z );
-            jointAxis.normalize();
-            model.addBody(  parent_joint_id, JointModelRevoluteUnaligned(jointAxis),
-                            jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          }
-          default:
-            assert( false && "Fatal Error while extracting revolute joint axis");
-            break;
-        }
-        break;
-      }
-      case ::urdf::Joint::PRISMATIC:
-      {
-        joint_info = "joint PRISMATIC with axis";
-      
-        typedef JointModelRX::ConfigVector_t ConfigVector_t;
-        typedef JointModelRX::TangentVector_t TangentVector_t;
-        
-        TangentVector_t max_effort;
-        TangentVector_t max_velocity;
-        ConfigVector_t lower_position;
-        ConfigVector_t upper_position;
-
-        if (joint->limits)
-          {
-          max_effort << joint->limits->effort;
-          max_velocity << joint->limits->velocity;
-          lower_position << joint->limits->lower;
-          upper_position << joint->limits->upper;
-        }
-      
-        AxisCartesian axis = extractCartesianAxis(joint->axis);   
-        switch(axis)
-        {
-          case AXIS_X:
-            joint_info += " along X";
-            model.addBody(  parent_joint_id, JointModelPX(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_Y:
-            joint_info += " along Y";
-            model.addBody(  parent_joint_id, JointModelPY(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_Z:
-            joint_info += " along Z";
-            model.addBody(  parent_joint_id, JointModelPZ(), jointPlacement, Y,
-                            max_effort, max_velocity, lower_position, upper_position,
-                            joint->name,link->name, has_visual );
-            break;
-          case AXIS_UNALIGNED:
-          {
-            std::stringstream axis_value;
-            axis_value << std::setprecision(5);
-            axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
-            joint_info += " unaligned " + axis_value.str();
-            std::cerr << "Bad axis = " << axis_value << std::endl;
-            assert(false && "Only X, Y or Z axis are accepted." );
-            break;
-          }
-          default:
-            assert( false && "Fatal Error while extracting prismatic joint axis");
-            break;
-        }
-        break;
-      }
-      case ::urdf::Joint::FIXED:
-      {
-        // In case of fixed joint, if link has inertial tag:
-        //    -add the inertia of the link to his parent in the model
-        // Otherwise do nothing.
-        // In all cases:
-        //    -let all the children become children of parent
-        //    -inform the parser of the offset to apply
-        //    -add fixed body in model to display it in gepetto-viewer
-        
-        joint_info = "fixed joint";
-        if (link->inertial)
-        {
-          model.mergeFixedBody(parent_joint_id, jointPlacement, Y); //Modify the parent inertia in the model
-        }
-
-        //transformation of the current placement offset
-        nextPlacementOffset = jointPlacement;
-
-        //add the fixed Body in the model for the viewer
-        model.addFixedBody(parent_joint_id, nextPlacementOffset, link->name, has_visual);
-        
-        //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() );
-        }
-        break;
-      }
-      default:
-      {
-        std::cerr << "The joint type " << joint->type << " is not supported." << std::endl;
-        assert(false && "Only revolute, prismatic and fixed joints are accepted." );
-        break;
-      }
-          }
-
-          if (verbose)
-          {
-            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;
-          }
-          
-  }
-          else if (link->getParent() != NULL)
-          {
-            const std::string exception_message (link->name + " - joint information missing.");
-            throw std::invalid_argument(exception_message);
-          }
 
-
-  BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
-  {
-    parseTree(child, model, nextPlacementOffset, verbose);
-  }
-}
-
-          ///
-          /// \brief Parse a tree with a specific root joint linking the model to the environment.
-          ///        The function returns an exception as soon as a necessary Inertia or Joint information are missing.
-          ///
-          /// \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.
-          /// \param[in] root_joint The specific root joint.
-          ///
+    ///
+    /// \brief Parse a tree with a specific root joint linking the model to the environment.
+    ///        The function returns an exception as soon as a necessary Inertia or Joint information are missing.
+    ///
+    /// \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.
+    /// \param[in] root_joint The specific root joint.
+    ///
     template <typename D>
-    void parseTree( ::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, const JointModelBase<D> & root_joint, const bool verbose = false) throw (std::invalid_argument)
-    {
-      if (!link->inertial)
-      {
-        const std::string exception_message (link->name + " - spatial inertia information missing.");
-        throw std::invalid_argument(exception_message);
-      }
-      
-      const Inertia & Y = convertFromUrdf(*link->inertial);
-      const bool has_visual = (link->visual) ? true : false;
-      model.addBody(0, root_joint, placementOffset, Y , "root_joint", link->name, has_visual);
-      
-      BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
-      {
-        parseTree(child, model, SE3::Identity(), verbose);
-      }
-    }
+    void parseTree (::urdf::LinkConstPtr link,
+                    Model & model,
+                    const SE3 & placementOffset,
+                    const JointModelBase<D> & root_joint,
+                    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.
@@ -464,21 +117,9 @@ namespace se3
     /// \return The se3::Model of the URDF file.
     ///
     template <typename D>
-    Model buildModel(const std::string & filename, const JointModelBase<D> & root_joint, bool verbose = false) throw (std::invalid_argument)
-    {
-      Model model;
-
-      ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
-      if (urdfTree)
-        parseTree(urdfTree->getRoot(), model, SE3::Identity(), root_joint, verbose);
-      else
-      {
-        const std::string exception_message ("The file " + filename + " does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
-      
-      return model;
-    }
+    Model buildModel (const std::string & filename,
+                      const JointModelBase<D> & root_joint,
+                      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.
@@ -487,23 +128,15 @@ namespace se3
     ///
     /// \return The se3::Model of the URDF file.
     ///
-    inline Model buildModel(const std::string & filename, const bool verbose = false) throw (std::invalid_argument)
-    {
-      Model model;
-
-      ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
-      if (urdfTree)
-        parseTree(urdfTree->getRoot(), model, SE3::Identity(), verbose);
-      else
-      {
-        const std::string exception_message ("The file " + filename + " does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
-
-      return model;
-    }
+    inline Model buildModel (const std::string & filename,
+                             const bool verbose = false) throw (std::invalid_argument);
 
   } // namespace urdf
 } // namespace se3
 
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+/* --- Details -------------------------------------------------------------- */
+#include "pinocchio/multibody/parser/urdf.hxx"
+
 #endif // ifndef __se3_urdf_hpp__
diff --git a/src/multibody/parser/urdf.hxx b/src/multibody/parser/urdf.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..6036287b9d57bce48c7affc640b9a3322951ce56
--- /dev/null
+++ b/src/multibody/parser/urdf.hxx
@@ -0,0 +1,444 @@
+//
+// Copyright (c) 2015 CNRS
+// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_urdf_hxx__
+#define __se3_urdf_hxx__
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <boost/foreach.hpp>
+#include "pinocchio/multibody/model.hpp"
+
+#include <exception>
+
+namespace se3
+{
+  namespace urdf
+  {
+
+    inline Inertia convertFromUrdf (const ::urdf::Inertial & Y)
+    {
+      const ::urdf::Vector3 & p = Y.origin.position;
+      const ::urdf::Rotation & q = Y.origin.rotation;
+      
+      const Eigen::Vector3d com(p.x,p.y,p.z);
+      const Eigen::Matrix3d & R = Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix();
+      
+      Eigen::Matrix3d I; I << Y.ixx,Y.ixy,Y.ixz
+      ,  Y.ixy,Y.iyy,Y.iyz
+      ,  Y.ixz,Y.iyz,Y.izz;
+      return Inertia(Y.mass,com,R*I*R.transpose());
+    }
+    
+    inline SE3 convertFromUrdf (const ::urdf::Pose & M)
+    {
+      const ::urdf::Vector3 & p = M.position;
+      const ::urdf::Rotation & q = M.rotation;
+      return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z));
+    }
+    
+    inline AxisCartesian extractCartesianAxis (const ::urdf::Vector3 & axis)
+    {
+      if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) )
+        return AXIS_X;
+      else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) )
+        return AXIS_Y;
+      else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) )
+        return AXIS_Z;
+      else
+        return AXIS_UNALIGNED;
+    }
+    
+    
+    inline void parseTree (::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, 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);
+
+        const std::string & joint_name = joint->name;
+        const std::string & link_name = link->name;
+        const std::string & parent_link_name = link->getParent()->name;
+        std::string 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::Index parent_joint_id = (link->getParent()->parent_joint==NULL) ? (model.existJointName("root_joint") ? model.getJointId("root_joint") : 0) :
+        model.getJointId( link->getParent()->parent_joint->name );
+
+        // 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 bool has_visual = (link->visual) ? true : false;
+
+        switch(joint->type)
+        {
+          case ::urdf::Joint::FLOATING:
+          {
+            joint_info = "joint FreeFlyer";
+
+            typedef JointModelFreeFlyer::ConfigVector_t ConfigVector_t;
+            typedef JointModelFreeFlyer::TangentVector_t TangentVector_t;
+            typedef ConfigVector_t::Scalar Scalar_t;
+
+
+            ConfigVector_t lower_position;
+            lower_position.fill(std::numeric_limits<Scalar_t>::min());
+
+            ConfigVector_t upper_position;
+            upper_position.fill(std::numeric_limits<Scalar_t>::max());
+
+            TangentVector_t max_effort;
+            max_effort.fill(std::numeric_limits<Scalar_t>::max());
+
+            TangentVector_t max_velocity;
+            max_velocity.fill(std::numeric_limits<Scalar_t>::max());
+
+            model.addBody(parent_joint_id, JointModelFreeFlyer(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name, link->name, has_visual);
+            break;
+          }
+          case ::urdf::Joint::REVOLUTE:
+          {
+            joint_info = "joint REVOLUTE with axis";
+
+            typedef JointModelRX::ConfigVector_t ConfigVector_t;
+            typedef JointModelRX::TangentVector_t TangentVector_t;
+
+            TangentVector_t max_effort;
+            TangentVector_t max_velocity;
+            ConfigVector_t lower_position;
+            ConfigVector_t upper_position;
+
+            if (joint->limits)
+            {
+              max_effort << joint->limits->effort;
+              max_velocity << joint->limits->velocity;
+              lower_position << joint->limits->lower;
+              upper_position << joint->limits->upper;
+            }
+
+            Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero());
+            AxisCartesian axis = extractCartesianAxis(joint->axis);
+
+            switch(axis)
+            {
+              case AXIS_X:
+              joint_info += " along X";
+              model.addBody(  parent_joint_id, JointModelRX(), jointPlacement, Y,
+                max_effort, max_velocity, lower_position, upper_position,
+                joint->name,link->name, has_visual );
+              break;
+              case AXIS_Y:
+              joint_info += " along Y";
+              model.addBody(  parent_joint_id, JointModelRY(), jointPlacement, Y,
+                max_effort, max_velocity, lower_position, upper_position,
+                joint->name,link->name, has_visual );
+              break;
+              case AXIS_Z:
+              joint_info += " along Z";
+              model.addBody(  parent_joint_id, JointModelRZ(), jointPlacement, Y,
+                max_effort, max_velocity, lower_position, upper_position,
+                joint->name,link->name, has_visual );
+              break;
+              case AXIS_UNALIGNED:
+              {
+                std::stringstream axis_value;
+                axis_value << std::setprecision(5);
+                axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
+                joint_info += " unaligned " + axis_value.str();
+
+                jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z );
+                jointAxis.normalize();
+                model.addBody(  parent_joint_id, JointModelRevoluteUnaligned(jointAxis),
+                  jointPlacement, Y,
+                  max_effort, max_velocity, lower_position, upper_position,
+                  joint->name,link->name, has_visual );
+                break;
+              }
+              default:
+              assert( false && "Fatal Error while extracting revolute joint axis");
+              break;
+            }
+            break;
+          }
+        case ::urdf::Joint::CONTINUOUS: // Revolute with no joint limits
+        {
+          joint_info = "joint CONTINUOUS with axis";
+          
+          typedef JointModelRX::ConfigVector_t ConfigVector_t;
+          typedef JointModelRX::TangentVector_t TangentVector_t;
+          
+          TangentVector_t max_effort;
+          TangentVector_t max_velocity;
+          ConfigVector_t lower_position;
+          ConfigVector_t upper_position;
+          
+          if (joint->limits)
+          {
+            max_effort << joint->limits->effort;
+            max_velocity << joint->limits->velocity;
+            lower_position << joint->limits->lower;
+            upper_position << joint->limits->upper;
+          }
+          
+          Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero());
+          AxisCartesian axis = extractCartesianAxis(joint->axis);
+          
+          switch(axis)
+          {
+            case AXIS_X:
+            joint_info += " along X";
+            model.addBody(  parent_joint_id, JointModelRX(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_Y:
+            joint_info += " along Y";
+            model.addBody(  parent_joint_id, JointModelRY(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_Z:
+            joint_info += " along Z";
+            model.addBody(  parent_joint_id, JointModelRZ(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_UNALIGNED:
+            {
+              std::stringstream axis_value;
+              axis_value << std::setprecision(5);
+              axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
+              joint_info += " unaligned " + axis_value.str();
+              
+              jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z );
+              jointAxis.normalize();
+              model.addBody(  parent_joint_id, JointModelRevoluteUnaligned(jointAxis),
+                jointPlacement, Y,
+                max_effort, max_velocity, lower_position, upper_position,
+                joint->name,link->name, has_visual );
+              break;
+            }
+            default:
+            assert( false && "Fatal Error while extracting revolute joint axis");
+            break;
+          }
+          break;
+        }
+        case ::urdf::Joint::PRISMATIC:
+        {
+          joint_info = "joint PRISMATIC with axis";
+          
+          typedef JointModelRX::ConfigVector_t ConfigVector_t;
+          typedef JointModelRX::TangentVector_t TangentVector_t;
+          
+          TangentVector_t max_effort;
+          TangentVector_t max_velocity;
+          ConfigVector_t lower_position;
+          ConfigVector_t upper_position;
+          
+          if (joint->limits)
+          {
+            max_effort << joint->limits->effort;
+            max_velocity << joint->limits->velocity;
+            lower_position << joint->limits->lower;
+            upper_position << joint->limits->upper;
+          }
+          
+          AxisCartesian axis = extractCartesianAxis(joint->axis);
+          switch(axis)
+          {
+            case AXIS_X:
+            joint_info += " along X";
+            model.addBody(  parent_joint_id, JointModelPX(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_Y:
+            joint_info += " along Y";
+            model.addBody(  parent_joint_id, JointModelPY(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_Z:
+            joint_info += " along Z";
+            model.addBody(  parent_joint_id, JointModelPZ(), jointPlacement, Y,
+              max_effort, max_velocity, lower_position, upper_position,
+              joint->name,link->name, has_visual );
+            break;
+            case AXIS_UNALIGNED:
+            {
+              std::stringstream axis_value;
+              axis_value << std::setprecision(5);
+              axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")";
+              joint_info += " unaligned " + axis_value.str();
+              std::cerr << "Bad axis = " << axis_value << std::endl;
+              assert(false && "Only X, Y or Z axis are accepted." );
+              break;
+            }
+            default:
+            assert( false && "Fatal Error while extracting prismatic joint axis");
+            break;
+          }
+          break;
+        }
+        case ::urdf::Joint::FIXED:
+        {
+          // In case of fixed joint, if link has inertial tag:
+          //    -add the inertia of the link to his parent in the model
+          // Otherwise do nothing.
+          // In all cases:
+          //    -let all the children become children of parent
+          //    -inform the parser of the offset to apply
+          //    -add fixed body in model to display it in gepetto-viewer
+
+          joint_info = "fixed joint";
+          if (link->inertial)
+          {
+            model.mergeFixedBody(parent_joint_id, jointPlacement, Y); //Modify the parent inertia in the model
+          }
+          
+          //transformation of the current placement offset
+          nextPlacementOffset = jointPlacement;
+          
+          //add the fixed Body in the model for the viewer
+          model.addFixedBody(parent_joint_id, nextPlacementOffset, link->name, has_visual);
+          
+          //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() );
+          }
+          break;
+        }
+        default:
+        {
+          std::cerr << "The joint type " << joint->type << " is not supported." << std::endl;
+          assert(false && "Only revolute, prismatic and fixed joints are accepted." );
+          break;
+        }
+      }
+      
+      if (verbose)
+      {
+        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;
+      }
+      
+    }
+    else if (link->getParent() != NULL)
+    {
+      const std::string exception_message (link->name + " - joint information missing.");
+      throw std::invalid_argument(exception_message);
+    }
+    
+    
+    BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
+    {
+      parseTree(child, model, nextPlacementOffset, verbose);
+    }
+  }
+  
+  
+            template <typename D>
+  void parseTree (::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, const JointModelBase<D> & root_joint, const bool verbose) throw (std::invalid_argument)
+  {
+    if (!link->inertial)
+    {
+      const std::string exception_message (link->name + " - spatial inertia information missing.");
+      throw std::invalid_argument(exception_message);
+    }
+    
+    const Inertia & Y = convertFromUrdf(*link->inertial);
+    const bool has_visual = (link->visual) ? true : false;
+    model.addBody(0, root_joint, placementOffset, Y , "root_joint", link->name, has_visual);
+    
+    BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links)
+    {
+      parseTree(child, model, SE3::Identity(), verbose);
+    }
+  }
+  
+  
+  template <typename D>
+  Model buildModel (const std::string & filename, const JointModelBase<D> & root_joint, bool verbose) throw (std::invalid_argument)
+  {
+    Model model;
+    
+    ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
+    if (urdfTree)
+      parseTree(urdfTree->getRoot(), model, SE3::Identity(), root_joint, verbose);
+    else
+    {
+      const std::string exception_message ("The file " + filename + " does not contain a valid URDF model.");
+      throw std::invalid_argument(exception_message);
+    }
+    
+    return model;
+  }
+  
+  
+  inline Model buildModel (const std::string & filename, const bool verbose) throw (std::invalid_argument)
+  {
+    Model model;
+    
+    ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename);
+    if (urdfTree)
+      parseTree(urdfTree->getRoot(), model, SE3::Identity(), verbose);
+    else
+    {
+      const std::string exception_message ("The file " + filename + " does not contain a valid URDF model.");
+      throw std::invalid_argument(exception_message);
+    }
+    
+    return model;
+  }
+
+  } // namespace urdf
+  
+} // namespace se3
+
+#endif // ifndef __se3_urdf_hxx__