From 1002170ce57651f2731d1c436ce9058321e1542e Mon Sep 17 00:00:00 2001
From: Joseph Mirabel <jmirabel@laas.fr>
Date: Fri, 6 Mar 2020 10:07:40 +0100
Subject: [PATCH] [URDF] Move parser into the library.

---
 src/CMakeLists.txt            |   3 +-
 src/parsers/urdf.hpp          |  11 +-
 src/parsers/urdf/geometry.cpp | 490 +++++++++++++++++
 src/parsers/urdf/geometry.hxx | 456 +---------------
 src/parsers/urdf/model.cpp    | 300 +++++++++++
 src/parsers/urdf/model.hxx    | 959 ++++++++++++----------------------
 src/parsers/urdf/utils.hpp    |  72 +--
 7 files changed, 1168 insertions(+), 1123 deletions(-)
 create mode 100644 src/parsers/urdf/geometry.cpp
 create mode 100644 src/parsers/urdf/model.cpp

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8caacd2a1..af42c2b00 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,7 +8,8 @@
 # ----------------------------------------------------
 
 SET(${PROJECT_NAME}_SOURCES
-  ${${PROJECT_NAME}_PARSERS_SOURCES}
+  parsers/urdf/model.cpp
+  parsers/urdf/geometry.cpp
 )
 
 # Extract the compile definitions of the project for export
diff --git a/src/parsers/urdf.hpp b/src/parsers/urdf.hpp
index 44a5f55e5..996007ea3 100644
--- a/src/parsers/urdf.hpp
+++ b/src/parsers/urdf.hpp
@@ -8,9 +8,14 @@
 
 #include "pinocchio/multibody/model.hpp"
 #include "pinocchio/multibody/geometry.hpp"
-#include "pinocchio/parsers/urdf/types.hpp"
 
 /// \cond
+// forward declaration of the unique type from urdfdom which is expose (mostly
+// for backward compatibility).
+namespace urdf {
+  class ModelInterface;
+}
+
 namespace hpp
 {
   namespace fcl
@@ -72,7 +77,7 @@ namespace pinocchio
     ///       or ::urdf::parseURDFFile
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
-    buildModel(const ::urdf::ModelInterfaceSharedPtr & urdfTree,
+    buildModel(const ::urdf::ModelInterface* urdfTree,
                const typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointModel & rootJoint,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose = false);
@@ -89,7 +94,7 @@ namespace pinocchio
     ///       or ::urdf::parseURDFFile
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
-    buildModel(const ::urdf::ModelInterfaceSharedPtr & urdfTree,
+    buildModel(const ::urdf::ModelInterface* urdfTree,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose = false);
     
diff --git a/src/parsers/urdf/geometry.cpp b/src/parsers/urdf/geometry.cpp
new file mode 100644
index 000000000..07bd42577
--- /dev/null
+++ b/src/parsers/urdf/geometry.cpp
@@ -0,0 +1,490 @@
+#include "pinocchio/parsers/urdf.hpp"
+#include "pinocchio/parsers/urdf/types.hpp"
+#include "pinocchio/parsers/utils.hpp"
+
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/property_tree/ptree.hpp>
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+namespace pinocchio
+{
+  namespace urdf
+  {
+    namespace details
+    {
+      struct UrdfTree
+      {
+        typedef boost::property_tree::ptree ptree;
+        typedef std::map<std::string, const ptree&> LinkMap_t;
+        
+        void parse (const std::string & xmlStr)
+        {
+          urdf_ = ::urdf::parseURDF(xmlStr);
+          if (!urdf_) {
+            throw std::invalid_argument ("Enable to parse URDF");
+          }
+          
+          std::istringstream iss(xmlStr);
+          using namespace boost::property_tree;
+          read_xml(iss, tree_, xml_parser::no_comments);
+          
+          BOOST_FOREACH(const ptree::value_type & link, tree_.get_child("robot")) {
+            if (link.first == "link") {
+              std::string name = link.second.get<std::string>("<xmlattr>.name");
+              links_.insert(std::pair<std::string,const ptree&>(name, link.second));
+            }
+          } // BOOST_FOREACH
+        }
+        
+        bool isCapsule (const std::string & linkName,
+                        const std::string & geomName) const
+        {
+          LinkMap_t::const_iterator _link = links_.find(linkName);
+          assert (_link != links_.end());
+          const ptree& link = _link->second;
+          if (link.count ("collision_checking") == 0)
+            return false;
+          BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
+            if (cc.first == "capsule") {
+#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
+              std::cerr << "Warning: support for tag link/collision_checking/capsule"
+                " is not available for URDFDOM < 0.3.0" << std::endl;
+#else
+              std::string name = cc.second.get<std::string>("<xmlattr>.name");
+              if (geomName == name) return true;
+#endif
+            }
+          } // BOOST_FOREACH
+          
+          return false;
+        }
+
+        bool isMeshConvex (const std::string & linkName,
+                           const std::string & geomName) const
+        {
+          LinkMap_t::const_iterator _link = links_.find(linkName);
+          assert (_link != links_.end());
+          const ptree& link = _link->second;
+          if (link.count ("collision_checking") == 0)
+            return false;
+          BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
+            if (cc.first == "convex") {
+#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
+              std::cerr << "Warning: support for tag link/collision_checking/convex"
+                " is not available for URDFDOM < 0.3.0" << std::endl;
+#else
+              std::string name = cc.second.get<std::string>("<xmlattr>.name");
+              if (geomName == name) return true;
+#endif
+            }
+          } // BOOST_FOREACH
+          
+          return false;
+        }
+        
+        // For standard URDF tags
+        ::urdf::ModelInterfaceSharedPtr urdf_;
+        // For other tags
+        ptree tree_;
+        // A mapping from link name to corresponding child of tree_
+        LinkMap_t links_;
+      };
+
+      ///
+      /// \brief Convert URDF Pose quantity to SE3.
+      ///
+      /// \param[in] M The input URDF Pose.
+      ///
+      /// \return The converted pose/transform pinocchio::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));
+      }
+
+      template<typename Vector3>
+      static void retrieveMeshScale(const ::urdf::MeshSharedPtr & mesh,
+                                    const Eigen::MatrixBase<Vector3> & scale)
+      {
+        Vector3 & scale_ = PINOCCHIO_EIGEN_CONST_CAST(Vector3,scale);
+        scale_ <<
+        mesh->scale.x,
+        mesh->scale.y,
+        mesh->scale.z;
+      }
+
+#ifdef PINOCCHIO_WITH_HPP_FCL
+# if ( HPP_FCL_MAJOR_VERSION>1 || ( HPP_FCL_MAJOR_VERSION==1 && \
+      ( HPP_FCL_MINOR_VERSION>1 || ( HPP_FCL_MINOR_VERSION==1 && \
+                                     HPP_FCL_PATCH_VERSION>3))))
+#  define PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
+# endif
+
+      /**
+       * @brief      Get a fcl::CollisionObject from an urdf geometry, searching
+       *             for it in specified package directories
+       *
+       * @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] meshPath      The Absolute path of the mesh currently read
+       * @param[out] meshScale     Scale of transformation currently applied to the mesh
+       *
+       * @return     A shared pointer on the geometry converted as a fcl::CollisionGeometry
+       */
+      boost::shared_ptr<fcl::CollisionGeometry>
+      inline retrieveCollisionGeometry(const UrdfTree& tree,
+                                       fcl::MeshLoaderPtr& meshLoader,
+                                       const std::string& linkName,
+                                       const std::string& geomName,
+                                       const ::urdf::GeometrySharedPtr urdf_geometry,
+                                       const std::vector<std::string> & package_dirs,
+                                       std::string & meshPath,
+                                       Eigen::Vector3d & meshScale)
+      {
+        boost::shared_ptr<fcl::CollisionGeometry> geometry;
+
+        // Handle the case where collision geometry is a mesh
+        if (urdf_geometry->type == ::urdf::Geometry::MESH)
+        {
+          const ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry);
+          std::string collisionFilename = urdf_mesh->filename;
+          
+          meshPath = retrieveResourcePath(collisionFilename, package_dirs);
+          if (meshPath == "") {
+            std::stringstream ss;
+            ss << "Mesh " << collisionFilename << " could not be found.";
+            throw std::invalid_argument (ss.str());
+          }
+          
+          fcl::Vec3f scale = fcl::Vec3f(urdf_mesh->scale.x,
+                                        urdf_mesh->scale.y,
+                                        urdf_mesh->scale.z
+                                        );
+          
+          retrieveMeshScale(urdf_mesh, meshScale);
+          
+          // Create FCL mesh by parsing Collada file.
+#ifdef PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
+          hpp::fcl::BVHModelPtr_t bvh = meshLoader->load (meshPath, scale);
+          bool convex = tree.isMeshConvex (linkName, geomName);
+          if (convex) {
+            bvh->buildConvexRepresentation (false);
+            geometry = bvh->convex;
+          } else
+            geometry = bvh;
+#else
+          geometry = meshLoader->load (meshPath, scale);
+#endif
+        }
+
+        // Handle the case where collision geometry is a cylinder
+        // Use FCL capsules for cylinders
+        else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER)
+        {
+          const bool is_capsule = tree.isCapsule(linkName, geomName);
+          meshScale << 1,1,1;
+          const ::urdf::CylinderSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry);
+          
+          double radius = collisionGeometry->radius;
+          double length = collisionGeometry->length;
+          
+          // Create fcl capsule geometry.
+          if (is_capsule) {
+            meshPath = "CAPSULE";
+            geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length));
+          } else {
+            meshPath = "CYLINDER";
+            geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Cylinder (radius, length));
+          }
+        }
+        // Handle the case where collision geometry is a box.
+        else if (urdf_geometry->type == ::urdf::Geometry::BOX) 
+        {
+          meshPath = "BOX";
+          meshScale << 1,1,1;
+          const ::urdf::BoxSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Box> (urdf_geometry);
+          
+          double x = collisionGeometry->dim.x;
+          double y = collisionGeometry->dim.y;
+          double z = collisionGeometry->dim.z;
+          
+          geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Box (x, y, z));
+        }
+        // Handle the case where collision geometry is a sphere.
+        else if (urdf_geometry->type == ::urdf::Geometry::SPHERE)
+        {
+          meshPath = "SPHERE";
+          meshScale << 1,1,1;
+          const ::urdf::SphereSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry);
+          
+          double radius = collisionGeometry->radius;
+          
+          geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Sphere (radius));
+        }
+        else throw std::invalid_argument("Unknown geometry type :");
+        
+        if (!geometry)
+        {
+          throw std::invalid_argument("The polyhedron retrived is empty");
+        }
+
+        return geometry;
+      }
+#endif // PINOCCHIO_WITH_HPP_FCL
+
+     /**
+      * @brief Get the first geometry attached to a link
+      *
+      * @param[in] link   The URDF link
+      *
+      * @return Either the first collision or visual
+      */
+      template<typename T>
+      inline PINOCCHIO_URDF_SHARED_PTR(const T)
+      getLinkGeometry(const ::urdf::LinkConstSharedPtr link);
+      
+      template<>
+      inline ::urdf::CollisionConstSharedPtr
+      getLinkGeometry< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
+      {
+        return link->collision;
+      }
+      
+      template<>
+      inline ::urdf::VisualConstSharedPtr
+      getLinkGeometry< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
+      {
+        return link->visual;
+      }
+
+
+     /**
+      * @brief Get the material values from the link visual object
+      *
+      * @param[in]  Visual/Collision The Visual or the Collision object.
+      * @param[out] meshTexturePath  The absolute file path containing the texture description.
+      * @param[out] meshColor        The mesh RGBA vector.
+      * @param[in]  package_dirs     A vector containing the different directories where to search for packages
+      *
+      */
+      template<typename urdfObject>
+      inline bool getVisualMaterial(const PINOCCHIO_URDF_SHARED_PTR(urdfObject) urdf_object,std::string & meshTexturePath,
+                                    Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs);
+      
+      template<>
+      inline bool getVisualMaterial< ::urdf::Collision>
+      (const ::urdf::CollisionSharedPtr, std::string& meshTexturePath,
+       Eigen::Vector4d & meshColor, const std::vector<std::string> &)
+      {
+        meshColor << 0.9, 0.9, 0.9, 1.;
+        meshTexturePath = "";
+        return false;
+      }
+      
+      template<>
+      inline bool getVisualMaterial< ::urdf::Visual>
+      (const ::urdf::VisualSharedPtr urdf_visual, std::string& meshTexturePath,
+       Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs)
+      {
+        meshColor.setZero();
+        meshTexturePath = "";
+        bool overrideMaterial = false;
+        if(urdf_visual->material) {
+          overrideMaterial = true;
+          meshColor << urdf_visual->material->color.r, urdf_visual->material->color.g,
+          urdf_visual->material->color.b, urdf_visual->material->color.a;
+          if(urdf_visual->material->texture_filename!="")
+            meshTexturePath = retrieveResourcePath((urdf_visual)->material->texture_filename, package_dirs);
+        }
+        return overrideMaterial;
+      }
+      
+     /**
+      * @brief Get the array of geometries attached to a link
+      *
+      * @param[in] link   The URDF link
+      *
+      * @return the array of either collisions or visuals
+      */
+      template<typename T>
+      inline const std::vector< PINOCCHIO_URDF_SHARED_PTR(T) > &
+      getLinkGeometryArray(const ::urdf::LinkConstSharedPtr link);
+      
+      template<>
+      inline const std::vector< ::urdf::CollisionSharedPtr> &
+      getLinkGeometryArray< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
+      {
+        return link->collision_array;
+      }
+      
+      template<>
+      inline const std::vector< ::urdf::VisualSharedPtr> &
+      getLinkGeometryArray< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
+      {
+        return link->visual_array;
+      }
+
+      /**
+       * @brief      Add the geometries attached to an URDF link to a GeometryModel, looking
+       *             either for collisions or visuals
+       *
+       * @param[in]  tree           The URDF kinematic tree
+       * @param[in]  meshLoader     The FCL mesh loader to avoid duplications of already loaded geometries
+       * @param[in]  link            The current URDF link
+       * @param      model           The model to which is the GeometryModel associated
+       * @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
+       *
+       */
+      template<typename GeometryType>
+      inline void addLinkGeometryToGeomModel(const UrdfTree & tree,
+                                             ::hpp::fcl::MeshLoaderPtr & meshLoader,
+                                             ::urdf::LinkConstSharedPtr link,
+                                             UrdfGeomVisitorBase& visitor,
+                                             GeometryModel & geomModel,
+                                             const std::vector<std::string> & package_dirs)
+      {
+#ifndef PINOCCHIO_WITH_HPP_FCL
+        PINOCCHIO_UNUSED_VARIABLE(tree);
+        PINOCCHIO_UNUSED_VARIABLE(meshLoader);
+#endif // PINOCCHIO_WITH_HPP_FCL
+        
+        typedef std::vector< PINOCCHIO_URDF_SHARED_PTR(GeometryType) > VectorSharedT;
+        typedef GeometryModel::SE3 SE3;
+
+        if(getLinkGeometry<GeometryType>(link))
+        {
+          std::string meshPath = "";
+
+          Eigen::Vector3d meshScale(Eigen::Vector3d::Ones());
+
+          const std::string & link_name = link->name;
+
+          VectorSharedT geometries_array = getLinkGeometryArray<GeometryType>(link);
+
+          FrameIndex frame_id;
+          UrdfGeomVisitorBase::Frame frame = visitor.getBodyFrame (link_name, frame_id);
+          SE3 body_placement = frame.placement;
+
+          std::size_t objectId = 0;
+          for (typename VectorSharedT::const_iterator i = geometries_array.begin();i != geometries_array.end(); ++i)
+          {
+            meshPath.clear();
+#ifdef PINOCCHIO_WITH_HPP_FCL
+            
+#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
+            const std::string & geom_name = (*i)->group_name;
+#else
+            const std::string & geom_name = (*i)->name;
+#endif // PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
+            const GeometryObject::CollisionGeometryPtr geometry =
+            retrieveCollisionGeometry(tree, meshLoader, link_name, geom_name,
+                                      (*i)->geometry, package_dirs, meshPath, meshScale);
+#else
+            ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> ((*i)->geometry);
+            if (urdf_mesh)
+            {
+              meshPath = retrieveResourcePath(urdf_mesh->filename, package_dirs);
+              retrieveMeshScale(urdf_mesh, meshScale);
+            }
+
+            const boost::shared_ptr<fcl::CollisionGeometry> geometry(new fcl::CollisionGeometry());
+#endif // PINOCCHIO_WITH_HPP_FCL
+
+            Eigen::Vector4d meshColor;
+            std::string meshTexturePath;
+            bool overrideMaterial = getVisualMaterial<GeometryType>((*i), meshTexturePath, meshColor, package_dirs);
+
+            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());
+            GeometryObject geometry_object(geometry_object_name,
+                                           frame_id, frame.parent,
+                                           geometry,
+                                           geomPlacement, meshPath, meshScale,
+                                           overrideMaterial, meshColor, meshTexturePath);
+            geomModel.addGeometryObject(geometry_object);
+            ++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]  tree           The URDF kinematic tree
+       * @param[in]  meshLoader     The FCL mesh loader to avoid duplications of already loaded geometries
+       * @param[in]  link           The current URDF link
+       * @param      model          The model to which is the GeometryModel associated
+       * @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 recursiveParseTreeForGeom(const UrdfTree& tree,
+                            ::hpp::fcl::MeshLoaderPtr& meshLoader,
+                            ::urdf::LinkConstSharedPtr link,
+                            UrdfGeomVisitorBase& visitor,
+                            GeometryModel & geomModel,
+                            const std::vector<std::string> & package_dirs,
+                            const GeometryType type)
+      {
+        
+        switch(type)
+        {
+          case COLLISION:
+            addLinkGeometryToGeomModel<::urdf::Collision >(tree, meshLoader, link, visitor, geomModel, package_dirs);
+            break;
+          case VISUAL:
+            addLinkGeometryToGeomModel<::urdf::Visual >(tree, meshLoader, link, visitor, geomModel, package_dirs);
+            break;
+          default:
+            break;
+        }
+        
+        BOOST_FOREACH(::urdf::LinkConstSharedPtr child,link->child_links)
+        {
+          recursiveParseTreeForGeom(tree, meshLoader, child, visitor, geomModel, package_dirs,type);
+        }
+        
+      }
+
+      void parseTreeForGeom(UrdfGeomVisitorBase& visitor,
+                            const std::istream& xmlStream,
+                            const GeometryType type,
+                            GeometryModel & geomModel,
+                            const std::vector<std::string> & package_dirs,
+                            ::hpp::fcl::MeshLoaderPtr meshLoader)
+      {
+        std::string xmlStr;
+        {
+          std::ostringstream os;
+          os << xmlStream.rdbuf();
+          xmlStr = os.str();
+        }
+        
+        details::UrdfTree tree;
+        tree.parse (xmlStr);
+        
+        std::vector<std::string> hint_directories(package_dirs);
+        
+        // Append the ROS_PACKAGE_PATH
+        std::vector<std::string> ros_pkg_paths = rosPaths();
+        hint_directories.insert(hint_directories.end(), ros_pkg_paths.begin(), ros_pkg_paths.end());
+
+#ifdef PINOCCHIO_WITH_HPP_FCL
+        if (!meshLoader) meshLoader = fcl::MeshLoaderPtr(new fcl::MeshLoader);
+#endif // ifdef PINOCCHIO_WITH_HPP_FCL
+        
+        recursiveParseTreeForGeom(tree, meshLoader, tree.urdf_->getRoot(),
+            visitor, geomModel, hint_directories,type);
+      }
+    } // namespace details
+  } // namespace urdf
+} // namespace pinocchio
diff --git a/src/parsers/urdf/geometry.hxx b/src/parsers/urdf/geometry.hxx
index 57814f14d..5c09261df 100644
--- a/src/parsers/urdf/geometry.hxx
+++ b/src/parsers/urdf/geometry.hxx
@@ -6,19 +6,10 @@
 #define __pinocchio_multibody_parsers_urdf_geometry_hxx__
 
 #include "pinocchio/parsers/urdf.hpp"
-#include "pinocchio/parsers/urdf/utils.hpp"
-#include "pinocchio/parsers/utils.hpp"
-
-#include <boost/property_tree/xml_parser.hpp>
-#include <boost/property_tree/ptree.hpp>
-
-#include <urdf_model/model.h>
-#include <urdf_parser/urdf_parser.h>
 
 #include <iostream>
 #include <sstream>
 #include <iomanip>
-#include <boost/foreach.hpp>
 #include <boost/shared_ptr.hpp>
 
 #ifdef PINOCCHIO_WITH_HPP_FCL
@@ -32,395 +23,32 @@ namespace pinocchio
   {
     namespace details
     {
-      struct UrdfTree
+      struct UrdfGeomVisitorBase
       {
-        typedef boost::property_tree::ptree ptree;
-        typedef std::map<std::string, const ptree&> LinkMap_t;
-        
-        void parse (const std::string & xmlStr)
-        {
-          urdf_ = ::urdf::parseURDF(xmlStr);
-          if (!urdf_) {
-            throw std::invalid_argument ("Enable to parse URDF");
-          }
-          
-          std::istringstream iss(xmlStr);
-          using namespace boost::property_tree;
-          read_xml(iss, tree_, xml_parser::no_comments);
-          
-          BOOST_FOREACH(const ptree::value_type & link, tree_.get_child("robot")) {
-            if (link.first == "link") {
-              std::string name = link.second.get<std::string>("<xmlattr>.name");
-              links_.insert(std::pair<std::string,const ptree&>(name, link.second));
-            }
-          } // BOOST_FOREACH
-        }
-        
-        bool isCapsule (const std::string & linkName,
-                        const std::string & geomName) const
-        {
-          LinkMap_t::const_iterator _link = links_.find(linkName);
-          assert (_link != links_.end());
-          const ptree& link = _link->second;
-          if (link.count ("collision_checking") == 0)
-            return false;
-          BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
-            if (cc.first == "capsule") {
-#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
-              std::cerr << "Warning: support for tag link/collision_checking/capsule"
-                " is not available for URDFDOM < 0.3.0" << std::endl;
-#else
-              std::string name = cc.second.get<std::string>("<xmlattr>.name");
-              if (geomName == name) return true;
-#endif
-            }
-          } // BOOST_FOREACH
-          
-          return false;
-        }
+        typedef FrameTpl<urdf_value_type, 0> Frame;
 
-        bool isMeshConvex (const std::string & linkName,
-                           const std::string & geomName) const
-        {
-          LinkMap_t::const_iterator _link = links_.find(linkName);
-          assert (_link != links_.end());
-          const ptree& link = _link->second;
-          if (link.count ("collision_checking") == 0)
-            return false;
-          BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
-            if (cc.first == "convex") {
-#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
-              std::cerr << "Warning: support for tag link/collision_checking/convex"
-                " is not available for URDFDOM < 0.3.0" << std::endl;
-#else
-              std::string name = cc.second.get<std::string>("<xmlattr>.name");
-              if (geomName == name) return true;
-#endif
-            }
-          } // BOOST_FOREACH
-          
-          return false;
-        }
-        
-        // For standard URDF tags
-        ::urdf::ModelInterfaceSharedPtr urdf_;
-        // For other tags
-        ptree tree_;
-        // A mapping from link name to corresponding child of tree_
-        LinkMap_t links_;
+        virtual Frame getBodyFrame (const std::string& name, FrameIndex& fid) const = 0;
       };
-      
-      template<typename Vector3>
-      static void retrieveMeshScale(const ::urdf::MeshSharedPtr & mesh,
-                                    const Eigen::MatrixBase<Vector3> & scale)
-      {
-        Vector3 & scale_ = PINOCCHIO_EIGEN_CONST_CAST(Vector3,scale);
-        scale_ <<
-        mesh->scale.x,
-        mesh->scale.y,
-        mesh->scale.z;
-      }
 
-#ifdef PINOCCHIO_WITH_HPP_FCL
-# if ( HPP_FCL_MAJOR_VERSION>1 || ( HPP_FCL_MAJOR_VERSION==1 && \
-      ( HPP_FCL_MINOR_VERSION>1 || ( HPP_FCL_MINOR_VERSION==1 && \
-                                     HPP_FCL_PATCH_VERSION>3))))
-#  define PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
-# endif
-
-      /**
-       * @brief      Get a fcl::CollisionObject from an urdf geometry, searching
-       *             for it in specified package directories
-       *
-       * @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] meshPath      The Absolute path of the mesh currently read
-       * @param[out] meshScale     Scale of transformation currently applied to the mesh
-       *
-       * @return     A shared pointer on the geometry converted as a fcl::CollisionGeometry
-       */
-      boost::shared_ptr<fcl::CollisionGeometry>
-      inline retrieveCollisionGeometry(const UrdfTree& tree,
-                                       fcl::MeshLoaderPtr& meshLoader,
-                                       const std::string& linkName,
-                                       const std::string& geomName,
-                                       const ::urdf::GeometrySharedPtr urdf_geometry,
-                                       const std::vector<std::string> & package_dirs,
-                                       std::string & meshPath,
-                                       Eigen::Vector3d & meshScale)
+      template<typename _Scalar, int _Options, template<typename,int> class JointCollectionTpl>
+      struct UrdfGeomVisitor : UrdfGeomVisitorBase
       {
-        boost::shared_ptr<fcl::CollisionGeometry> geometry;
+        typedef ModelTpl<_Scalar,_Options,JointCollectionTpl> Model;
+        const Model& model;
 
-        // Handle the case where collision geometry is a mesh
-        if (urdf_geometry->type == ::urdf::Geometry::MESH)
-        {
-          const ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry);
-          std::string collisionFilename = urdf_mesh->filename;
-          
-          meshPath = retrieveResourcePath(collisionFilename, package_dirs);
-          if (meshPath == "") {
-            std::stringstream ss;
-            ss << "Mesh " << collisionFilename << " could not be found.";
-            throw std::invalid_argument (ss.str());
-          }
-          
-          fcl::Vec3f scale = fcl::Vec3f(urdf_mesh->scale.x,
-                                        urdf_mesh->scale.y,
-                                        urdf_mesh->scale.z
-                                        );
-          
-          retrieveMeshScale(urdf_mesh, meshScale);
-          
-          // Create FCL mesh by parsing Collada file.
-#ifdef PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
-          hpp::fcl::BVHModelPtr_t bvh = meshLoader->load (meshPath, scale);
-          bool convex = tree.isMeshConvex (linkName, geomName);
-          if (convex) {
-            bvh->buildConvexRepresentation (false);
-            geometry = bvh->convex;
-          } else
-            geometry = bvh;
-#else
-          geometry = meshLoader->load (meshPath, scale);
-#endif
-        }
+        UrdfGeomVisitor (const Model& model) : model(model) {}
 
-        // Handle the case where collision geometry is a cylinder
-        // Use FCL capsules for cylinders
-        else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER)
-        {
-          const bool is_capsule = tree.isCapsule(linkName, geomName);
-          meshScale << 1,1,1;
-          const ::urdf::CylinderSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry);
-          
-          double radius = collisionGeometry->radius;
-          double length = collisionGeometry->length;
-          
-          // Create fcl capsule geometry.
-          if (is_capsule) {
-            meshPath = "CAPSULE";
-            geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length));
-          } else {
-            meshPath = "CYLINDER";
-            geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Cylinder (radius, length));
-          }
-        }
-        // Handle the case where collision geometry is a box.
-        else if (urdf_geometry->type == ::urdf::Geometry::BOX) 
-        {
-          meshPath = "BOX";
-          meshScale << 1,1,1;
-          const ::urdf::BoxSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Box> (urdf_geometry);
-          
-          double x = collisionGeometry->dim.x;
-          double y = collisionGeometry->dim.y;
-          double z = collisionGeometry->dim.z;
-          
-          geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Box (x, y, z));
-        }
-        // Handle the case where collision geometry is a sphere.
-        else if (urdf_geometry->type == ::urdf::Geometry::SPHERE)
+        Frame getBodyFrame (const std::string& link_name, FrameIndex& fid) const
         {
-          meshPath = "SPHERE";
-          meshScale << 1,1,1;
-          const ::urdf::SphereSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry);
-          
-          double radius = collisionGeometry->radius;
-          
-          geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Sphere (radius));
-        }
-        else throw std::invalid_argument("Unknown geometry type :");
-        
-        if (!geometry)
-        {
-          throw std::invalid_argument("The polyhedron retrived is empty");
-        }
-
-        return geometry;
-      }
-#endif // PINOCCHIO_WITH_HPP_FCL
-
-     /**
-      * @brief Get the first geometry attached to a link
-      *
-      * @param[in] link   The URDF link
-      *
-      * @return Either the first collision or visual
-      */
-      template<typename T>
-      inline PINOCCHIO_URDF_SHARED_PTR(const T)
-      getLinkGeometry(const ::urdf::LinkConstSharedPtr link);
-      
-      template<>
-      inline ::urdf::CollisionConstSharedPtr
-      getLinkGeometry< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
-      {
-        return link->collision;
-      }
-      
-      template<>
-      inline ::urdf::VisualConstSharedPtr
-      getLinkGeometry< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
-      {
-        return link->visual;
-      }
-
-
-     /**
-      * @brief Get the material values from the link visual object
-      *
-      * @param[in]  Visual/Collision The Visual or the Collision object.
-      * @param[out] meshTexturePath  The absolute file path containing the texture description.
-      * @param[out] meshColor        The mesh RGBA vector.
-      * @param[in]  package_dirs     A vector containing the different directories where to search for packages
-      *
-      */
-      template<typename urdfObject>
-      inline bool getVisualMaterial(const PINOCCHIO_URDF_SHARED_PTR(urdfObject) urdf_object,std::string & meshTexturePath,
-                                    Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs);
-      
-      template<>
-      inline bool getVisualMaterial< ::urdf::Collision>
-      (const ::urdf::CollisionSharedPtr, std::string& meshTexturePath,
-       Eigen::Vector4d & meshColor, const std::vector<std::string> &)
-      {
-        meshColor << 0.9, 0.9, 0.9, 1.;
-        meshTexturePath = "";
-        return false;
-      }
-      
-      template<>
-      inline bool getVisualMaterial< ::urdf::Visual>
-      (const ::urdf::VisualSharedPtr urdf_visual, std::string& meshTexturePath,
-       Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs)
-      {
-        meshColor.setZero();
-        meshTexturePath = "";
-        bool overrideMaterial = false;
-        if(urdf_visual->material) {
-          overrideMaterial = true;
-          meshColor << urdf_visual->material->color.r, urdf_visual->material->color.g,
-          urdf_visual->material->color.b, urdf_visual->material->color.a;
-          if(urdf_visual->material->texture_filename!="")
-            meshTexturePath = retrieveResourcePath((urdf_visual)->material->texture_filename, package_dirs);
-        }
-        return overrideMaterial;
-      }
-      
-     /**
-      * @brief Get the array of geometries attached to a link
-      *
-      * @param[in] link   The URDF link
-      *
-      * @return the array of either collisions or visuals
-      */
-      template<typename T>
-      inline const std::vector< PINOCCHIO_URDF_SHARED_PTR(T) > &
-      getLinkGeometryArray(const ::urdf::LinkConstSharedPtr link);
-      
-      template<>
-      inline const std::vector< ::urdf::CollisionSharedPtr> &
-      getLinkGeometryArray< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
-      {
-        return link->collision_array;
-      }
-      
-      template<>
-      inline const std::vector< ::urdf::VisualSharedPtr> &
-      getLinkGeometryArray< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
-      {
-        return link->visual_array;
-      }
-
-      /**
-       * @brief      Add the geometries attached to an URDF link to a GeometryModel, looking
-       *             either for collisions or visuals
-       *
-       * @param[in]  tree           The URDF kinematic tree
-       * @param[in]  meshLoader     The FCL mesh loader to avoid duplications of already loaded geometries
-       * @param[in]  link            The current URDF link
-       * @param      model           The model to which is the GeometryModel associated
-       * @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
-       *
-       */
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename GeometryType>
-      inline void addLinkGeometryToGeomModel(const UrdfTree & tree,
-                                             ::hpp::fcl::MeshLoaderPtr & meshLoader,
-                                             ::urdf::LinkConstSharedPtr link,
-                                             const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                                             GeometryModel & geomModel,
-                                             const std::vector<std::string> & package_dirs)
-      {
-#ifndef PINOCCHIO_WITH_HPP_FCL
-        PINOCCHIO_UNUSED_VARIABLE(tree);
-        PINOCCHIO_UNUSED_VARIABLE(meshLoader);
-#endif // PINOCCHIO_WITH_HPP_FCL
-        
-        typedef std::vector< PINOCCHIO_URDF_SHARED_PTR(GeometryType) > VectorSharedT;
-        typedef GeometryModel::SE3 SE3;
-
-        if(getLinkGeometry<GeometryType>(link))
-        {
-          std::string meshPath = "";
-
-          Eigen::Vector3d meshScale(Eigen::Vector3d::Ones());
-
-          const std::string & link_name = link->name;
-
-          VectorSharedT geometries_array = getLinkGeometryArray<GeometryType>(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;
-          PINOCCHIO_CHECK_INPUT_ARGUMENT(model.frames[frame_id].type == BODY);
-
-          std::size_t objectId = 0;
-          for (typename VectorSharedT::const_iterator i = geometries_array.begin();i != geometries_array.end(); ++i)
-          {
-            meshPath.clear();
-#ifdef PINOCCHIO_WITH_HPP_FCL
-            
-#ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
-            const std::string & geom_name = (*i)->group_name;
-#else
-            const std::string & geom_name = (*i)->name;
-#endif // PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
-            const GeometryObject::CollisionGeometryPtr geometry =
-            retrieveCollisionGeometry(tree, meshLoader, link_name, geom_name,
-                                      (*i)->geometry, package_dirs, meshPath, meshScale);
-#else
-            ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> ((*i)->geometry);
-            if (urdf_mesh)
-            {
-              meshPath = retrieveResourcePath(urdf_mesh->filename, package_dirs);
-              retrieveMeshScale(urdf_mesh, meshScale);
-            }
-
-            const boost::shared_ptr<fcl::CollisionGeometry> geometry(new fcl::CollisionGeometry());
-#endif // PINOCCHIO_WITH_HPP_FCL
-
-            Eigen::Vector4d meshColor;
-            std::string meshTexturePath;
-            bool overrideMaterial = getVisualMaterial<GeometryType>((*i), meshTexturePath, meshColor, package_dirs);
-
-            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());
-            GeometryObject geometry_object(geometry_object_name,
-                                           frame_id, model.frames[frame_id].parent,
-                                           geometry,
-                                           geomPlacement, meshPath, meshScale,
-                                           overrideMaterial, meshColor, meshTexturePath);
-            geomModel.addGeometryObject(geometry_object);
-            ++objectId;
-          }
+          fid = model.getFrameId(link_name, BODY);
+          PINOCCHIO_CHECK_INPUT_ARGUMENT(model.frames[fid].type == BODY);
+          return model.frames[fid].template cast<urdf_value_type>();
         }
-      }
+      };
 
       /**
        * @brief      Recursive procedure for reading the URDF tree, looking for geometries
@@ -435,34 +63,12 @@ namespace pinocchio
        * @param[in]  type           The type of objects that must be loaded ( can be VISUAL or COLLISION)
        *
        */
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      void parseTreeForGeom(const UrdfTree& tree,
-                            ::hpp::fcl::MeshLoaderPtr& meshLoader,
-                            ::urdf::LinkConstSharedPtr link,
-                            const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
+      void parseTreeForGeom(UrdfGeomVisitorBase& visitor,
+                            const std::istream& xmlStream,
+                            const GeometryType type,
                             GeometryModel & geomModel,
                             const std::vector<std::string> & package_dirs,
-                            const GeometryType type)
-      {
-        
-        switch(type)
-        {
-          case COLLISION:
-            addLinkGeometryToGeomModel<Scalar,Options,JointCollectionTpl, ::urdf::Collision >(tree, meshLoader, link, model, geomModel, package_dirs);
-            break;
-          case VISUAL:
-            addLinkGeometryToGeomModel<Scalar,Options,JointCollectionTpl, ::urdf::Visual >(tree, meshLoader, link, model, geomModel, package_dirs);
-            break;
-          default:
-            break;
-        }
-        
-        BOOST_FOREACH(::urdf::LinkConstSharedPtr child,link->child_links)
-        {
-          parseTreeForGeom(tree, meshLoader, child, model, geomModel, package_dirs,type);
-        }
-        
-      }
+                            ::hpp::fcl::MeshLoaderPtr meshLoader);
       
       } // namespace details
       
@@ -492,35 +98,13 @@ namespace pinocchio
                                const std::vector<std::string> & package_dirs,
                                ::hpp::fcl::MeshLoaderPtr meshLoader)
       {
-        std::string xmlStr;
-        {
-          std::ostringstream os;
-          os << xmlStream.rdbuf();
-          xmlStr = os.str();
-        }
-        
-        details::UrdfTree tree;
-        tree.parse (xmlStr);
-        
-        std::vector<std::string> hint_directories(package_dirs);
-        
-        // Append the ROS_PACKAGE_PATH
-        std::vector<std::string> ros_pkg_paths = rosPaths();
-        hint_directories.insert(hint_directories.end(), ros_pkg_paths.begin(), ros_pkg_paths.end());
-
-#ifdef PINOCCHIO_WITH_HPP_FCL
-        if (!meshLoader) meshLoader = fcl::MeshLoaderPtr(new fcl::MeshLoader);
-#endif // ifdef PINOCCHIO_WITH_HPP_FCL
-        
-        details::parseTreeForGeom(tree, meshLoader, tree.urdf_->getRoot(), model, geomModel, hint_directories,type);
+        details::UrdfGeomVisitor<Scalar, Options, JointCollectionTpl> visitor (model);
+        details::parseTreeForGeom (visitor, xmlStream, type, geomModel,
+            package_dirs, meshLoader);
         return geomModel;
       }
 
   } // namespace urdf
 } // namespace pinocchio
             
-#ifdef PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
-# undef PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
-#endif
-
 #endif // ifndef __pinocchio_multibody_parsers_urdf_geometry_hxx__
diff --git a/src/parsers/urdf/model.cpp b/src/parsers/urdf/model.cpp
new file mode 100644
index 000000000..63ffe7f02
--- /dev/null
+++ b/src/parsers/urdf/model.cpp
@@ -0,0 +1,300 @@
+//
+// Copyright (c) 2015-2020 CNRS
+// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
+//
+
+#include "pinocchio/parsers/urdf.hpp"
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+#include <sstream>
+#include <boost/foreach.hpp>
+#include <limits>
+
+namespace pinocchio
+{
+  namespace urdf
+  {
+    namespace details
+    {
+      ///
+      /// \brief Convert URDF Inertial quantity to Spatial Inertia.
+      ///
+      /// \param[in] Y The input URDF Inertia.
+      ///
+      /// \return The converted Spatial Inertia pinocchio::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::InertialSharedPtr & Y)
+      {
+        if (Y) return convertFromUrdf (*Y);
+        return Inertia::Zero();
+      }
+
+      ///
+      /// \brief Convert URDF Pose quantity to SE3.
+      ///
+      /// \param[in] M The input URDF Pose.
+      ///
+      /// \return The converted pose/transform pinocchio::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));
+      }
+
+      FrameIndex getParentJointFrame(const ::urdf::LinkConstSharedPtr link,
+                                     UrdfVisitorBase& model)
+      {
+        PINOCCHIO_CHECK_INPUT_ARGUMENT(link && link->getParent());
+
+        FrameIndex id = -1;
+        std::string parent_joint_name;
+        if (!link->getParent()->parent_joint)
+        {
+          try {
+            id = model.getJointFrameId("root_joint");
+          } catch (const std::invalid_argument&) {
+            id = 0;
+          }
+        }
+        else
+          id = model.getJointFrameId(link->getParent()->parent_joint->name);
+
+        return id;
+      }
+      
+      ///
+      /// \brief Recursive procedure for reading the URDF tree.
+      ///        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.
+      ///
+      void parseTree(::urdf::LinkConstSharedPtr link,
+                     UrdfVisitorBase& model)
+      {
+        typedef typename UrdfVisitorBase::Scalar Scalar;
+        typedef typename UrdfVisitorBase::SE3 SE3;
+        typedef typename UrdfVisitorBase::Vector Vector;
+        typedef typename UrdfVisitorBase::Vector3 Vector3;
+        typedef typename Model::FrameIndex FrameIndex;
+
+        // Parent joint of the current body
+        const ::urdf::JointConstSharedPtr joint =
+        ::urdf::const_pointer_cast< ::urdf::Joint>(link->parent_joint);
+
+        if(joint) // if the link is not the root of the tree
+        {
+          PINOCCHIO_CHECK_INPUT_ARGUMENT(link->getParent());
+
+          const std::string & joint_name = joint->name;
+          const std::string & link_name = link->name;
+          const std::string & parent_link_name = link->getParent()->name;
+          std::ostringstream joint_info;
+
+          FrameIndex parentFrameId = getParentJointFrame(link, model);
+
+          // Transformation from the parent link to the joint origin
+          const SE3 jointPlacement
+          = convertFromUrdf(joint->parent_to_joint_origin_transform);
+
+          const Inertia Y = convertFromUrdf(link->inertial);
+
+          Vector max_effort(1), max_velocity(1), min_config(1), max_config(1);
+          Vector3 axis (joint->axis.x, joint->axis.y, joint->axis.z);
+
+          const Scalar infty = std::numeric_limits<Scalar>::infinity();
+
+          switch(joint->type)
+          {
+            case ::urdf::Joint::FLOATING:
+              joint_info << "joint FreeFlyer";
+
+              max_effort   = Vector::Constant(6, infty);
+              max_velocity = Vector::Constant(6, infty);
+              min_config   = Vector::Constant(7,-infty);
+              max_config   = Vector::Constant(7, infty);
+              min_config.tail<4>().setConstant(-1.01);
+              max_config.tail<4>().setConstant( 1.01);
+
+              model.addJointAndBody(UrdfVisitorBase::FLOATING, axis,
+                  parentFrameId,jointPlacement,joint->name,
+                  Y,link->name,
+                  max_effort,max_velocity,min_config,max_config);
+              break;
+
+            case ::urdf::Joint::REVOLUTE:
+              joint_info << "joint REVOLUTE with axis";
+
+              // TODO I think the URDF standard forbids REVOLUTE with no limits.
+              assert(joint->limits);
+              if (joint->limits)
+              {
+                max_effort << joint->limits->effort;
+                max_velocity << joint->limits->velocity;
+                min_config << joint->limits->lower;
+                max_config << joint->limits->upper;
+              }
+
+              model.addJointAndBody(UrdfVisitorBase::REVOLUTE, axis,
+                  parentFrameId,jointPlacement,joint->name,
+                  Y,link->name,
+                  max_effort,max_velocity,min_config,max_config);
+              break;
+
+            case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits
+              joint_info << "joint CONTINUOUS with axis";
+
+              min_config.resize(2);
+              max_config.resize(2);
+              min_config << -1.01, -1.01;
+              max_config <<  1.01,  1.01;
+
+              if(joint->limits)
+              {
+                max_effort << joint->limits->effort;
+                max_velocity << joint->limits->velocity;
+              }
+
+              model.addJointAndBody(UrdfVisitorBase::CONTINUOUS, axis,
+                  parentFrameId,jointPlacement,joint->name,
+                  Y,link->name,
+                  max_effort,max_velocity,min_config,max_config);
+              break;
+
+            case ::urdf::Joint::PRISMATIC:
+              joint_info << "joint PRISMATIC with axis";
+
+              // TODO I think the URDF standard forbids REVOLUTE with no limits.
+              assert(joint->limits);
+              if (joint->limits)
+              {
+                max_effort << joint->limits->effort;
+                max_velocity << joint->limits->velocity;
+                min_config << joint->limits->lower;
+                max_config << joint->limits->upper;
+              }
+
+              model.addJointAndBody(UrdfVisitorBase::PRISMATIC, axis,
+                  parentFrameId,jointPlacement,joint->name,
+                  Y,link->name,
+                  max_effort,max_velocity,min_config,max_config);
+              break;
+
+            case ::urdf::Joint::PLANAR:
+              joint_info << "joint PLANAR with normal axis along Z";
+
+              max_effort   = Vector::Constant(3, infty);
+              max_velocity = Vector::Constant(3, infty);
+              min_config   = Vector::Constant(4,-infty);
+              max_config   = Vector::Constant(4, infty);
+              min_config.tail<2>().setConstant(-1.01);
+              max_config.tail<2>().setConstant( 1.01);
+
+              model.addJointAndBody(UrdfVisitorBase::PLANAR, axis,
+                  parentFrameId,jointPlacement,joint->name,
+                  Y,link->name,
+                  max_effort,max_velocity,min_config,max_config);
+              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";
+              model.addFixedJointAndBody(parentFrameId, jointPlacement,
+                  joint_name, Y, link_name);
+              break;
+
+            default:
+              throw std::invalid_argument("The type of joint " + joint_name + " is not supported.");
+              break;
+          }
+
+          model
+            << "Adding Body" << '\n'
+            << '\"' << link_name << "\" connected to \"" << parent_link_name << "\" through joint \"" << joint_name << "\"\n"
+            << "joint type: " << joint_info.str() << '\n'
+            << "joint placement:\n" << jointPlacement << '\n'
+            << "body info: " << '\n'
+            << "  mass: " << Y.mass() << '\n'
+            << "  lever: " << Y.lever().transpose() << '\n'
+            << "  inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << Y.inertia().data().transpose() << '\n' << '\n';
+        }
+        else if (link->getParent())
+          throw std::invalid_argument(link->name + " - joint information missing.");
+
+        BOOST_FOREACH(::urdf::LinkConstSharedPtr child, link->child_links)
+        {
+          parseTree(child, model);
+        }
+      }
+
+      ///
+      /// \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.
+      ///
+      void parseRootTree(const ::urdf::ModelInterface * urdfTree,
+                         UrdfVisitorBase& model)
+      {
+        model.setName(urdfTree->getName());
+
+        ::urdf::LinkConstSharedPtr root_link = urdfTree->getRoot();
+        model.addRootJoint(convertFromUrdf(root_link->inertial), root_link->name);
+        
+        BOOST_FOREACH(::urdf::LinkConstSharedPtr child, root_link->child_links)
+        {
+          parseTree(child, model);
+        }
+      }
+
+      void parseRootTree(const std::string & filename,
+                         UrdfVisitorBase& model)
+      {
+        ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile (filename);
+        if (urdfTree)
+          return parseRootTree (urdfTree.get(), model);
+        else
+          throw std::invalid_argument("The file " + filename + " does not "
+              "contain a valid URDF model.");
+      }
+
+      void parseRootTreeFromXML(const std::string & xmlString,
+                                UrdfVisitorBase& model)
+      {
+        ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(xmlString);
+        if (urdfTree)
+          return parseRootTree (urdfTree.get(), model);
+        else
+          throw std::invalid_argument("The XML stream does not contain a valid "
+              "URDF model.");
+      }
+    } // namespace details
+  } // namespace urdf
+} // namespace pinocchio
diff --git a/src/parsers/urdf/model.hxx b/src/parsers/urdf/model.hxx
index a31fd28db..785fa36f3 100644
--- a/src/parsers/urdf/model.hxx
+++ b/src/parsers/urdf/model.hxx
@@ -8,12 +8,8 @@
 
 #include "pinocchio/math/matrix.hpp"
 #include "pinocchio/parsers/urdf.hpp"
-#include "pinocchio/parsers/urdf/utils.hpp"
 #include "pinocchio/multibody/model.hpp"
 
-#include <urdf_model/model.h>
-#include <urdf_parser/urdf_parser.h>
-
 #include <sstream>
 #include <boost/foreach.hpp>
 #include <limits>
@@ -22,590 +18,358 @@ namespace pinocchio
 {
   namespace urdf
   {
-    namespace details
-    {
-      const FrameType JOINT_OR_FIXED_JOINT = (FrameType) (JOINT | FIXED_JOINT);
-      
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      FrameIndex getParentJointFrame(const ::urdf::LinkConstSharedPtr link,
-                                     const ModelTpl<Scalar,Options,JointCollectionTpl> & model)
-      {
-        typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-        typedef typename Model::Frame Frame;
-        typedef typename Model::FrameIndex FrameIndex;
-        
-        PINOCCHIO_CHECK_INPUT_ARGUMENT(link && link->getParent());
-        
-        FrameIndex id;
-        if (!link->getParent()->parent_joint)
-        {
-          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);
-        }
-        
-        const 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");
-      }
-
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      void appendBodyToJoint(ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                             const FrameIndex fid,
-                             const ::urdf::InertialConstSharedPtr Y_ptr,
-                             const typename ModelTpl<Scalar,Options,JointCollectionTpl>::SE3 & placement,
-                             const std::string & body_name)
-      {
-        typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-        typedef typename Model::Frame Frame;
-        typedef typename Model::SE3 SE3;
-        
-        const Frame & frame = model.frames[fid];
-        const SE3 & p = frame.placement * placement;
-        if(frame.parent > 0
-           && Y_ptr
-           && Y_ptr->mass > Eigen::NumTraits<double>::epsilon())
-        {
-          model.appendBodyToJoint(frame.parent, convertFromUrdf(*Y_ptr), 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 Scalar, int Options, template<typename,int> class JointCollectionTpl, typename JointModel>
-      void addJointAndBody(ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                           const JointModelBase<JointModel> & jmodel,
-                           const typename ModelTpl<Scalar,Options,JointCollectionTpl>::FrameIndex & parentFrameId,
-                           const typename ModelTpl<Scalar,Options,JointCollectionTpl>::SE3 & joint_placement,
-                           const std::string & joint_name,
-                           const ::urdf::InertialConstSharedPtr Y,
-                           const std::string & body_name,
-                           const typename JointModel::TangentVector_t & max_effort,
-                           const typename JointModel::TangentVector_t & max_velocity,
-                           const typename JointModel::ConfigVector_t  & min_config,
-                           const typename JointModel::ConfigVector_t  & max_config)
-      {
-        typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-        typedef typename Model::Frame Frame;
-        typedef typename Model::SE3 SE3;
-        typedef typename Model::JointIndex JointIndex;
-        typedef typename Model::FrameIndex FrameIndex;
-        
-        JointIndex idx;
-        const Frame & frame = model.frames[parentFrameId];
-        
-        idx = model.addJoint(frame.parent,jmodel,
-                             frame.placement * joint_placement,
-                             joint_name,
-                             max_effort,max_velocity,min_config,max_config
-                             );
-        int res (model.addJointFrame(idx, (int)parentFrameId));
-        if (res == -1) {
-          std::ostringstream oss;
-          oss << joint_name << " already inserted as a frame. Current frames "
-          "are [";
-          for (typename PINOCCHIO_ALIGNED_STD_VECTOR(Frame)::const_iterator it =
-               model.frames.begin (); it != model.frames.end (); ++it) {
-            oss << "\"" << it->name << "\",";
+    namespace details {
+      typedef double urdf_value_type;
+
+      template<typename _Scalar, int Options>
+      class UrdfVisitorBaseTpl {
+        public:
+          enum JointType {
+            REVOLUTE, CONTINUOUS, PRISMATIC, FLOATING, PLANAR
+          };
+
+          typedef _Scalar Scalar;
+          typedef SE3Tpl<Scalar,Options> SE3;
+          typedef InertiaTpl<Scalar,Options> Inertia;
+
+          typedef Eigen::Matrix<Scalar, 3, 1> Vector3;
+          typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;
+          typedef Eigen::Ref<Vector> VectorRef;
+          typedef Eigen::Ref<const Vector> VectorConstRef;
+
+          virtual void setName (const std::string& name) = 0;
+
+          virtual void addRootJoint (const Inertia& Y, const std::string & body_name) = 0;
+
+          virtual void addJointAndBody(
+              JointType type,
+              const Vector3& axis,
+              const FrameIndex & parentFrameId,
+              const SE3 & placement,
+              const std::string & joint_name,
+              const Inertia& Y,
+              const std::string & body_name,
+              const VectorConstRef& max_effort,
+              const VectorConstRef& max_velocity,
+              const VectorConstRef& min_config,
+              const VectorConstRef& max_config) = 0;
+
+          virtual void addFixedJointAndBody(
+              const FrameIndex & parentFrameId,
+              const SE3 & joint_placement,
+              const std::string & joint_name,
+              const Inertia& Y,
+              const std::string & body_name) = 0;
+
+          virtual void appendBodyToJoint(
+              const FrameIndex fid,
+              const Inertia& Y,
+              const SE3 & placement,
+              const std::string & body_name) = 0;
+
+          virtual FrameIndex getJointFrameId (
+              const std::string& frame_name) const = 0;
+
+          UrdfVisitorBaseTpl () : log (NULL) {}
+
+          template <typename T>
+          UrdfVisitorBaseTpl& operator<< (const T& t)
+          {
+            if (log != NULL) *log << t;
+            return *this;
           }
-          oss << "]";
-          throw std::invalid_argument(oss.str().c_str());
-        }
-        
-        FrameIndex jointFrameId = (FrameIndex) res; // 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);
-      }
-      
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename JointModel>
-      void addJointAndBody(ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                           const JointModelBase<JointModel> & jmodel,
-                           const typename ModelTpl<Scalar,Options,JointCollectionTpl>::FrameIndex & parentFrameId,
-                           const typename ModelTpl<Scalar,Options,JointCollectionTpl>::SE3 & joint_placement,
-                           const std::string & joint_name,
-                           const ::urdf::InertialConstSharedPtr Y,
-                           const std::string & body_name)
-      {
-        const Scalar infty = std::numeric_limits<Scalar>::infinity();
-        
-        const typename JointModel::TangentVector_t max_effort   = JointModel::TangentVector_t::Constant(jmodel.nv(), infty);
-        const typename JointModel::TangentVector_t max_velocity = JointModel::TangentVector_t::Constant(jmodel.nv(), infty);
-        const typename JointModel::ConfigVector_t  min_config   = JointModel::ConfigVector_t ::Constant(jmodel.nq(),-infty);
-        const typename JointModel::ConfigVector_t  max_config   = JointModel::ConfigVector_t ::Constant(jmodel.nq(), infty);
-        
-        addJointAndBody(model,jmodel.derived(),parentFrameId,joint_placement,joint_name,Y,body_name,
-                        max_effort,max_velocity,min_config,max_config);
-      }
-      
-      ///
-      /// \brief Shortcut for adding a fixed joint and directly append a body to it.
-      ///
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      void addFixedJointAndBody(ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                                const typename ModelTpl<Scalar,Options,JointCollectionTpl>::FrameIndex & parentFrameId,
-                                const typename ModelTpl<Scalar,Options,JointCollectionTpl>::SE3 & joint_placement,
-                                const std::string & joint_name,
-                                const ::urdf::InertialConstSharedPtr Y,
-                                const std::string & body_name)
-      {
-        typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-        typedef typename Model::Frame Frame;
-        
-        const 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 Recursive procedure for reading the URDF tree.
-      ///        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.
-      ///
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      void parseTree(::urdf::LinkConstSharedPtr link,
-                     ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                     bool verbose)
-      {
-        typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-        typedef typename Model::JointCollection JointCollection;
-        typedef typename Model::SE3 SE3;
-        typedef typename Model::FrameIndex FrameIndex;
 
-        // Parent joint of the current body
-        const ::urdf::JointConstSharedPtr joint =
-        ::urdf::const_pointer_cast< ::urdf::Joint>(link->parent_joint);
+          std::ostream* log;
+      };
 
-        if(joint) // if the link is not the root of the tree
-        {
-          PINOCCHIO_CHECK_INPUT_ARGUMENT(link->getParent());
+      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
+      class UrdfVisitor : public UrdfVisitorBaseTpl<Scalar, Options>
+      {
+        public:
+          typedef UrdfVisitorBaseTpl<Scalar, Options> Base;
+          typedef typename Base::JointType      JointType;
+          typedef typename Base::Vector3        Vector3;
+          typedef typename Base::VectorConstRef VectorConstRef;
+          typedef typename Base::SE3            SE3;
+          typedef typename Base::Inertia        Inertia;
 
-          const std::string & joint_name = joint->name;
-          const std::string & link_name = link->name;
-          const std::string & parent_link_name = link->getParent()->name;
-          std::ostringstream joint_info;
+          typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
+          typedef typename Model::JointCollection JointCollection;
+          typedef typename Model::JointModel JointModel;
+          typedef typename Model::Frame Frame;
 
-          FrameIndex parentFrameId = getParentJointFrame(link, model);
+          Model& model;
 
-          // Transformation from the parent link to the joint origin
-          const SE3 jointPlacement
-          = convertFromUrdf(joint->parent_to_joint_origin_transform).template cast<Scalar>();
+          UrdfVisitor (Model& model) : model(model) {}
 
-          const ::urdf::InertialSharedPtr Y =
-          ::urdf::const_pointer_cast< ::urdf::Inertial>(link->inertial);
+          void setName (const std::string& name)
+          {
+            model.name = name;
+          }
 
-          switch(joint->type)
+          virtual void addRootJoint (const Inertia& Y, const std::string & body_name)
           {
-            case ::urdf::Joint::FLOATING:
-              joint_info << "joint FreeFlyer";
-              addJointAndBody(model,typename JointCollection::JointModelFreeFlyer(),
-                              parentFrameId,jointPlacement,joint->name,
-                              Y,link->name);
-
-              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;
-              }
+            addFixedJointAndBody(0, SE3::Identity(), "root_joint", Y, body_name);
+          }
 
-              CartesianAxis axis = extractCartesianAxis(joint->axis);
-
-              switch(axis)
-              {
-                case AXIS_X:
-                  joint_info << " along X";
-                  addJointAndBody(model, typename JointCollection::JointModelRX(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Y:
-                  joint_info << " along Y";
-                  addJointAndBody(model, typename JointCollection::JointModelRY(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Z:
-                  joint_info << " along Z";
-                  addJointAndBody(model, typename JointCollection::JointModelRZ(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_UNALIGNED:
-                {
-                  typename SE3::Vector3 joint_axis((Scalar)joint->axis.x,(Scalar)joint->axis.y,(Scalar)joint->axis.z);
-                  joint_info << " unaligned along (" << joint_axis.transpose() << ")";
-
-                  addJointAndBody(model, typename JointCollection::JointModelRevoluteUnaligned(joint_axis.normalized()),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-                }
-                default:
-                  PINOCCHIO_CHECK_INPUT_ARGUMENT(false, "The axis type of the revolute joint is of wrong type.");
-                  break;
-              }
-              break;
+          void addJointAndBody(
+              JointType type,
+              const Vector3& axis,
+              const FrameIndex & parentFrameId,
+              const SE3 & placement,
+              const std::string & joint_name,
+              const Inertia& Y,
+              const std::string & body_name,
+              const VectorConstRef& max_effort,
+              const VectorConstRef& max_velocity,
+              const VectorConstRef& min_config,
+              const VectorConstRef& max_config)
+          {
+            JointIndex idx;
+            const Frame & frame = model.frames[parentFrameId];
+
+            switch (type) {
+              case Base::FLOATING:
+                idx = model.addJoint(frame.parent,
+                    typename JointCollection::JointModelFreeFlyer(),
+                    frame.placement * placement,
+                    joint_name,
+                    max_effort,max_velocity,min_config,max_config
+                    );
+                break;
+              case Base::REVOLUTE:
+                idx = addJoint<
+                  typename JointCollection::JointModelRX,
+                  typename JointCollection::JointModelRY,
+                  typename JointCollection::JointModelRZ,
+                  typename JointCollection::JointModelRevoluteUnaligned> (
+                      axis, frame, placement, joint_name,
+                      max_effort, max_velocity, min_config, max_config);
+                break;
+              case Base::CONTINUOUS:
+                idx = addJoint<
+                  typename JointCollection::JointModelRUBX,
+                  typename JointCollection::JointModelRUBY,
+                  typename JointCollection::JointModelRUBZ,
+                  typename JointCollection::JointModelRevoluteUnboundedUnaligned> (
+                      axis, frame, placement, joint_name,
+                      max_effort, max_velocity, min_config, max_config);
+                break;
+              case Base::PRISMATIC:
+                idx = addJoint<
+                  typename JointCollection::JointModelPX,
+                  typename JointCollection::JointModelPY,
+                  typename JointCollection::JointModelPZ,
+                  typename JointCollection::JointModelPrismaticUnaligned> (
+                      axis, frame, placement, joint_name,
+                      max_effort, max_velocity, min_config, max_config);
+                break;
+              case Base::PLANAR:
+                idx = model.addJoint(frame.parent,
+                    typename JointCollection::JointModelPlanar(),
+                    frame.placement * placement,
+                    joint_name,
+                    max_effort,max_velocity,min_config,max_config
+                    );
+                break;
+              default:
+                PINOCCHIO_CHECK_INPUT_ARGUMENT(false, "The joint type is not correct.");
+            };
+            int res (model.addJointFrame(idx, (int)parentFrameId));
+            if (res == -1) {
+              std::ostringstream oss;
+              oss << joint_name << " already inserted as a frame. Current frames "
+                "are [";
+              for (typename PINOCCHIO_ALIGNED_STD_VECTOR(Frame)::const_iterator it =
+                  model.frames.begin (); it != model.frames.end (); ++it) {
+                oss << '"' << it->name << "\",";
               }
+              oss << ']';
+              throw std::invalid_argument(oss.str());
+            }
 
-            case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits
-              {
-              joint_info << "joint CONTINUOUS with axis";
+            FrameIndex jointFrameId = (FrameIndex) res; // C-style cast to remove polluting compilation warning. This is Bad practice. See issue #323 (rework indexes)
+            appendBodyToJoint(jointFrameId, Y, SE3::Identity(), body_name);
+          }
 
-              typedef JointModelRUBX::ConfigVector_t ConfigVector_t;
-              typedef JointModelRUBX::TangentVector_t TangentVector_t;
+          void addFixedJointAndBody(
+              const FrameIndex & parentFrameId,
+              const SE3 & joint_placement,
+              const std::string & joint_name,
+              const Inertia& Y,
+              const std::string & body_name)
+          {
+            const Frame & frame = model.frames[parentFrameId];
 
-              TangentVector_t max_effort;
-              TangentVector_t max_velocity;
-              const ConfigVector_t::Scalar u = 1.01;
-              ConfigVector_t lower_position(-u, -u);
-              ConfigVector_t upper_position( u,  u);
+            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.");
 
-              if(joint->limits)
-              {
-                max_effort << joint->limits->effort;
-                max_velocity << joint->limits->velocity;
-              }
+            appendBodyToJoint((FrameIndex)fid, Y, SE3::Identity(), body_name);
+          }
 
-              CartesianAxis axis = extractCartesianAxis(joint->axis);
-
-              switch(axis)
-              {
-                case AXIS_X:
-                  joint_info << " along X";
-                  addJointAndBody(model, typename JointCollection::JointModelRUBX(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Y:
-                  joint_info << " along Y";
-                  addJointAndBody(model, typename JointCollection::JointModelRUBY(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Z:
-                  joint_info << " along Z";
-                  addJointAndBody(model, typename JointCollection::JointModelRUBZ(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_UNALIGNED:
-                {
-                  typename SE3::Vector3 joint_axis((Scalar)joint->axis.x,(Scalar)joint->axis.y,(Scalar)joint->axis.z);
-                  joint_info << " unaligned along (" << joint_axis.transpose() << ")";
-
-                  typedef typename JointCollection::JointModelRevoluteUnboundedUnaligned::ConfigVector_t ConfigVector_t;
-
-                  const Scalar infty = std::numeric_limits<Scalar>::infinity();
-                  ConfigVector_t lower_position(ConfigVector_t::Constant(-infty));
-                  ConfigVector_t upper_position(ConfigVector_t::Constant(infty));
-
-                  addJointAndBody(model, typename JointCollection::JointModelRevoluteUnboundedUnaligned(joint_axis.normalized()),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position,upper_position);
-                  break;
-                }
-
-                default:
-                  PINOCCHIO_CHECK_INPUT_ARGUMENT(false, "The axis type of the revolute joint is of wrong type.");
-                  break;
-              }
-              break;
-              }
+          void appendBodyToJoint(
+              const FrameIndex fid,
+              const Inertia& 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.mass() > Eigen::NumTraits<Scalar>::epsilon())
+            {
+              model.appendBodyToJoint(frame.parent, 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()));
+            }
+          }
 
-            case ::urdf::Joint::PRISMATIC:
-              {
-              joint_info << "joint PRISMATIC with axis";
+          FrameIndex getJointFrameId (const std::string& frame_name) const
+          {
+            static const FrameType JOINT_OR_FIXED_JOINT = (FrameType)(JOINT | FIXED_JOINT);
+            if (model.existFrame(frame_name, JOINT_OR_FIXED_JOINT)) {
+              FrameIndex fid = model.getFrameId (frame_name, JOINT_OR_FIXED_JOINT);
+              assert(model.frames[fid].type == JOINT
+                  || model.frames[fid].type == FIXED_JOINT);
+              return fid;
+            } else
+              throw std::invalid_argument("Model does not have any joints named "
+                  + frame_name);
+          }
 
-              typedef JointModelRX::ConfigVector_t ConfigVector_t;
-              typedef JointModelRX::TangentVector_t TangentVector_t;
+        private:
+          ///
+          /// \brief The four possible cartesian types of an 3D axis.
+          ///
+          enum CartesianAxis { AXIS_X=0, AXIS_Y=1, AXIS_Z=2, AXIS_UNALIGNED };
+
+          ///
+          /// \brief Extract the cartesian property of a particular 3D axis.
+          ///
+          /// \param[in] axis The input URDF axis.
+          ///
+          /// \return The property of the particular axis pinocchio::urdf::CartesianAxis.
+          ///
+          static inline CartesianAxis extractCartesianAxis (const Vector3 & axis)
+          {
+            if( axis == Vector3(1., 0., 0.))
+              return AXIS_X;
+            else if( axis == Vector3(0., 1., 0.))
+              return AXIS_Y;
+            else if( axis == Vector3(0., 0., 1.))
+              return AXIS_Z;
+            else
+              return AXIS_UNALIGNED;
+          }
 
-              TangentVector_t max_effort;
-              TangentVector_t max_velocity;
-              ConfigVector_t lower_position;
-              ConfigVector_t upper_position;
+          template <typename TypeX, typename TypeY, typename TypeZ,
+                   typename TypeUnaligned>
+          JointIndex addJoint(
+              const Vector3& axis,
+              const Frame & frame,
+              const SE3 & placement,
+              const std::string & joint_name,
+              const VectorConstRef& max_effort,
+              const VectorConstRef& max_velocity,
+              const VectorConstRef& min_config,
+              const VectorConstRef& max_config)
+          {
+            CartesianAxis axisType = extractCartesianAxis(axis);
+            switch (axisType)
+            {
+              case AXIS_X:
+                return model.addJoint(frame.parent, TypeX(),
+                    frame.placement * placement, joint_name,
+                    max_effort,max_velocity,min_config,max_config);
+                break;
 
-              if (joint->limits)
-              {
-                max_effort << joint->limits->effort;
-                max_velocity << joint->limits->velocity;
-                lower_position << joint->limits->lower;
-                upper_position << joint->limits->upper;
-              }
+              case AXIS_Y:
+                return model.addJoint(frame.parent, TypeY(),
+                    frame.placement * placement, joint_name,
+                    max_effort,max_velocity,min_config,max_config);
+                break;
 
-              CartesianAxis axis = extractCartesianAxis(joint->axis);
-              switch(axis)
-              {
-                case AXIS_X:
-                  joint_info << " along X";
-                  addJointAndBody(model, typename JointCollection::JointModelPX(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Y:
-
-                  joint_info << " along Y";
-                  addJointAndBody(model, typename JointCollection::JointModelPY(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_Z:
-                  joint_info << " along Z";
-                  addJointAndBody(model, typename JointCollection::JointModelPZ(),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-
-                case AXIS_UNALIGNED:
-                {
-                  typename SE3::Vector3 joint_axis((Scalar)joint->axis.x,(Scalar)joint->axis.y,(Scalar)joint->axis.z);
-                  joint_info << " unaligned along (" << joint_axis.transpose() << ")";
-
-                  addJointAndBody(model, typename JointCollection::JointModelPrismaticUnaligned(joint_axis.normalized()),
-                                  parentFrameId,jointPlacement,joint->name,
-                                  Y,link->name,
-                                  max_effort,max_velocity,
-                                  lower_position, upper_position);
-                  break;
-                }
-
-                default:
-                  PINOCCHIO_CHECK_INPUT_ARGUMENT(false, "The axis type of the prismatic joint is of wrong type.");
-                  break;
-              }
-              break;
-              }
+              case AXIS_Z:
+                return model.addJoint(frame.parent, TypeZ(),
+                    frame.placement * placement, joint_name,
+                    max_effort,max_velocity,min_config,max_config);
+                break;
 
-            case ::urdf::Joint::PLANAR:
-              {
-              joint_info << "joint PLANAR with normal axis along Z";
+              case AXIS_UNALIGNED:
+                return model.addJoint(frame.parent, TypeUnaligned (axis.normalized()),
+                    frame.placement * placement, joint_name,
+                    max_effort,max_velocity,min_config,max_config);
+                break;
+              default:
+                PINOCCHIO_CHECK_INPUT_ARGUMENT(false, "The axis type of the joint is of wrong type.");
+                break;
+            }
+          }
+      };
 
-              typedef JointModelPlanar::ConfigVector_t ConfigVector_t;
-              typedef JointModelPlanar::TangentVector_t TangentVector_t;
+      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
+      class UrdfVisitorWithRootJoint : public UrdfVisitor<Scalar, Options, JointCollectionTpl>
+      {
+        public:
+          typedef UrdfVisitor<Scalar, Options, JointCollectionTpl> Base;
+          typedef typename Base::Inertia        Inertia;
+          using Base::model;
+          using Base::appendBodyToJoint;
 
-              TangentVector_t max_effort;
-              TangentVector_t max_velocity;
-              ConfigVector_t lower_position;
-              ConfigVector_t upper_position;
+          typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
+          typedef typename Model::JointCollection JointCollection;
 
-              if (joint->limits)
-              {
-                max_effort << joint->limits->effort;
-                max_velocity << joint->limits->velocity;
-                lower_position << joint->limits->lower;
-                upper_position << joint->limits->upper;
-              }
+          JointModel root_joint;
 
-              addJointAndBody(model, typename JointCollection::JointModelPlanar(),
-                              parentFrameId,jointPlacement,joint->name,
-                              Y,link->name,
-                              max_effort,max_velocity,
-                              lower_position, upper_position);
+          UrdfVisitorWithRootJoint (Model& model, const JointModelBase<JointModel> & root_joint)
+            : Base (model), root_joint (root_joint.derived()) {}
 
+          void addRootJoint (const Inertia& Y, const std::string & body_name)
+          {
+            const Frame & frame = model.frames[0];
+
+            JointIndex idx = model.addJoint(frame.parent, root_joint,
+                SE3::Identity(), "root_joint"
+                //TODO ,max_effort,max_velocity,min_config,max_config
+                );
+            int res (model.addJointFrame(idx, 0));
+            if (res == -1) {
+              std::ostringstream oss;
+              oss << "root_joint already inserted as a frame. Current frames "
+                "are [";
+              for (typename PINOCCHIO_ALIGNED_STD_VECTOR(Frame)::const_iterator it =
+                  model.frames.begin (); it != model.frames.end (); ++it) {
+                oss << '"' << it->name << "\",";
               }
-              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";
-              addFixedJointAndBody(model, parentFrameId, jointPlacement,
-                                   joint_name, Y, link_name);
-              
-              break;
-              
-            default:
-              {
-                const std::string exception_message("The type of joint " + joint_name + " is not supported.");
-                throw std::invalid_argument(exception_message);
-                break;
-              }
-          }
+              oss << ']';
+              throw std::invalid_argument(oss.str());
+            }
 
-          if(verbose)
-          {
-            const Inertia YY = (!Y) ? 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.str() << std::endl;
-            std::cout << "joint placement:\n" << jointPlacement;
-            std::cout << "body info: " << 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;
+            FrameIndex jointFrameId = (FrameIndex) res; // C-style cast to remove polluting compilation warning. This is Bad practice. See issue #323 (rework indexes)
+            appendBodyToJoint(jointFrameId, Y, SE3::Identity(), body_name);
           }
-        }
-        else if (link->getParent())
-        {
-          const std::string exception_message (link->name + " - joint information missing.");
-          throw std::invalid_argument(exception_message);
-        }
-
-        BOOST_FOREACH(::urdf::LinkConstSharedPtr child, link->child_links)
-        {
-          parseTree(child, model, 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] verbose Print parsing info.
-      ///
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-      void parseRootTree(::urdf::LinkConstSharedPtr root_link,
-                         ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                         const bool verbose)
-      {
-        addFixedJointAndBody(model, 0, SE3::Identity(), "root_joint",
-                             root_link->inertial, root_link->name);
-        
-        BOOST_FOREACH(::urdf::LinkConstSharedPtr child, root_link->child_links)
-        {
-          parseTree(child, model, 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] root_joint The specific root joint.
-      /// \param[in] verbose Print parsing info.
-      ///
-      template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename JointModel>
-      void parseRootTree(::urdf::LinkConstSharedPtr root_link,
-                         ModelTpl<Scalar,Options,JointCollectionTpl> & model,
-                         const JointModelBase<JointModel> & root_joint,
-                         const bool verbose)
-      {
-        addJointAndBody(model,root_joint,
-                        0,SE3::Identity(),"root_joint",
-                        root_link->inertial,root_link->name);
-
-        BOOST_FOREACH(::urdf::LinkConstSharedPtr child, root_link->child_links)
-        {
-          parseTree(child, model, verbose);
-        }
-      }
-    } // namespace details
-              
-    ///
-    /// \brief Call parse root tree templated function
-    ///
-    template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
-    struct ParseRootTreeVisitor : public boost::static_visitor<>
-    {
-      typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
-      ::urdf::LinkConstSharedPtr m_root_link;
-      Model & m_model;
-      const bool m_verbose;
-     
-      ParseRootTreeVisitor(::urdf::LinkConstSharedPtr root_link,
-                           Model & model,
-                           const bool verbose)
-      : m_root_link(root_link)
-      , m_model(model)
-      , m_verbose(verbose)
-      {}
-      
-      template<typename JointModel>
-      void operator()(const JointModelBase<JointModel> & root_joint) const
-      {
-        details::parseRootTree(m_root_link,m_model,root_joint,m_verbose);
-      }
-      
-      static void run(::urdf::LinkConstSharedPtr root_link,
-                      Model & model,
-                      const typename Model::JointModel & root_joint,
-                      const bool verbose)
-      {
-        boost::apply_visitor(ParseRootTreeVisitor(root_link,model,verbose),root_joint);
-      }
-    }; // struct ParseRootTreeVisitor
+      };
+
+      typedef UrdfVisitorBaseTpl<double, 0> UrdfVisitorBase;
+
+      void parseRootTree(const ::urdf::ModelInterface * urdfTree,
+                         UrdfVisitorBase& model);
+
+      void parseRootTree(const std::string & filename,
+                         UrdfVisitorBase& model);
+
+      void parseRootTreeFromXML(const std::string & xmlString,
+                                UrdfVisitorBase& model);
+    }
 
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
@@ -613,39 +377,22 @@ namespace pinocchio
                const typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointModel & root_joint,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose)
-     
     {
-      ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile (filename);
-
-      if (urdfTree)
-      {
-          return buildModel (urdfTree, root_joint, model, verbose);
-      }
-      else
-      {
-        const std::string exception_message ("The file " + filename + " does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
+      details::UrdfVisitorWithRootJoint<Scalar, Options, JointCollectionTpl> visitor (model, root_joint);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTree(filename, visitor);
       return model;
     }
+
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
     buildModel(const std::string & filename,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose)
-   
     {
-      ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(filename);
-      if (urdfTree)
-      {
-          return buildModel(urdfTree, model, verbose);
-      }
-      else
-      {
-        const std::string exception_message("The file " + filename + " does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
-      
+      details::UrdfVisitor<Scalar, Options, JointCollectionTpl> visitor (model);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTree(filename, visitor);
       return model;
     }
     
@@ -656,16 +403,9 @@ namespace pinocchio
                       ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                       const bool verbose)
     {
-      ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(xmlStream);
-      
-      if (urdfTree)
-        return buildModel(urdfTree, rootJoint, model, verbose);
-      else
-      {
-        const std::string exception_message ("The XML stream does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
-      
+      details::UrdfVisitorWithRootJoint<Scalar, Options, JointCollectionTpl> visitor (model, rootJoint);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTreeFromXML(xmlStream, visitor);
       return model;
     }
     
@@ -675,41 +415,36 @@ namespace pinocchio
                       ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                       const bool verbose)
     {
-      ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(xmlStream);
-      
-      if (urdfTree)
-        return buildModel(urdfTree, model, verbose);
-      else
-      {
-        const std::string exception_message ("The XML stream does not contain a valid URDF model.");
-        throw std::invalid_argument(exception_message);
-      }
-      
+      details::UrdfVisitor<Scalar, Options, JointCollectionTpl> visitor (model);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTreeFromXML(xmlStream, visitor);
       return model;
     }
 
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
-    buildModel(const ::urdf::ModelInterfaceSharedPtr & urdfTree,
-               const typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointModel & root_joint,
+    buildModel(const ::urdf::ModelInterface* urdfTree,
+               const typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointModel & rootJoint,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose)
     {
-      PINOCCHIO_CHECK_INPUT_ARGUMENT(urdfTree);
-      model.name = urdfTree->getName();
-      ParseRootTreeVisitor<Scalar,Options,JointCollectionTpl>::run(urdfTree->getRoot(),model,root_joint,verbose);
+      PINOCCHIO_CHECK_INPUT_ARGUMENT(urdfTree != NULL);
+      details::UrdfVisitorWithRootJoint<Scalar, Options, JointCollectionTpl> visitor (model, rootJoint);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTree(urdfTree, visitor);
       return model;
     }
-    
+
     template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
     ModelTpl<Scalar,Options,JointCollectionTpl> &
-    buildModel(const ::urdf::ModelInterfaceSharedPtr & urdfTree,
+    buildModel(const ::urdf::ModelInterface* urdfTree,
                ModelTpl<Scalar,Options,JointCollectionTpl> & model,
                const bool verbose)
     {
-      PINOCCHIO_CHECK_INPUT_ARGUMENT(urdfTree);
-      model.name = urdfTree->getName();
-      details::parseRootTree(urdfTree->getRoot(),model,verbose);
+      PINOCCHIO_CHECK_INPUT_ARGUMENT(urdfTree != NULL);
+      details::UrdfVisitor<Scalar, Options, JointCollectionTpl> visitor (model);
+      if (verbose) visitor.log = &std::cout;
+      parseRootTree(urdfTree, visitor);
       return model;
     }
 
diff --git a/src/parsers/urdf/utils.hpp b/src/parsers/urdf/utils.hpp
index 1772939a9..056da1537 100644
--- a/src/parsers/urdf/utils.hpp
+++ b/src/parsers/urdf/utils.hpp
@@ -5,76 +5,6 @@
 #ifndef __pinocchio_parsers_urdf_utils_hpp__
 #define __pinocchio_parsers_urdf_utils_hpp__
 
-#include <urdf_model/model.h>
+#warning "This file is not deprecated and will be removed in future releases. There is no replacement."
 
-#include "pinocchio/spatial/se3.hpp"
-#include "pinocchio/spatial/inertia.hpp"
-
-namespace pinocchio
-{
-  namespace urdf
-  {
-
-    ///
-    /// \brief Convert URDF Inertial quantity to Spatial Inertia.
-    ///
-    /// \param[in] Y The input URDF Inertia.
-    ///
-    /// \return The converted Spatial Inertia pinocchio::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());
-    }
-    
-    ///
-    /// \brief Convert URDF Pose quantity to SE3.
-    ///
-    /// \param[in] M The input URDF Pose.
-    ///
-    /// \return The converted pose/transform pinocchio::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));
-    }
-    
-    ///
-    /// \brief The four possible cartesian types of an 3D axis.
-    ///
-    enum CartesianAxis { AXIS_X=0, AXIS_Y=1, AXIS_Z=2, AXIS_UNALIGNED };
-    
-    ///
-    /// \brief Extract the cartesian property of a particular 3D axis.
-    ///
-    /// \param[in] axis The input URDF axis.
-    ///
-    /// \return The property of the particular axis pinocchio::urdf::CartesianAxis.
-    ///
-    inline CartesianAxis 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;
-    }
-
-  } //urdf
-} // se3
 #endif // __pinocchio_parsers_urdf_utils_hpp__
-- 
GitLab