From a215dbe6fb8cb38d51f5aa5f7af2ccf5a9cb34c6 Mon Sep 17 00:00:00 2001
From: Mansard <nmansard@laas.fr>
Date: Sun, 24 Aug 2014 23:09:21 +0200
Subject: [PATCH] Copy urdf parser in multibody/parser.

---
 CMakeLists.txt                |   2 +
 src/multibody/parser/urdf.hpp | 142 ++++++++++++++++++++++++++++++++++
 unittest/urdf.cpp             | 131 +------------------------------
 3 files changed, 147 insertions(+), 128 deletions(-)
 create mode 100644 src/multibody/parser/urdf.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 051344854..b5759b14b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ SET(${PROJECT_NAME}_HEADERS
   multibody/joint/joint-variant.hpp
   multibody/model.hpp
   multibody/visitor.hpp
+  multibody/parser/urdf.hpp
   tools/timer.hpp
   algorithm/rnea.hpp
 )
@@ -53,6 +54,7 @@ MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/spatial")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody/joint")
+MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/multibody/parser")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/tools")
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/algorithm")
 
diff --git a/src/multibody/parser/urdf.hpp b/src/multibody/parser/urdf.hpp
new file mode 100644
index 000000000..17ab1fc95
--- /dev/null
+++ b/src/multibody/parser/urdf.hpp
@@ -0,0 +1,142 @@
+#ifndef __se3_urdf_hpp__
+#define __se3_urdf_hpp__
+
+#include <urdf_model/model.h>
+#include <urdf_parser/urdf_parser.h>
+
+#include <iostream>
+#include <boost/foreach.hpp>
+#include "pinocchio/multibody/model.hpp"
+
+namespace urdf
+{
+  typedef boost::shared_ptr<ModelInterface> ModelInterfacePtr;
+  typedef boost::shared_ptr<const Joint> JointConstPtr;
+  typedef boost::shared_ptr<const Link> LinkConstPtr;
+  typedef boost::shared_ptr<Link> LinkPtr;
+
+  typedef boost::shared_ptr<const Inertial> InertialConstPtr;
+}
+
+namespace se3
+{
+  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());
+  }
+
+  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));
+  }
+
+  enum AxisCartesian { AXIS_X, AXIS_Y, AXIS_Z, AXIS_ERROR };
+  AxisCartesian extractCartesianAxis( const urdf::Vector3 & axis )
+  {
+    if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) )
+      return AXIS_X;
+    else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) )
+      return AXIS_Y;
+    else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) )
+      return AXIS_Z;
+
+    std::cerr << "Axis = (" <<axis.x<<","<<axis.y<<","<<axis.z<<")" << std::endl;
+    assert( false && "Only cartesian axis are accepted." );
+    return AXIS_ERROR;
+  }
+
+  void parseTree( urdf::LinkConstPtr link, Model & model )
+  {
+    urdf::JointConstPtr joint = link->parent_joint;
+
+    // std::cout << " *** " << link->name << "    < attached by joint ";
+    // if(joint)
+    //   std::cout << "#" << link->parent_joint->name << std::endl;
+    // else std::cout << "###ROOT" << std::endl;
+ 
+    assert(link->inertial && "The parser cannot accept trivial mass");
+    const Inertia & Y = convertFromUrdf(*link->inertial);
+    //std::cout << "Inertia: " << Y << std::endl;
+
+    if(joint!=NULL)
+      {
+	assert(link->getParent()!=NULL);
+	Model::Index parent 
+	  = (link->getParent()->parent_joint==NULL) ?
+	  1 : model.getBodyId( link->getParent()->parent_joint->name );
+
+	const SE3 & jointPlacement = convertFromUrdf(joint->parent_to_joint_origin_transform);
+
+	//std::cout << "Parent = " << parent << std::endl;
+	//std::cout << "Placement = " << (Matrix4)jointPlacement << std::endl;
+
+	switch(joint->type)
+	  {
+	  case urdf::Joint::REVOLUTE:
+	  case urdf::Joint::CONTINUOUS: // Revolute with no joint limits
+	    {
+	      AxisCartesian axis = extractCartesianAxis(joint->axis);
+	      switch(axis)
+		{
+		case AXIS_X:
+		  model.addBody( parent, JointModelRX(), jointPlacement, Y, joint->name );
+		  break;
+		case AXIS_Y:
+		  model.addBody( parent, JointModelRY(), jointPlacement, Y, joint->name );
+		  break;
+		case AXIS_Z:
+		  model.addBody( parent, JointModelRZ(), jointPlacement, Y, joint->name );
+		  break;
+		default:
+		  std::cerr << "Bad axis = (" <<joint->axis.x<<","<<joint->axis.y
+			    <<","<<joint->axis.z<<")" << std::endl;
+		  assert(false && "Only X, Y or Z axis are accepted." );
+		  break;
+		}
+	      break;
+	    }
+	  default:
+	    {
+	      std::cerr << "The joint type " << joint->type << " is not supported." << std::endl;
+	      assert(false && "Only revolute joint are accepted." );
+	      break;
+	    }
+	  }
+      }
+    else /* (joint==NULL) */
+      { /* The link is the root of the body. */
+	//std::cout << "Parent = 0 (universe)" << std::endl;
+	model.addBody( 0, JointModelFreeFlyer(), SE3::Identity(), Y, "root" );
+      }
+
+    BOOST_FOREACH(urdf::LinkConstPtr child,link->child_links)
+      {
+	parseTree( child,model );
+      }
+  }  
+
+  Model buildModel( const std::string & filename )
+  {
+    Model model;
+
+    urdf::ModelInterfacePtr urdfTree = urdf::parseURDFFile (filename);
+    parseTree(urdfTree->getRoot(),model);
+    return model;
+  }
+
+} // namespace se3
+
+#endif // ifndef __se3_urdf_hpp__
+
diff --git a/unittest/urdf.cpp b/unittest/urdf.cpp
index 3e077859f..9b08df746 100644
--- a/unittest/urdf.cpp
+++ b/unittest/urdf.cpp
@@ -1,139 +1,14 @@
-#include <urdf_model/model.h>
-#include <urdf_parser/urdf_parser.h>
-
 #include <iostream>
-#include <boost/foreach.hpp>
-#include <Eigen/Core>
-#include <Eigen/Geometry>
-#include "pinocchio/multibody/model.hpp"
-
-namespace urdf
-{
-  typedef boost::shared_ptr<ModelInterface> ModelInterfacePtr;
-  typedef boost::shared_ptr<const Joint> JointConstPtr;
-  typedef boost::shared_ptr<const Link> LinkConstPtr;
-  typedef boost::shared_ptr<Link> LinkPtr;
-
-  typedef boost::shared_ptr<const Inertial> InertialConstPtr;
-}
-
-se3::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 se3::Inertia(Y.mass,com,R*I*R.transpose());
-}
-se3::SE3 convertFromUrdf( const urdf::Pose & M )
-{
-  const urdf::Vector3 & p = M.position;
-  const urdf::Rotation & q = M.rotation;
-  return se3::SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z));
-}
-
-enum AxisCartesian { AXIS_X, AXIS_Y, AXIS_Z };
-AxisCartesian extractCartesianAxis( const urdf::Vector3 & axis )
-{
-  if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) )
-    return AXIS_X;
-  else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) )
-    return AXIS_Y;
-  else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) )
-    return AXIS_Z;
 
-  std::cerr << "Axis = (" <<axis.x<<","<<axis.y<<","<<axis.z<<")" << std::endl;
-  assert( false && "Only cartesian axis are accepted." );
-}
-
-
-void parseTree( urdf::LinkConstPtr link, const urdf::ModelInterfacePtr & model, se3::Model & multibody )
-{
-  urdf::JointConstPtr joint = link->parent_joint;
-
-  std::cout << " *** " << link->name << "    < attached by joint ";
-  if(joint)
-    std::cout << "#" << link->parent_joint->name << std::endl;
-  else std::cout << "###ROOT" << std::endl;
- 
-  assert(link->inertial && "The parser cannot accept trivial mass");
-  const se3::Inertia & Y = convertFromUrdf(*link->inertial);
-  //std::cout << "Inertia: " << Y << std::endl;
-
-  if(joint!=NULL)
-    {
-      assert(link->getParent()!=NULL);
-      se3::Model::Index parent 
-	= (link->getParent()->parent_joint==NULL) ?
-	1 : multibody.getBodyId( link->getParent()->parent_joint->name );
-      const se3::SE3 & jointPlacement = convertFromUrdf(joint->parent_to_joint_origin_transform);
-
-      std::cout << "Parent = " << parent << std::endl;
-      std::cout << "Placement = " << (se3::SE3::Matrix4)jointPlacement << std::endl;
-
-      switch(joint->type)
-	{
-	case urdf::Joint::REVOLUTE:
-	case urdf::Joint::CONTINUOUS: // Revolute with no joint limits
-	  {
-	    AxisCartesian axis = extractCartesianAxis(joint->axis);
-	    switch(axis)
-	      {
-	      case AXIS_X:
-		multibody.addBody( parent, se3::JointModelRX(), jointPlacement, Y, joint->name );
-		break;
-	      case AXIS_Y:
-		multibody.addBody( parent, se3::JointModelRY(), jointPlacement, Y, joint->name );
-		break;
-	      case AXIS_Z:
-		multibody.addBody( parent, se3::JointModelRZ(), jointPlacement, Y, joint->name );
-		break;
-	      default:
-		std::cerr << "Bad axis = (" <<joint->axis.x<<","<<joint->axis.y
-			  <<","<<joint->axis.z<<")" << std::endl;
-		assert(false && "Only X axis are accepted." );
-	      }
-	    break;
-	  }
-	default:
-	  std::cerr << "The joint type " << joint->type << " is not supported." << std::endl;
-	}
-    }
-  else // (joint==NULL)
-    { // The link is the root of the body.
-      std::cout << "Parent = 0 (universe)" << std::endl;
-      multibody.addBody( 0, se3::JointModelFreeFlyer(), se3::SE3::Identity(), Y, "root" );
-    }
-
-
-  BOOST_FOREACH(urdf::LinkConstPtr child,link->child_links)
-    {
-      parseTree( child,model,multibody );
-    }
-}  
-
-
-void buildModel( const std::string & filename )
-{
-  urdf::ModelInterfacePtr model = urdf::parseURDFFile (filename);
-  urdf::LinkConstPtr root = model->getRoot();
-  se3::Model multibody;
-
-  parseTree(root,model,multibody);
-}
+#include "pinocchio/multibody/model.hpp"
+#include "pinocchio/multibody/parser/urdf.hpp"
 
 int main(int argc, const char**argv)
 {
   std::string filename = "/home/nmansard/src/rbdl/rbdl_evaluate_performances/models/simple_humanoid.urdf";
   if(argc>1) filename = argv[1];
 
-  buildModel(filename);
+  se3::Model model = se3::buildModel(filename);
 
   return 0;
 }
-- 
GitLab