From fd2374f5943061098a0d02c3f910cd2fee88ad59 Mon Sep 17 00:00:00 2001 From: Valenza Florian <fvalenza@laas.fr> Date: Tue, 12 Jul 2016 13:20:05 +0200 Subject: [PATCH] [C++][Cmake] Reorganize urdf parsers - moved parsers one level above --- CMakeLists.txt | 41 +- benchmark/timings-geometry.cpp | 5 +- benchmark/timings.cpp | 4 +- src/CMakeLists.txt | 20 +- src/multibody/geometry.hxx | 2 +- src/multibody/parser/urdf-with-geometry.hpp | 98 --- src/multibody/parser/urdf-with-geometry.hxx | 193 ------ src/multibody/parser/urdf.hxx | 624 ------------------ src/multibody/parser/utils.hpp | 49 -- src/{multibody/parser => parsers}/lua.cpp | 4 +- src/{multibody/parser => parsers}/lua.hpp | 0 .../parser => parsers}/lua/lua_tables.cpp | 2 +- .../parser => parsers}/lua/lua_tables.hpp | 0 src/{multibody/parser => parsers}/python.cpp | 2 +- src/{multibody/parser => parsers}/python.hpp | 0 .../parser => parsers}/sample-models.cpp | 2 +- .../parser => parsers}/sample-models.hpp | 0 src/{multibody/parser => parsers}/srdf.hpp | 0 src/{multibody/parser => parsers}/urdf.hpp | 70 +- src/parsers/urdf/geometry.hxx | 224 +++++++ src/parsers/urdf/model.hxx | 584 ++++++++++++++++ src/parsers/urdf/utils.hpp | 104 +++ .../utils.hpp} | 42 +- src/python/model.hpp | 2 +- src/python/parsers.hpp | 7 +- src/tools/file-explorer.hpp | 11 + unittest/aba.cpp | 2 +- unittest/cholesky.cpp | 2 +- unittest/com.cpp | 2 +- unittest/compute-all-terms.cpp | 2 +- unittest/crba.cpp | 2 +- unittest/dynamics.cpp | 2 +- unittest/energy.cpp | 2 +- unittest/frames.cpp | 2 +- unittest/geom.cpp | 5 +- unittest/jacobian.cpp | 2 +- unittest/joint-configurations.cpp | 2 +- unittest/joint.cpp | 4 +- unittest/lua.cpp | 2 +- unittest/python_parser.cpp | 2 +- unittest/rnea.cpp | 2 +- unittest/urdf.cpp | 2 +- unittest/value.cpp | 2 +- utils/pinocchio_read_model.cpp | 6 +- 44 files changed, 1061 insertions(+), 1074 deletions(-) delete mode 100644 src/multibody/parser/urdf-with-geometry.hpp delete mode 100644 src/multibody/parser/urdf-with-geometry.hxx delete mode 100644 src/multibody/parser/urdf.hxx delete mode 100644 src/multibody/parser/utils.hpp rename src/{multibody/parser => parsers}/lua.cpp (98%) rename src/{multibody/parser => parsers}/lua.hpp (100%) rename src/{multibody/parser => parsers}/lua/lua_tables.cpp (99%) rename src/{multibody/parser => parsers}/lua/lua_tables.hpp (100%) rename src/{multibody/parser => parsers}/python.cpp (97%) rename src/{multibody/parser => parsers}/python.hpp (100%) rename src/{multibody/parser => parsers}/sample-models.cpp (99%) rename src/{multibody/parser => parsers}/sample-models.hpp (100%) rename src/{multibody/parser => parsers}/srdf.hpp (100%) rename src/{multibody/parser => parsers}/urdf.hpp (64%) create mode 100644 src/parsers/urdf/geometry.hxx create mode 100644 src/parsers/urdf/model.hxx create mode 100644 src/parsers/urdf/utils.hpp rename src/{multibody/parser/from-collada-to-fcl.hpp => parsers/utils.hpp} (75%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74fa8613a..13f8e5333 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,10 +153,6 @@ SET(${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS multibody/joint/joint-basic-visitors.hxx ) -SET(${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS - multibody/parser/sample-models.hpp - multibody/parser/utils.hpp - ) SET(${PROJECT_NAME}_MULTIBODY_HEADERS multibody/fwd.hpp @@ -166,9 +162,14 @@ SET(${PROJECT_NAME}_MULTIBODY_HEADERS multibody/model.hpp multibody/model.hxx multibody/visitor.hpp - multibody/parser/srdf.hpp ) +SET(${PROJECT_NAME}_PARSERS_HEADERS + parsers/sample-models.hpp + parsers/utils.hpp + parsers/srdf.hpp + ) + SET(${PROJECT_NAME}_ALGORITHM_HEADERS algorithm/aba.hpp algorithm/aba.hxx @@ -213,8 +214,8 @@ IF(BUILD_PYTHON_INTERFACE) python/explog.hpp ) - LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS - multibody/parser/python.hpp + LIST(APPEND ${PROJECT_NAME}_PARSERS_HEADERS + parsers/python.hpp ) ENDIF(BUILD_PYTHON_INTERFACE) @@ -228,16 +229,15 @@ IF(HPP_FCL_FOUND AND BUILD_PYTHON_INTERFACE) ENDIF(HPP_FCL_FOUND AND BUILD_PYTHON_INTERFACE) IF(URDFDOM_FOUND) - LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS - multibody/parser/urdf.hpp - multibody/parser/urdf.hxx + LIST(APPEND ${PROJECT_NAME}_PARSERS_HEADERS + parsers/urdf.hpp + parsers/urdf/model.hxx + parsers/urdf/utils.hpp ) IF(HPP_FCL_FOUND ) - LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS - multibody/parser/from-collada-to-fcl.hpp - multibody/parser/urdf-with-geometry.hpp - multibody/parser/urdf-with-geometry.hxx + LIST(APPEND ${PROJECT_NAME}_PARSERS_HEADERS + parsers/urdf/geometry.hxx ) ENDIF(HPP_FCL_FOUND) @@ -258,9 +258,9 @@ IF(HPP_FCL_FOUND) ENDIF(HPP_FCL_FOUND) IF(LUA5_1_FOUND) - LIST(APPEND ${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS - multibody/parser/lua.hpp - multibody/parser/lua/lua_tables.hpp + LIST(APPEND ${PROJECT_NAME}_PARSERS_HEADERS + parsers/lua.hpp + parsers/lua/lua_tables.hpp ) ADD_DEFINITIONS(-DWITH_LUA) @@ -272,8 +272,8 @@ SET(HEADERS ${${PROJECT_NAME}_TOOLS_HEADERS} ${${PROJECT_NAME}_SPATIAL_HEADERS} ${${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS} - ${${PROJECT_NAME}_MULTIBODY_PARSER_HEADERS} ${${PROJECT_NAME}_MULTIBODY_HEADERS} + ${${PROJECT_NAME}_PARSERS_HEADERS} ${${PROJECT_NAME}_ALGORITHM_HEADERS} ${${PROJECT_NAME}_PYTHON_HEADERS} exception.hpp @@ -289,8 +289,9 @@ MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/math") 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/multibody/parser/lua") +MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/parsers/lua") +MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/parsers") +MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/parsers/urdf") MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/tools") MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/algorithm") MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/pinocchio/python") diff --git a/benchmark/timings-geometry.cpp b/benchmark/timings-geometry.cpp index 66bc7073e..6faa9ab49 100644 --- a/benchmark/timings-geometry.cpp +++ b/benchmark/timings-geometry.cpp @@ -27,12 +27,11 @@ #include "pinocchio/algorithm/compute-all-terms.hpp" #include "pinocchio/algorithm/kinematics.hpp" #include "pinocchio/algorithm/collisions.hpp" -#include "pinocchio/multibody/parser/urdf.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/urdf.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/multibody/geometry.hpp" -#include "pinocchio/multibody/parser/urdf-with-geometry.hpp" #ifdef WITH_HPP_MODEL_URDF #include <hpp/util/debug.hh> #include <hpp/model/device.hh> diff --git a/benchmark/timings.cpp b/benchmark/timings.cpp index e23c37c65..55107238d 100644 --- a/benchmark/timings.cpp +++ b/benchmark/timings.cpp @@ -27,8 +27,8 @@ #include "pinocchio/algorithm/center-of-mass.hpp" #include "pinocchio/algorithm/compute-all-terms.hpp" #include "pinocchio/algorithm/kinematics.hpp" -#include "pinocchio/multibody/parser/urdf.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/urdf.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include <iostream> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38c29f83e..0bc13b375 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,25 +45,29 @@ ENDMACRO(ADD_TARGET_CFLAGS) SET(${PROJECT_NAME}_MULTIBODY_SOURCES multibody/model.cpp - multibody/parser/sample-models.cpp + ) + +SET(${PROJECT_NAME}_PARSERS_SOURCES + parsers/sample-models.cpp ) IF(BUILD_PYTHON_INTERFACE) - SET(${PROJECT_NAME}_MULTIBODY_PARSER_PYTHON_SOURCES - multibody/parser/python.cpp - ) +SET(${PROJECT_NAME}_PARSERS_PYTHON_SOURCES + parsers/python.cpp + ) ENDIF(BUILD_PYTHON_INTERFACE) SET(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_MULTIBODY_SOURCES}) IF(BUILD_PYTHON_INTERFACE) - LIST(APPEND ${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_MULTIBODY_PARSER_PYTHON_SOURCES}) + LIST(APPEND ${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_PARSERS_SOURCES} + ${${PROJECT_NAME}_PARSERS_PYTHON_SOURCES}) ENDIF(BUILD_PYTHON_INTERFACE) IF(LUA5_1_FOUND) SET(${PROJECT_NAME}_MULTIBODY_PARSER_LUA_SOURCES - multibody/parser/lua/lua_tables.cpp - multibody/parser/lua.cpp + parsers/lua/lua_tables.cpp + parsers/lua.cpp ) LIST(APPEND ${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_MULTIBODY_PARSER_LUA_SOURCES}) ENDIF(LUA5_1_FOUND) @@ -145,7 +149,7 @@ IF(BUILD_PYTHON_INTERFACE) python/explog.py ) - FOREACH(python ${PYTHON_FILES}) + FOREACH(python ${PYTHON_FILES}) GET_FILENAME_COMPONENT(pythonFile ${python} NAME) EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK} ${${PROJECT_NAME}_SOURCE_DIR}/src/${python} diff --git a/src/multibody/geometry.hxx b/src/multibody/geometry.hxx index fa1a08b70..7c69015b9 100644 --- a/src/multibody/geometry.hxx +++ b/src/multibody/geometry.hxx @@ -27,7 +27,7 @@ #include "pinocchio/spatial/fcl-pinocchio-conversions.hpp" #include "pinocchio/multibody/model.hpp" #include "pinocchio/multibody/joint/joint-variant.hpp" -#include "pinocchio/multibody/parser/srdf.hpp" +#include "pinocchio/parsers/srdf.hpp" #include <iostream> #include <hpp/fcl/collision_object.h> diff --git a/src/multibody/parser/urdf-with-geometry.hpp b/src/multibody/parser/urdf-with-geometry.hpp deleted file mode 100644 index d0aecf248..000000000 --- a/src/multibody/parser/urdf-with-geometry.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) 2015-2016 CNRS -// -// This file is part of Pinocchio -// Pinocchio is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// Pinocchio is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// Pinocchio If not, see -// <http://www.gnu.org/licenses/>. - -#ifndef __se3_urdf_geom_hpp__ -#define __se3_urdf_geom_hpp__ - -#include <iostream> -#include <exception> -#include "pinocchio/multibody/model.hpp" - -#include <hpp/fcl/collision_object.h> -#include <hpp/fcl/collision.h> -#include <hpp/fcl/shape/geometric_shapes.h> - -#include "pinocchio/multibody/parser/urdf.hpp" - -namespace se3 -{ - namespace urdf - { - - - /** - * @brief Get a fcl::CollisionObject from an urdf geometry, searching - * for it in specified package directories - * - * @param[in] urdf_geometry The input urdf geometry - * @param[in] package_dirs A vector containing the different directories where to search for packages - * @param[out] mesh_path The Absolute path of the mesh currently read - * - * @return The geometry converted as a fcl::CollisionObject - */ - inline fcl::CollisionObject retrieveCollisionGeometry(const boost::shared_ptr < ::urdf::Geometry > urdf_geometry, - const std::vector < std::string > & package_dirs, - std::string & mesh_path); - - - /** - * @brief Recursive procedure for reading the URDF tree, looking for geometries - * This function fill the geometric model whith geometry objects retrieved from the URDF tree - * - * @param[in] link The current URDF link - * @param model The model to which is the GeometryModel associated - * @param model_geom The GeometryModel where the Collision Objects must be added - * @param[in] package_dirs A vector containing the different directories where to search for packages - * @param[in] rootJointAdded If a root joint was added at the begining of the urdf kinematic chain by user when constructing the Model - */ - inline void parseTreeForGeom( ::urdf::LinkConstPtr link, - const Model & model, - GeometryModel & model_geom, - const std::vector<std::string> & package_dirs) throw (std::invalid_argument); - - - - /** - * @brief Build The GeometryModel from a URDF file. Search for meshes - * in the directories specified by the user first and then in - * the environment variable ROS_PACKAGE_PATH - * - * @param[in] model The model of the robot, built with - * urdf::buildModel - * @param[in] filename The URDF complete (absolute) file path - * @param[in] package_dirs A vector containing the different directories - * where to search for models and meshes. - * - * @return The GeometryModel associated to the urdf file and the given Model. - * - */ - inline GeometryModel buildGeom(const Model & model, - const std::string & filename, - const std::vector<std::string> & package_dirs = std::vector<std::string> ()) throw (std::invalid_argument); - - } // namespace urdf - -} // namespace se3 - - -/* --- Details -------------------------------------------------------------- */ -/* --- Details -------------------------------------------------------------- */ -/* --- Details -------------------------------------------------------------- */ -#include "pinocchio/multibody/parser/urdf-with-geometry.hxx" - -#endif // ifndef __se3_urdf_geom_hpp__ - diff --git a/src/multibody/parser/urdf-with-geometry.hxx b/src/multibody/parser/urdf-with-geometry.hxx deleted file mode 100644 index 49dd57a4e..000000000 --- a/src/multibody/parser/urdf-with-geometry.hxx +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) 2015-2016 CNRS -// -// This file is part of Pinocchio -// Pinocchio is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// Pinocchio is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// Pinocchio If not, see -// <http://www.gnu.org/licenses/>. - -#ifndef __se3_urdf_geom_hxx__ -#define __se3_urdf_geom_hxx__ - -#include <urdf_model/model.h> -#include <urdf_parser/urdf_parser.h> - -#include <boost/foreach.hpp> -#include "pinocchio/multibody/model.hpp" - -#include "pinocchio/multibody/parser/from-collada-to-fcl.hpp" -#include <hpp/fcl/mesh_loader/assimp.h> - - - namespace se3 -{ - namespace urdf - { - typedef fcl::BVHModel< fcl::OBBRSS > PolyhedronType; - typedef boost::shared_ptr <PolyhedronType> PolyhedronPtrType; - - inline fcl::CollisionObject retrieveCollisionGeometry(const boost::shared_ptr < ::urdf::Geometry> urdf_geometry, - const std::vector < std::string > & package_dirs, - std::string & mesh_path) - { - boost::shared_ptr < fcl::CollisionGeometry > geometry; - - // Handle the case where collision geometry is a mesh - if (urdf_geometry->type == ::urdf::Geometry::MESH) - { - boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry); - std::string collisionFilename = collisionGeometry->filename; - - mesh_path = convertURDFMeshPathToAbsolutePath(collisionFilename, package_dirs); - - fcl::Vec3f scale = fcl::Vec3f(collisionGeometry->scale.x, - collisionGeometry->scale.y, - collisionGeometry->scale.z - ); - - // Create FCL mesh by parsing Collada file. - PolyhedronPtrType polyhedron (new PolyhedronType); - - fcl::loadPolyhedronFromResource (mesh_path, scale, polyhedron); - geometry = polyhedron; - } - - // Handle the case where collision geometry is a cylinder - // Use FCL capsules for cylinders - else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER) - { - mesh_path = "CYLINDER"; - boost::shared_ptr < ::urdf::Cylinder> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry); - - double radius = collisionGeometry->radius; - double length = collisionGeometry->length; - - // Create fcl capsule geometry. - geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length)); - } - // Handle the case where collision geometry is a box. - else if (urdf_geometry->type == ::urdf::Geometry::BOX) - { - mesh_path = "BOX"; - boost::shared_ptr < ::urdf::Box> collisionGeometry = boost::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) - { - mesh_path = "SPHERE"; - boost::shared_ptr < ::urdf::Sphere> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry); - - double radius = collisionGeometry->radius; - - geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Sphere (radius)); - } - else throw std::runtime_error (std::string ("Unknown geometry type :")); - - if (!geometry) - { - throw std::runtime_error(std::string("The polyhedron retrived is empty")); - } - fcl::CollisionObject collisionObject (geometry, fcl::Transform3f()); - - return collisionObject; - } - - - inline void parseTreeForGeom(::urdf::LinkConstPtr link, - const Model & model, - GeometryModel & geom_model, - const std::vector<std::string> & package_dirs) throw (std::invalid_argument) - { - - std::string mesh_path = ""; - - std::string link_name = link->name; - // start with first link that is not empty - if(link->collision) - { - assert(link->getParent()!=NULL); - if (link->getParent() == NULL) - { - const std::string exception_message (link->name + " - joint information missing."); - throw std::invalid_argument(exception_message); - } - - for (std::vector< boost::shared_ptr< ::urdf::Collision> >::const_iterator i = link->collision_array.begin();i != link->collision_array.end(); ++i) - { - fcl::CollisionObject collision_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path); - SE3 geomPlacement = convertFromUrdf((*i)->origin); - const std::string & collision_object_name = link_name; - geom_model.addCollisionObject(model.getFrameParent(link_name), collision_object, geomPlacement, collision_object_name, mesh_path); - } - } // if(link->collision) - - if(link->visual) - { - assert(link->getParent()!=NULL); - if (link->getParent() == NULL) - { - const std::string exception_message (link->name + " - joint information missing."); - throw std::invalid_argument(exception_message); - } - - for (std::vector< boost::shared_ptr< ::urdf::Visual> >::const_iterator i = link->visual_array.begin(); i != link->visual_array.end(); ++i) - { - fcl::CollisionObject visual_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path); - SE3 geomPlacement = convertFromUrdf((*i)->origin); - const std::string & visual_object_name = link_name; - geom_model.addVisualObject(model.getFrameParent(link_name), visual_object, geomPlacement, visual_object_name, mesh_path); - } - } // if(link->visual) - - - BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links) - { - parseTreeForGeom(child, model, geom_model, package_dirs); - } - - } - - - inline GeometryModel buildGeom(const Model & model, - const std::string & filename, - const std::vector<std::string> & package_dirs) throw(std::invalid_argument) - { - GeometryModel model_geom(model); - - std::vector<std::string> hint_directories(package_dirs); - - // Append the ROS_PACKAGE_PATH - std::vector<std::string> ros_pkg_paths = extractPathFromEnvVar("ROS_PACKAGE_PATH"); - hint_directories.insert(hint_directories.end(), ros_pkg_paths.begin(), ros_pkg_paths.end()); - - if(hint_directories.empty()) - { - throw std::runtime_error("You did not specify any package directory and ROS_PACKAGE_PATH is empty. Geometric parsing will crash"); - } - - ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); - parseTreeForGeom(urdfTree->getRoot(), model, model_geom, hint_directories); - return model_geom; - } - - - } // namespace urdf -} // namespace se3 - -#endif // ifndef __se3_urdf_geom_hxx__ - diff --git a/src/multibody/parser/urdf.hxx b/src/multibody/parser/urdf.hxx deleted file mode 100644 index baab62097..000000000 --- a/src/multibody/parser/urdf.hxx +++ /dev/null @@ -1,624 +0,0 @@ - // -// Copyright (c) 2015-2016 CNRS -// Copyright (c) 2015-2016 Wandercraft, 86 rue de Paris 91400 Orsay, France. -// -// This file is part of Pinocchio -// Pinocchio is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// Pinocchio is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// Pinocchio If not, see -// <http://www.gnu.org/licenses/>. - -#ifndef __se3_urdf_hxx__ -#define __se3_urdf_hxx__ - -#include <urdf_model/model.h> -#include <urdf_parser/urdf_parser.h> - -#include <iostream> -#include <sstream> -#include <iomanip> -#include <boost/foreach.hpp> -#include "pinocchio/multibody/model.hpp" - -#include <exception> - -/// @cond DEV - -namespace se3 -{ - namespace urdf - { - - /// - /// \brief Convert URDF Inertial quantity to Spatial Inertia. - /// - /// \param[in] Y The input URDF Inertia. - /// - /// \return The converted Spatial Inertia se3::Inertia. - /// - inline Inertia convertFromUrdf (const ::urdf::Inertial & Y) - { - const ::urdf::Vector3 & p = Y.origin.position; - const ::urdf::Rotation & q = Y.origin.rotation; - - const Eigen::Vector3d com(p.x,p.y,p.z); - const Eigen::Matrix3d & R = Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(); - - Eigen::Matrix3d I; I << Y.ixx,Y.ixy,Y.ixz - , Y.ixy,Y.iyy,Y.iyz - , Y.ixz,Y.iyz,Y.izz; - return Inertia(Y.mass,com,R*I*R.transpose()); - } - - /// - /// \brief Convert URDF Pose quantity to SE3. - /// - /// \param[in] M The input URDF Pose. - /// - /// \return The converted pose/transform se3::SE3. - /// - inline SE3 convertFromUrdf (const ::urdf::Pose & M) - { - const ::urdf::Vector3 & p = M.position; - const ::urdf::Rotation & q = M.rotation; - return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z)); - } - - /// - /// \brief The four possible cartesian types of an 3D axis. - /// - enum AxisCartesian { AXIS_X, AXIS_Y, AXIS_Z, 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 se3::urdf::AxisCartesian. - /// - inline AxisCartesian extractCartesianAxis (const ::urdf::Vector3 & axis) - { - if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) ) - return AXIS_X; - else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) ) - return AXIS_Y; - else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) ) - return AXIS_Z; - else - return AXIS_UNALIGNED; - } - - /// - /// \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. - /// \param[in] placementOffset The relative placement of the link relative to the closer non fixed joint in the tree. - /// - inline void parseTree (::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, bool verbose) throw (std::invalid_argument) - { - - // Parent joint of the current body - ::urdf::JointConstPtr joint = link->parent_joint; - - // OffSet of the next link. In case we encounter a fixed joint, we need to propagate the offset placement of its attached body to next joint. - SE3 nextPlacementOffset = SE3::Identity(); - - if(joint != NULL) // if the link is not the root of the tree - { - assert(link->getParent()!=NULL); - - const std::string & joint_name = joint->name; - const std::string & link_name = link->name; - const std::string & parent_link_name = link->getParent()->name; - std::string joint_info = ""; - - // check if inertial information is provided - if (!link->inertial && joint->type != ::urdf::Joint::FIXED) - { - const std::string exception_message (link->name + " - spatial inertial information missing."); - throw std::invalid_argument(exception_message); - } - - Model::JointIndex parent_joint_id = (link->getParent()->parent_joint==NULL) ? (model.existJointName("root_joint") ? model.getJointId("root_joint") : 0) : - model.getJointId( link->getParent()->parent_joint->name ); - - // Transformation from the parent link to the joint origin - const SE3 & jointPlacement = placementOffset*convertFromUrdf(joint->parent_to_joint_origin_transform); - - const Inertia & Y = (link->inertial) ? convertFromUrdf(*link->inertial) : - Inertia::Zero(); - - - switch(joint->type) - { - case ::urdf::Joint::FLOATING: - { - joint_info = "joint FreeFlyer"; - - typedef JointModelFreeFlyer::ConfigVector_t ConfigVector_t; - typedef JointModelFreeFlyer::TangentVector_t TangentVector_t; - typedef ConfigVector_t::Scalar Scalar; - - - ConfigVector_t lower_position; - lower_position.fill(std::numeric_limits<Scalar>::min()); - - ConfigVector_t upper_position; - upper_position.fill(std::numeric_limits<Scalar>::max()); - - TangentVector_t max_effort; - max_effort.fill(std::numeric_limits<Scalar>::max()); - - TangentVector_t max_velocity; - max_velocity.fill(std::numeric_limits<Scalar>::max()); - - model.addJointAndBody(parent_joint_id, JointModelFreeFlyer(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name, 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; - } - - Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero()); - AxisCartesian axis = extractCartesianAxis(joint->axis); - - switch(axis) - { - case AXIS_X: - { - joint_info += " along X"; - model.addJointAndBody(parent_joint_id, JointModelRX(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_Y: - { - joint_info += " along Y"; - model.addJointAndBody(parent_joint_id, JointModelRY(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_Z: - { - joint_info += " along Z"; - model.addJointAndBody(parent_joint_id, JointModelRZ(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_UNALIGNED: - { - std::stringstream axis_value; - axis_value << std::setprecision(5); - axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; - joint_info += " unaligned " + axis_value.str(); - - jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z ); - jointAxis.normalize(); - model.addJointAndBody( parent_joint_id, JointModelRevoluteUnaligned(jointAxis), - jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - default: - { - assert(false && "The axis type of the revolute joint is of wrong type."); - break; - } - } - break; - } - case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits - { - joint_info = "joint CONTINUOUS with axis"; - - typedef JointModelRX::ConfigVector_t ConfigVector_t; - typedef JointModelRX::TangentVector_t TangentVector_t; - - TangentVector_t max_effort; - TangentVector_t max_velocity; - ConfigVector_t lower_position; - ConfigVector_t upper_position; - - if (joint->limits) - { - max_effort << joint->limits->effort; - max_velocity << joint->limits->velocity; - lower_position << joint->limits->lower; - upper_position << joint->limits->upper; - } - - Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero()); - AxisCartesian axis = extractCartesianAxis(joint->axis); - - switch(axis) - { - case AXIS_X: - { - joint_info += " along X"; - model.addJointAndBody(parent_joint_id, JointModelRX(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_Y: - { - joint_info += " along Y"; - model.addJointAndBody(parent_joint_id, JointModelRY(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_Z: - { - joint_info += " along Z"; - model.addJointAndBody(parent_joint_id, JointModelRZ(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_UNALIGNED: - { - std::stringstream axis_value; - axis_value << std::setprecision(5); - axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; - joint_info += " unaligned " + axis_value.str(); - - jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z ); - jointAxis.normalize(); - model.addJointAndBody( parent_joint_id, JointModelRevoluteUnaligned(jointAxis), - jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - default: - { - assert(false && "The axis type of the revolute joint is of wrong type."); - break; - } - } - break; - } - case ::urdf::Joint::PRISMATIC: - { - joint_info = "joint PRISMATIC with axis"; - - typedef JointModelRX::ConfigVector_t ConfigVector_t; - typedef JointModelRX::TangentVector_t TangentVector_t; - - TangentVector_t max_effort; - TangentVector_t max_velocity; - ConfigVector_t lower_position; - ConfigVector_t upper_position; - - if (joint->limits) - { - max_effort << joint->limits->effort; - max_velocity << joint->limits->velocity; - lower_position << joint->limits->lower; - upper_position << joint->limits->upper; - } - - AxisCartesian axis = extractCartesianAxis(joint->axis); - switch(axis) - { - case AXIS_X: - { - joint_info += " along X"; - model.addJointAndBody(parent_joint_id, JointModelPX(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_Y: - { - joint_info += " along Y"; - model.addJointAndBody(parent_joint_id, JointModelPY(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name); - break; - } - case AXIS_Z: - { - joint_info += " along Z"; - model.addJointAndBody(parent_joint_id, JointModelPZ(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name ); - break; - } - case AXIS_UNALIGNED: - { - std::stringstream axis_value; - axis_value << std::setprecision(5); - axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; - joint_info += " unaligned " + axis_value.str(); - - Eigen::Vector3d jointAxis(Eigen::Vector3d(joint->axis.x,joint->axis.y,joint->axis.z)); - jointAxis.normalize(); - model.addJointAndBody(parent_joint_id, JointModelPrismaticUnaligned(jointAxis), - jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->name); - - break; - } - default: - { - assert(false && "The axis type of the prismatic joint is of wrong type."); - break; - } - } - break; - } - case ::urdf::Joint::PLANAR: - { - joint_info = "joint PLANAR with normal axis along Z"; - - typedef JointModelPlanar::ConfigVector_t ConfigVector_t; - typedef JointModelPlanar::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; - } - - model.addJointAndBody(parent_joint_id, JointModelPlanar(), jointPlacement, Y, - max_effort, max_velocity, lower_position, upper_position, - joint->name,link->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"; - if (link->inertial) - { - model.appendBodyToJoint(parent_joint_id, jointPlacement, Y, link->name); //Modify the parent inertia in the model - } - - //transformation of the current placement offset - nextPlacementOffset = jointPlacement; - - // Add a frame in the model to keep trace of this fixed joint - model.addFrame(joint->name, parent_joint_id, nextPlacementOffset, FIXED_JOINT); - - //for the children of the current link, set their parent to be - //the the parent of the current link. - BOOST_FOREACH(::urdf::LinkPtr child_link, link->child_links) - { - child_link->setParent(link->getParent() ); - } - break; - } - default: - { - const std::string exception_message ("The type of joint " + joint_name + " is not supported."); - throw std::invalid_argument(exception_message); - break; - } - } - - if (verbose) - { - std::cout << "Adding Body" << std::endl; - std::cout << "\"" << link_name << "\" connected to " << "\"" << parent_link_name << "\" throw joint " << "\"" << joint_name << "\"" << std::endl; - std::cout << "joint type: " << joint_info << std::endl; - std::cout << "joint placement:\n" << jointPlacement; - std::cout << "body info: " << std::endl; - std::cout << " " << "mass: " << Y.mass() << std::endl; - std::cout << " " << "lever: " << Y.lever().transpose() << std::endl; - std::cout << " " << "inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << Y.inertia().data().transpose() << std::endl << std::endl; - } - - } - else if (link->getParent() != NULL) - { - const std::string exception_message (link->name + " - joint information missing."); - throw std::invalid_argument(exception_message); - } - - - BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links) - { - parseTree(child, model, nextPlacementOffset, verbose); - } - } - - - template <typename D> - void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const JointModelBase<D> & root_joint, const bool verbose) throw (std::invalid_argument) - { - // If the root link has no inertial info (because it is a base_link for example), - // we have to merge its inertial info with all its children connected to it with fixed joints - if (!root_link->inertial) - { - // If the root link has only one child - if (root_link->child_links.size() == 1) - { - ::urdf::LinkPtr child_link = root_link->child_links[0]; - assert(child_link->inertial != NULL && "Inertial information missing for parsing the root link."); - const Inertia & Y = convertFromUrdf(*child_link->inertial); - model.addJointAndBody(0, root_joint, SE3::Identity(), Y, "root_joint", child_link->name); - - // Change the name of the parent joint in the URDF tree - child_link->parent_joint->name = "root_joint"; - - BOOST_FOREACH(::urdf::LinkConstPtr child, child_link->child_links) - { - parseTree(child, model, SE3::Identity(), verbose); - } - } - else - { - const std::string exception_message (root_link->name + " has no inertial information and has more than one child link. It corresponds to a disjoint tree."); - throw std::invalid_argument(exception_message); - } - - } - else // otherwise, it is a plain body with inertial info. It processes as usual. - { - const Inertia & Y = convertFromUrdf(*root_link->inertial); - model.addJointAndBody(0, root_joint, SE3::Identity(), Y , "root_joint", root_link->name); - - BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links) - { - parseTree(child, model, SE3::Identity(), verbose); - } - } - - } - - - template <typename D> - Model buildModel (const std::string & filename, const JointModelBase<D> & root_joint, bool verbose) throw (std::invalid_argument) - { - Model model; - - ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); - if (urdfTree) - parseRootTree(urdfTree->getRoot(), model, root_joint, verbose); - else - { - const std::string exception_message ("The file " + filename + " does not contain a valid URDF model."); - throw std::invalid_argument(exception_message); - } - - return model; - } - - void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const bool verbose) throw (std::invalid_argument) - { - // If the root link has no inertial info, it may be because it is a base_link. - // In this case, we look for its child links which indeed contribute to the dynamics, they are not fixed to the universe. - // TODO: it may be necessary to compute joint placement variable instead of setting it to SE3::Identity() - if (!root_link->inertial) - { - typedef std::vector< ::urdf::LinkPtr > LinkSharedPtrVector_t; - LinkSharedPtrVector_t movable_child_links; - LinkSharedPtrVector_t direct_child_links(root_link->child_links); - LinkSharedPtrVector_t next_direct_child_links; // next child to visit - LinkSharedPtrVector_t pathologic_child_links; // children which have inertial info but rigidly attached to the world - do - { - next_direct_child_links.clear(); - BOOST_FOREACH(::urdf::LinkPtr child, direct_child_links) - { - if (child->parent_joint->type != ::urdf::Joint::FIXED) - movable_child_links.push_back(child); - else - { - if (child->inertial) - pathologic_child_links.push_back(child); - next_direct_child_links.insert (next_direct_child_links.end(), child->child_links.begin(), child->child_links.end()); - } - - } - direct_child_links = next_direct_child_links; - } - while (!direct_child_links.empty()); - - if (!pathologic_child_links.empty()) - { - std::cout << "[INFO] The links:" << std::endl; - for (LinkSharedPtrVector_t::iterator it = pathologic_child_links.begin(); - it < pathologic_child_links.end(); ++it) - { - std::cout << " - " << (*it)->name << std::endl; - } - std::cout << "are fixed regarding to the universe (base_link) and convey inertial info. They won't affect the dynamics of the output model. Maybe, a root joint is missing connecting this links to the universe." << std::endl; - - } - - BOOST_FOREACH(::urdf::LinkPtr child, movable_child_links) - { - child->getParent()->parent_joint->name = model.names[0]; - parseTree(child, model, SE3::Identity(), verbose); - } - - } - else // Otherwise, we have to rase an exception because the first link will no be added to the model. - // It seems a root joint is missing. - { - std::cout << "[INFO] The root link " << root_link->name << " of the model tree contains inertial information. It seems that a root joint is missing connecting this root link to the universe. The root link won't affect the dynamics of the model." << std::endl; - - BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links) - { - parseTree(child, model, SE3::Identity(), verbose); - } - } - - - } - - - inline Model buildModel (const std::string & filename, const bool verbose) throw (std::invalid_argument) - { - Model model; - - ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); - if (urdfTree) - parseRootTree(urdfTree->getRoot(),model,verbose); - else - { - const std::string exception_message ("The file " + filename + " does not contain a valid URDF model."); - throw std::invalid_argument(exception_message); - } - - return model; - } - - } // namespace urdf - -} // namespace se3 - -/// @endcond - -#endif // ifndef __se3_urdf_hxx__ diff --git a/src/multibody/parser/utils.hpp b/src/multibody/parser/utils.hpp deleted file mode 100644 index 20cc54329..000000000 --- a/src/multibody/parser/utils.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) 2015 CNRS -// -// This file is part of Pinocchio -// Pinocchio is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// Pinocchio is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// Pinocchio If not, see -// <http://www.gnu.org/licenses/>. - -#include <iostream> - -namespace se3 -{ - /// - /// \brief Supported model file extensions - /// - enum ModelFileExtensionType{ - UNKNOWN = 0, - URDF, - LUA - }; - - /// - /// \brief Extract the type of the given model file according to its extension - /// - /// \param[in] filemane The complete path to the model file. - /// - /// \return The type of the extension of the model file - /// - ModelFileExtensionType checkModelFileExtension (const std::string & filename) - { - const std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if (extension == "urdf") - return URDF; - else if (extension == "lua") - return LUA; - - return UNKNOWN; - } -} // namespace se3 diff --git a/src/multibody/parser/lua.cpp b/src/parsers/lua.cpp similarity index 98% rename from src/multibody/parser/lua.cpp rename to src/parsers/lua.cpp index a45d7cdff..9a5a558ac 100644 --- a/src/multibody/parser/lua.cpp +++ b/src/parsers/lua.cpp @@ -1,6 +1,6 @@ -#include "pinocchio/multibody/parser/lua/lua_tables.hpp" -#include "pinocchio/multibody/parser/lua.hpp" +#include "pinocchio/parsers/lua/lua_tables.hpp" +#include "pinocchio/parsers/lua.hpp" #include <lua.hpp> #include <iostream> diff --git a/src/multibody/parser/lua.hpp b/src/parsers/lua.hpp similarity index 100% rename from src/multibody/parser/lua.hpp rename to src/parsers/lua.hpp diff --git a/src/multibody/parser/lua/lua_tables.cpp b/src/parsers/lua/lua_tables.cpp similarity index 99% rename from src/multibody/parser/lua/lua_tables.cpp rename to src/parsers/lua/lua_tables.cpp index 11f4b6235..e95040b61 100644 --- a/src/multibody/parser/lua/lua_tables.cpp +++ b/src/parsers/lua/lua_tables.cpp @@ -25,7 +25,7 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pinocchio/multibody/parser/lua/lua_tables.hpp" +#include "pinocchio/parsers/lua/lua_tables.hpp" #include <assert.h> #include <iostream> diff --git a/src/multibody/parser/lua/lua_tables.hpp b/src/parsers/lua/lua_tables.hpp similarity index 100% rename from src/multibody/parser/lua/lua_tables.hpp rename to src/parsers/lua/lua_tables.hpp diff --git a/src/multibody/parser/python.cpp b/src/parsers/python.cpp similarity index 97% rename from src/multibody/parser/python.cpp rename to src/parsers/python.cpp index 3f1b48580..b88404fbd 100644 --- a/src/multibody/parser/python.cpp +++ b/src/parsers/python.cpp @@ -16,7 +16,7 @@ // <http://www.gnu.org/licenses/>. -#include "pinocchio/multibody/parser/python.hpp" +#include "pinocchio/parsers/python.hpp" #include "pinocchio/python/model.hpp" #include <iostream> diff --git a/src/multibody/parser/python.hpp b/src/parsers/python.hpp similarity index 100% rename from src/multibody/parser/python.hpp rename to src/parsers/python.hpp diff --git a/src/multibody/parser/sample-models.cpp b/src/parsers/sample-models.cpp similarity index 99% rename from src/multibody/parser/sample-models.cpp rename to src/parsers/sample-models.cpp index d9af943db..ddb89526b 100644 --- a/src/multibody/parser/sample-models.cpp +++ b/src/parsers/sample-models.cpp @@ -16,7 +16,7 @@ // Pinocchio If not, see // <http://www.gnu.org/licenses/>. -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #ifdef WITH_HPP_FCL #include <hpp/fcl/shape/geometric_shapes.h> diff --git a/src/multibody/parser/sample-models.hpp b/src/parsers/sample-models.hpp similarity index 100% rename from src/multibody/parser/sample-models.hpp rename to src/parsers/sample-models.hpp diff --git a/src/multibody/parser/srdf.hpp b/src/parsers/srdf.hpp similarity index 100% rename from src/multibody/parser/srdf.hpp rename to src/parsers/srdf.hpp diff --git a/src/multibody/parser/urdf.hpp b/src/parsers/urdf.hpp similarity index 64% rename from src/multibody/parser/urdf.hpp rename to src/parsers/urdf.hpp index 72c8d3245..8e63f552a 100644 --- a/src/multibody/parser/urdf.hpp +++ b/src/parsers/urdf.hpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2015-2016 CNRS +// Copyright (c) 2016 CNRS // Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France. // // This file is part of Pinocchio @@ -16,8 +16,8 @@ // Pinocchio If not, see // <http://www.gnu.org/licenses/>. -#ifndef __se3_urdf_hpp__ -#define __se3_urdf_hpp__ +#ifndef __se3_parsers_urdf_hpp__ +#define __se3_parsers_urdf_hpp__ #include <urdf_model/model.h> #include <urdf_parser/urdf_parser.h> @@ -31,6 +31,12 @@ #include <exception> #include <limits> +#ifdef WITH_HPP_FCL +#include <hpp/fcl/collision_object.h> +#include <hpp/fcl/collision.h> +#include <hpp/fcl/shape/geometric_shapes.h> +#endif + namespace urdf { typedef boost::shared_ptr<ModelInterface> ModelInterfacePtr; @@ -45,34 +51,6 @@ namespace se3 namespace urdf { - /// - /// \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. - /// - void parseRootTree (::urdf::LinkConstPtr link, - Model & model, - const bool verbose = false) throw (std::invalid_argument); - - - /// - /// \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 D> - void parseRootTree (::urdf::LinkConstPtr link, - Model & model, - const JointModelBase<D> & root_joint, - const bool verbose = false) throw (std::invalid_argument); - /// /// \brief Build the model from a URDF file with a particular joint as root of the model tree. /// @@ -98,12 +76,38 @@ namespace se3 inline Model buildModel (const std::string & filename, const bool verbose = false) throw (std::invalid_argument); +#ifdef WITH_HPP_FCL + + /** + * @brief Build The GeometryModel from a URDF file. Search for meshes + * in the directories specified by the user first and then in + * the environment variable ROS_PACKAGE_PATH + * + * @param[in] model The model of the robot, built with + * urdf::buildModel + * @param[in] filename The URDF complete (absolute) file path + * @param[in] package_dirs A vector containing the different directories + * where to search for models and meshes, typically + * obtained from calling se3::rosPaths() + * + * @return The GeometryModel associated to the urdf file and the given Model. + * + */ + inline GeometryModel buildGeom(const Model & model, + const std::string & filename, + const std::vector<std::string> & package_dirs = std::vector<std::string> ()) throw (std::invalid_argument); + +#endif + } // namespace urdf } // namespace se3 /* --- Details -------------------------------------------------------------- */ /* --- Details -------------------------------------------------------------- */ /* --- Details -------------------------------------------------------------- */ -#include "pinocchio/multibody/parser/urdf.hxx" +#include "pinocchio/parsers/urdf/model.hxx" +#ifdef WITH_HPP_FCL +#include "pinocchio/parsers/urdf/geometry.hxx" +#endif -#endif // ifndef __se3_urdf_hpp__ +#endif // ifndef __se3_parsers_urdf_hpp__ diff --git a/src/parsers/urdf/geometry.hxx b/src/parsers/urdf/geometry.hxx new file mode 100644 index 000000000..c158e948a --- /dev/null +++ b/src/parsers/urdf/geometry.hxx @@ -0,0 +1,224 @@ +// +// Copyright (c) 2015 - 2016 CNRS +// +// This file is part of Pinocchio +// Pinocchio is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation, either version +// 3 of the License, or (at your option) any later version. +// +// Pinocchio is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Lesser Public License for more details. You should have +// received a copy of the GNU Lesser General Public License along with +// Pinocchio If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef __se3_parsers_urdf_geometry_hxx__ +#define __se3_parsers_urdf_geometry_hxx__ + +#include <urdf_model/model.h> +#include <urdf_parser/urdf_parser.h> + +#include <iostream> +#include <sstream> +#include <iomanip> +#include <boost/foreach.hpp> + +#include "pinocchio/parsers/urdf/utils.hpp" +#include "pinocchio/parsers/utils.hpp" +#include "pinocchio/multibody/model.hpp" + +#include <hpp/fcl/mesh_loader/assimp.h> + +#include <exception> + +namespace se3 +{ + namespace urdf + { + namespace details + { + typedef fcl::BVHModel< fcl::OBBRSS > PolyhedronType; + typedef boost::shared_ptr <PolyhedronType> PolyhedronPtrType; + + /** + * @brief Get a fcl::CollisionObject from an urdf geometry, searching + * for it in specified package directories + * + * @param[in] urdf_geometry The input urdf geometry + * @param[in] package_dirs A vector containing the different directories where to search for packages + * @param[out] mesh_path The Absolute path of the mesh currently read + * + * @return The geometry converted as a fcl::CollisionObject + */ + inline fcl::CollisionObject retrieveCollisionGeometry(const boost::shared_ptr < ::urdf::Geometry> urdf_geometry, + const std::vector < std::string > & package_dirs, + std::string & mesh_path) + { + boost::shared_ptr < fcl::CollisionGeometry > geometry; + + // Handle the case where collision geometry is a mesh + if (urdf_geometry->type == ::urdf::Geometry::MESH) + { + boost::shared_ptr < ::urdf::Mesh> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry); + std::string collisionFilename = collisionGeometry->filename; + + mesh_path = convertURDFMeshPathToAbsolutePath(collisionFilename, package_dirs); + + fcl::Vec3f scale = fcl::Vec3f(collisionGeometry->scale.x, + collisionGeometry->scale.y, + collisionGeometry->scale.z + ); + + // Create FCL mesh by parsing Collada file. + PolyhedronPtrType polyhedron (new PolyhedronType); + + fcl::loadPolyhedronFromResource (mesh_path, scale, polyhedron); + geometry = polyhedron; + } + + // Handle the case where collision geometry is a cylinder + // Use FCL capsules for cylinders + else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER) + { + mesh_path = "CYLINDER"; + boost::shared_ptr < ::urdf::Cylinder> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry); + + double radius = collisionGeometry->radius; + double length = collisionGeometry->length; + + // Create fcl capsule geometry. + geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length)); + } + // Handle the case where collision geometry is a box. + else if (urdf_geometry->type == ::urdf::Geometry::BOX) + { + mesh_path = "BOX"; + boost::shared_ptr < ::urdf::Box> collisionGeometry = boost::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) + { + mesh_path = "SPHERE"; + boost::shared_ptr < ::urdf::Sphere> collisionGeometry = boost::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry); + + double radius = collisionGeometry->radius; + + geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Sphere (radius)); + } + else throw std::runtime_error (std::string ("Unknown geometry type :")); + + if (!geometry) + { + throw std::runtime_error(std::string("The polyhedron retrived is empty")); + } + fcl::CollisionObject collisionObject (geometry, fcl::Transform3f()); + + return collisionObject; + } + + + /** + * @brief Recursive procedure for reading the URDF tree, looking for geometries + * This function fill the geometric model whith geometry objects retrieved from the URDF tree + * + * @param[in] link The current URDF link + * @param model The model to which is the GeometryModel associated + * @param model_geom The GeometryModel where the Collision Objects must be added + * @param[in] package_dirs A vector containing the different directories where to search for packages + * @param[in] rootJointAdded If a root joint was added at the begining of the urdf kinematic chain by user when constructing the Model + */ + inline void parseTreeForGeom(::urdf::LinkConstPtr link, + const Model & model, + GeometryModel & geom_model, + const std::vector<std::string> & package_dirs) throw (std::invalid_argument) + { + + std::string mesh_path = ""; + + std::string link_name = link->name; + // start with first link that is not empty + if(link->collision) + { + assert(link->getParent()!=NULL); + if (link->getParent() == NULL) + { + const std::string exception_message (link->name + " - joint information missing."); + throw std::invalid_argument(exception_message); + } + + for (std::vector< boost::shared_ptr< ::urdf::Collision> >::const_iterator i = link->collision_array.begin();i != link->collision_array.end(); ++i) + { + fcl::CollisionObject collision_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path); + SE3 geomPlacement = convertFromUrdf((*i)->origin); + const std::string & collision_object_name = link_name; + geom_model.addCollisionObject(model.getFrameParent(link_name), collision_object, geomPlacement, collision_object_name, mesh_path); + } + } // if(link->collision) + + if(link->visual) + { + assert(link->getParent()!=NULL); + if (link->getParent() == NULL) + { + const std::string exception_message (link->name + " - joint information missing."); + throw std::invalid_argument(exception_message); + } + + for (std::vector< boost::shared_ptr< ::urdf::Visual> >::const_iterator i = link->visual_array.begin(); i != link->visual_array.end(); ++i) + { + fcl::CollisionObject visual_object = retrieveCollisionGeometry((*i)->geometry, package_dirs, mesh_path); + SE3 geomPlacement = convertFromUrdf((*i)->origin); + const std::string & visual_object_name = link_name; + geom_model.addVisualObject(model.getFrameParent(link_name), visual_object, geomPlacement, visual_object_name, mesh_path); + } + } // if(link->visual) + + + BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links) + { + parseTreeForGeom(child, model, geom_model, package_dirs); + } + + } + + + } // namespace details + + + + inline GeometryModel buildGeom(const Model & model, + const std::string & filename, + const std::vector<std::string> & package_dirs) throw(std::invalid_argument) + { + GeometryModel model_geom(model); + + 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()); + + if(hint_directories.empty()) + { + throw std::runtime_error("You did not specify any package directory and ROS_PACKAGE_PATH is empty. Geometric parsing will crash"); + } + + ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); + details::parseTreeForGeom(urdfTree->getRoot(), model, model_geom, hint_directories); + return model_geom; + } + + } // namespace urdf +} // namespace se3 + + +#endif // __se3_parsers_urdf_geometry_hxx__ diff --git a/src/parsers/urdf/model.hxx b/src/parsers/urdf/model.hxx new file mode 100644 index 000000000..17573ef02 --- /dev/null +++ b/src/parsers/urdf/model.hxx @@ -0,0 +1,584 @@ +// +// Copyright (c) 2016 CNRS +// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France. +// +// This file is part of Pinocchio +// Pinocchio is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation, either version +// 3 of the License, or (at your option) any later version. +// +// Pinocchio is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Lesser Public License for more details. You should have +// received a copy of the GNU Lesser General Public License along with +// Pinocchio If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef __se3_parsers_urdf_model_hxx__ +#define __se3_parsers_urdf_model_hxx__ + +#include <urdf_model/model.h> +#include <urdf_parser/urdf_parser.h> + +#include <iostream> +#include <sstream> +#include <iomanip> +#include <boost/foreach.hpp> + +#include "pinocchio/parsers/urdf/utils.hpp" +#include "pinocchio/multibody/model.hpp" + +#include <exception> + +namespace se3 +{ + namespace urdf + { + namespace details + { +/// +/// \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. +/// \param[in] placementOffset The relative placement of the link relative to the closer non fixed joint in the tree. +/// +inline void parseTree (::urdf::LinkConstPtr link, Model & model, const SE3 & placementOffset, bool verbose) throw (std::invalid_argument) +{ + + // Parent joint of the current body + ::urdf::JointConstPtr joint = link->parent_joint; + + // OffSet of the next link. In case we encounter a fixed joint, we need to propagate the offset placement of its attached body to next joint. + SE3 nextPlacementOffset = SE3::Identity(); + + if(joint != NULL) // if the link is not the root of the tree + { + assert(link->getParent()!=NULL); + + const std::string & joint_name = joint->name; + const std::string & link_name = link->name; + const std::string & parent_link_name = link->getParent()->name; + std::string joint_info = ""; + + // check if inertial information is provided + if (!link->inertial && joint->type != ::urdf::Joint::FIXED) + { + const std::string exception_message (link->name + " - spatial inertial information missing."); + throw std::invalid_argument(exception_message); + } + + Model::JointIndex parent_joint_id = (link->getParent()->parent_joint==NULL) ? (model.existJointName("root_joint") ? model.getJointId("root_joint") : 0) : + model.getJointId( link->getParent()->parent_joint->name ); + + // Transformation from the parent link to the joint origin + const SE3 & jointPlacement = placementOffset*convertFromUrdf(joint->parent_to_joint_origin_transform); + + const Inertia & Y = (link->inertial) ? convertFromUrdf(*link->inertial) : + Inertia::Zero(); + + + switch(joint->type) + { + case ::urdf::Joint::FLOATING: + { + joint_info = "joint FreeFlyer"; + + typedef JointModelFreeFlyer::ConfigVector_t ConfigVector_t; + typedef JointModelFreeFlyer::TangentVector_t TangentVector_t; + typedef ConfigVector_t::Scalar Scalar_t; + + + ConfigVector_t lower_position; + lower_position.fill(std::numeric_limits<Scalar_t>::min()); + + ConfigVector_t upper_position; + upper_position.fill(std::numeric_limits<Scalar_t>::max()); + + TangentVector_t max_effort; + max_effort.fill(std::numeric_limits<Scalar_t>::max()); + + TangentVector_t max_velocity; + max_velocity.fill(std::numeric_limits<Scalar_t>::max()); + + model.addJointAndBody(parent_joint_id, JointModelFreeFlyer(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name, 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; + } + + Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero()); + AxisCartesian axis = extractCartesianAxis(joint->axis); + + switch(axis) + { + case AXIS_X: + { + joint_info += " along X"; + model.addJointAndBody(parent_joint_id, JointModelRX(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_Y: + { + joint_info += " along Y"; + model.addJointAndBody(parent_joint_id, JointModelRY(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_Z: + { + joint_info += " along Z"; + model.addJointAndBody(parent_joint_id, JointModelRZ(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_UNALIGNED: + { + std::stringstream axis_value; + axis_value << std::setprecision(5); + axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; + joint_info += " unaligned " + axis_value.str(); + + jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z ); + jointAxis.normalize(); + model.addJointAndBody( parent_joint_id, JointModelRevoluteUnaligned(jointAxis), + jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + default: + { + assert(false && "The axis type of the revolute joint is of wrong type."); + break; + } + } + break; + } + case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits + { + joint_info = "joint CONTINUOUS with axis"; + + typedef JointModelRX::ConfigVector_t ConfigVector_t; + typedef JointModelRX::TangentVector_t TangentVector_t; + + TangentVector_t max_effort; + TangentVector_t max_velocity; + ConfigVector_t lower_position; + ConfigVector_t upper_position; + + if (joint->limits) + { + max_effort << joint->limits->effort; + max_velocity << joint->limits->velocity; + lower_position << joint->limits->lower; + upper_position << joint->limits->upper; + } + + Eigen::Vector3d jointAxis(Eigen::Vector3d::Zero()); + AxisCartesian axis = extractCartesianAxis(joint->axis); + + switch(axis) + { + case AXIS_X: + { + joint_info += " along X"; + model.addJointAndBody(parent_joint_id, JointModelRX(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_Y: + { + joint_info += " along Y"; + model.addJointAndBody(parent_joint_id, JointModelRY(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_Z: + { + joint_info += " along Z"; + model.addJointAndBody(parent_joint_id, JointModelRZ(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_UNALIGNED: + { + std::stringstream axis_value; + axis_value << std::setprecision(5); + axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; + joint_info += " unaligned " + axis_value.str(); + + jointAxis = Eigen::Vector3d( joint->axis.x,joint->axis.y,joint->axis.z ); + jointAxis.normalize(); + model.addJointAndBody( parent_joint_id, JointModelRevoluteUnaligned(jointAxis), + jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + default: + { + assert(false && "The axis type of the revolute joint is of wrong type."); + break; + } + } + break; + } + case ::urdf::Joint::PRISMATIC: + { + joint_info = "joint PRISMATIC with axis"; + + typedef JointModelRX::ConfigVector_t ConfigVector_t; + typedef JointModelRX::TangentVector_t TangentVector_t; + + TangentVector_t max_effort; + TangentVector_t max_velocity; + ConfigVector_t lower_position; + ConfigVector_t upper_position; + + if (joint->limits) + { + max_effort << joint->limits->effort; + max_velocity << joint->limits->velocity; + lower_position << joint->limits->lower; + upper_position << joint->limits->upper; + } + + AxisCartesian axis = extractCartesianAxis(joint->axis); + switch(axis) + { + case AXIS_X: + { + joint_info += " along X"; + model.addJointAndBody(parent_joint_id, JointModelPX(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_Y: + { + joint_info += " along Y"; + model.addJointAndBody(parent_joint_id, JointModelPY(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name); + break; + } + case AXIS_Z: + { + joint_info += " along Z"; + model.addJointAndBody(parent_joint_id, JointModelPZ(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name ); + break; + } + case AXIS_UNALIGNED: + { + std::stringstream axis_value; + axis_value << std::setprecision(5); + axis_value << "(" << joint->axis.x <<"," << joint->axis.y << "," << joint->axis.z << ")"; + joint_info += " unaligned " + axis_value.str(); + + Eigen::Vector3d jointAxis(Eigen::Vector3d(joint->axis.x,joint->axis.y,joint->axis.z)); + jointAxis.normalize(); + model.addJointAndBody(parent_joint_id, JointModelPrismaticUnaligned(jointAxis), + jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->name); + + break; + } + default: + { + assert(false && "The axis type of the prismatic joint is of wrong type."); + break; + } + } + break; + } + case ::urdf::Joint::PLANAR: + { + joint_info = "joint PLANAR with normal axis along Z"; + + typedef JointModelPlanar::ConfigVector_t ConfigVector_t; + typedef JointModelPlanar::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; + } + + model.addJointAndBody(parent_joint_id, JointModelPlanar(), jointPlacement, Y, + max_effort, max_velocity, lower_position, upper_position, + joint->name,link->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"; + if (link->inertial) + { + model.appendBodyToJoint(parent_joint_id, jointPlacement, Y, link->name); //Modify the parent inertia in the model + } + + //transformation of the current placement offset + nextPlacementOffset = jointPlacement; + + // Add a frame in the model to keep trace of this fixed joint + model.addFrame(joint->name, parent_joint_id, nextPlacementOffset, FIXED_JOINT); + + //for the children of the current link, set their parent to be + //the the parent of the current link. + BOOST_FOREACH(::urdf::LinkPtr child_link, link->child_links) + { + child_link->setParent(link->getParent() ); + } + break; + } + default: + { + const std::string exception_message ("The type of joint " + joint_name + " is not supported."); + throw std::invalid_argument(exception_message); + break; + } + } + + if (verbose) + { + std::cout << "Adding Body" << std::endl; + std::cout << "\"" << link_name << "\" connected to " << "\"" << parent_link_name << "\" throw joint " << "\"" << joint_name << "\"" << std::endl; + std::cout << "joint type: " << joint_info << std::endl; + std::cout << "joint placement:\n" << jointPlacement; + std::cout << "body info: " << std::endl; + std::cout << " " << "mass: " << Y.mass() << std::endl; + std::cout << " " << "lever: " << Y.lever().transpose() << std::endl; + std::cout << " " << "inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << Y.inertia().data().transpose() << std::endl << std::endl; + } + + } + else if (link->getParent() != NULL) + { + const std::string exception_message (link->name + " - joint information missing."); + throw std::invalid_argument(exception_message); + } + + + BOOST_FOREACH(::urdf::LinkConstPtr child,link->child_links) + { + parseTree(child, model, nextPlacementOffset, verbose); + } +} + + + +/// +/// \brief Parse a tree with a specific root joint linking the model to the environment. +/// The function returns an exception as soon as a necessary Inertia or Joint information are missing. +/// +/// \param[in] link The current URDF link. +/// \param[in] model The model where the link must be added. +/// \param[in] verbose Print parsing info. +/// +void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const bool verbose) throw (std::invalid_argument) +{ + // If the root link has no inertial info, it may be because it is a base_link. + // In this case, we look for its child links which indeed contribute to the dynamics, they are not fixed to the universe. + // TODO: it may be necessary to compute joint placement variable instead of setting it to SE3::Identity() + if (!root_link->inertial) + { + typedef std::vector< ::urdf::LinkPtr > LinkSharedPtrVector_t; + LinkSharedPtrVector_t movable_child_links; + LinkSharedPtrVector_t direct_child_links(root_link->child_links); + LinkSharedPtrVector_t next_direct_child_links; // next child to visit + LinkSharedPtrVector_t pathologic_child_links; // children which have inertial info but rigidly attached to the world + do + { + next_direct_child_links.clear(); + BOOST_FOREACH(::urdf::LinkPtr child, direct_child_links) + { + if (child->parent_joint->type != ::urdf::Joint::FIXED) + movable_child_links.push_back(child); + else + { + if (child->inertial) + pathologic_child_links.push_back(child); + next_direct_child_links.insert (next_direct_child_links.end(), child->child_links.begin(), child->child_links.end()); + } + + } + direct_child_links = next_direct_child_links; + } + while (!direct_child_links.empty()); + + if (!pathologic_child_links.empty()) + { + std::cout << "[INFO] The links:" << std::endl; + for (LinkSharedPtrVector_t::iterator it = pathologic_child_links.begin(); + it < pathologic_child_links.end(); ++it) + { + std::cout << " - " << (*it)->name << std::endl; + } + std::cout << "are fixed regarding to the universe (base_link) and convey inertial info. They won't affect the dynamics of the output model. Maybe, a root joint is missing connecting this links to the universe." << std::endl; + + } + + BOOST_FOREACH(::urdf::LinkPtr child, movable_child_links) + { + child->getParent()->parent_joint->name = model.names[0]; + parseTree(child, model, SE3::Identity(), verbose); + } + + } + else // Otherwise, we have to rase an exception because the first link will no be added to the model. + // It seems a root joint is missing. + { + std::cout << "[INFO] The root link " << root_link->name << " of the model tree contains inertial information. It seems that a root joint is missing connecting this root link to the universe. The root link won't affect the dynamics of the model." << std::endl; + + BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links) + { + parseTree(child, model, SE3::Identity(), verbose); + } + } + + +} + +/// +/// \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 D> +void parseRootTree (::urdf::LinkConstPtr root_link, Model & model, const JointModelBase<D> & root_joint, const bool verbose) throw (std::invalid_argument) +{ + // If the root link has no inertial info (because it is a base_link for example), + // we have to merge its inertial info with all its children connected to it with fixed joints + if (!root_link->inertial) + { + // If the root link has only one child + if (root_link->child_links.size() == 1) + { + ::urdf::LinkPtr child_link = root_link->child_links[0]; + assert(child_link->inertial != NULL && "Inertial information missing for parsing the root link."); + const Inertia & Y = convertFromUrdf(*child_link->inertial); + model.addJointAndBody(0, root_joint, SE3::Identity(), Y, "root_joint", child_link->name); + + // Change the name of the parent joint in the URDF tree + child_link->parent_joint->name = "root_joint"; + + BOOST_FOREACH(::urdf::LinkConstPtr child, child_link->child_links) + { + parseTree(child, model, SE3::Identity(), verbose); + } + } + else + { + const std::string exception_message (root_link->name + " has no inertial information and has more than one child link. It corresponds to a disjoint tree."); + throw std::invalid_argument(exception_message); + } + + } + else // otherwise, it is a plain body with inertial info. It processes as usual. + { + const Inertia & Y = convertFromUrdf(*root_link->inertial); + model.addJointAndBody(0, root_joint, SE3::Identity(), Y , "root_joint", root_link->name); + + BOOST_FOREACH(::urdf::LinkPtr child, root_link->child_links) + { + parseTree(child, model, SE3::Identity(), verbose); + } + } + +} + } // namespace details + +template <typename D> +Model buildModel (const std::string & filename, const JointModelBase<D> & root_joint, bool verbose) throw (std::invalid_argument) +{ + Model model; + + ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); + if (urdfTree) + details::parseRootTree(urdfTree->getRoot(), model, root_joint, verbose); + else + { + const std::string exception_message ("The file " + filename + " does not contain a valid URDF model."); + throw std::invalid_argument(exception_message); + } + + return model; +} + + + + +inline Model buildModel (const std::string & filename, const bool verbose) throw (std::invalid_argument) +{ + Model model; + + ::urdf::ModelInterfacePtr urdfTree = ::urdf::parseURDFFile (filename); + if (urdfTree) + details::parseRootTree(urdfTree->getRoot(),model,verbose); + else + { + const std::string exception_message ("The file " + filename + " does not contain a valid URDF model."); + throw std::invalid_argument(exception_message); + } + + return model; +} + + } // namespace urdf +} // namespace se3 + + +#endif // __se3_parsers_urdf_model_hxx__ diff --git a/src/parsers/urdf/utils.hpp b/src/parsers/urdf/utils.hpp new file mode 100644 index 000000000..1b00571cb --- /dev/null +++ b/src/parsers/urdf/utils.hpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2016 CNRS +// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France. +// +// This file is part of Pinocchio +// Pinocchio is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation, either version +// 3 of the License, or (at your option) any later version. +// +// Pinocchio is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Lesser Public License for more details. You should have +// received a copy of the GNU Lesser General Public License along with +// Pinocchio If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef __se3_parsers_urdf_utils_hpp__ +#define __se3_parsers_urdf_utils_hpp__ + +#include <urdf_model/model.h> +#include <urdf_parser/urdf_parser.h> + +#include <iostream> +#include <sstream> +#include <iomanip> +#include <boost/foreach.hpp> + +#include "pinocchio/spatial/fwd.hpp" +#include "pinocchio/spatial/se3.hpp" + +// #include "pinocchio/multibody/model.hpp" + +#include <exception> +#include <limits> + +namespace se3 +{ + namespace urdf + { + + /// + /// \brief Convert URDF Inertial quantity to Spatial Inertia. + /// + /// \param[in] Y The input URDF Inertia. + /// + /// \return The converted Spatial Inertia se3::Inertia. + /// + inline Inertia convertFromUrdf (const ::urdf::Inertial & Y) + { + const ::urdf::Vector3 & p = Y.origin.position; + const ::urdf::Rotation & q = Y.origin.rotation; + + const Eigen::Vector3d com(p.x,p.y,p.z); + const Eigen::Matrix3d & R = Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(); + + Eigen::Matrix3d I; I << Y.ixx,Y.ixy,Y.ixz + , Y.ixy,Y.iyy,Y.iyz + , Y.ixz,Y.iyz,Y.izz; + return Inertia(Y.mass,com,R*I*R.transpose()); + } + + /// + /// \brief Convert URDF Pose quantity to SE3. + /// + /// \param[in] M The input URDF Pose. + /// + /// \return The converted pose/transform se3::SE3. + /// + inline SE3 convertFromUrdf (const ::urdf::Pose & M) + { + const ::urdf::Vector3 & p = M.position; + const ::urdf::Rotation & q = M.rotation; + return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z)); + } + + /// + /// \brief The four possible cartesian types of an 3D axis. + /// + enum AxisCartesian { AXIS_X, AXIS_Y, AXIS_Z, 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 se3::urdf::AxisCartesian. + /// + inline AxisCartesian extractCartesianAxis (const ::urdf::Vector3 & axis) + { + if( (axis.x==1.0)&&(axis.y==0.0)&&(axis.z==0.0) ) + return AXIS_X; + else if( (axis.x==0.0)&&(axis.y==1.0)&&(axis.z==0.0) ) + return AXIS_Y; + else if( (axis.x==0.0)&&(axis.y==0.0)&&(axis.z==1.0) ) + return AXIS_Z; + else + return AXIS_UNALIGNED; + } + + } //urdf +} // se3 +#endif // __se3_parsers_urdf_utils_hpp__ diff --git a/src/multibody/parser/from-collada-to-fcl.hpp b/src/parsers/utils.hpp similarity index 75% rename from src/multibody/parser/from-collada-to-fcl.hpp rename to src/parsers/utils.hpp index 76ee4894d..e686012a0 100644 --- a/src/multibody/parser/from-collada-to-fcl.hpp +++ b/src/parsers/utils.hpp @@ -1,8 +1,7 @@ // -// Copyright (c) 2015-2016 CNRS +// Copyright (c) 2015 CNRS // -// This file is part of Pinocchio and is mainly inspired -// by software hpp-model-urdf +// This file is part of Pinocchio // Pinocchio is free software: you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation, either version @@ -16,9 +15,7 @@ // Pinocchio If not, see // <http://www.gnu.org/licenses/>. -#ifndef __se3_collada_to_fcl_hpp__ -#define __se3_collada_to_fcl_hpp__ - +#include <iostream> #include <limits> #include <sstream> @@ -33,8 +30,36 @@ namespace se3 { - + /// + /// \brief Supported model file extensions + /// + enum ModelFileExtensionType{ + UNKNOWN = 0, + URDF, + LUA + }; + /// + /// \brief Extract the type of the given model file according to its extension + /// + /// \param[in] filemane The complete path to the model file. + /// + /// \return The type of the extension of the model file + /// + ModelFileExtensionType checkModelFileExtension (const std::string & filename) + { + const std::string extension = filename.substr(filename.find_last_of(".") + 1); + + if (extension == "urdf") + return URDF; + else if (extension == "lua") + return LUA; + + return UNKNOWN; + } + + + /** * @brief Transform a package://.. mesh path to an absolute path, searching for a valid file * in a list of package directories @@ -67,6 +92,3 @@ namespace se3 } } // namespace se3 - - -#endif // __se3_collada_to_fcl_hpp__ diff --git a/src/python/model.hpp b/src/python/model.hpp index ddb92b7db..7d8b507dc 100644 --- a/src/python/model.hpp +++ b/src/python/model.hpp @@ -24,7 +24,7 @@ #include <eigenpy/eigenpy.hpp> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/python/se3.hpp" #include "pinocchio/python/eigen_container.hpp" #include "pinocchio/python/handler.hpp" diff --git a/src/python/parsers.hpp b/src/python/parsers.hpp index d2dc499ca..284cdc62e 100644 --- a/src/python/parsers.hpp +++ b/src/python/parsers.hpp @@ -25,19 +25,18 @@ #include "pinocchio/python/data.hpp" #ifdef WITH_URDFDOM - #include "pinocchio/multibody/parser/urdf.hpp" + #include "pinocchio/parsers/urdf.hpp" #ifdef WITH_HPP_FCL #include "pinocchio/python/geometry-model.hpp" #include "pinocchio/python/geometry-data.hpp" - #include "pinocchio/multibody/parser/urdf-with-geometry.hpp" #endif #endif #ifdef WITH_LUA - #include "pinocchio/multibody/parser/lua.hpp" + #include "pinocchio/parsers/lua.hpp" #endif // #ifdef WITH_LUA -#include "pinocchio/multibody/parser/srdf.hpp" +#include "pinocchio/parsers/srdf.hpp" namespace se3 { diff --git a/src/tools/file-explorer.hpp b/src/tools/file-explorer.hpp index 9bb588646..74a857428 100644 --- a/src/tools/file-explorer.hpp +++ b/src/tools/file-explorer.hpp @@ -58,6 +58,17 @@ namespace se3 return env_var_paths; } + + /** + * @brief Parse the environment variable ROS_PACKAGE_PATH and extract paths + * + * @return The vector of paths extracted from the environment variable ROS_PACKAGE_PATH + */ + inline std::vector<std::string> rosPaths() + { + return extractPathFromEnvVar("ROS_PACKAGE_PATH"); + } + } #endif // __se3_file_explorer_hpp__ diff --git a/unittest/aba.cpp b/unittest/aba.cpp index c5c60e6a9..ac78668c5 100644 --- a/unittest/aba.cpp +++ b/unittest/aba.cpp @@ -23,7 +23,7 @@ #include "pinocchio/algorithm/aba.hpp" #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/algorithm/crba.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/algorithm/compute-all-terms.hpp" #include "pinocchio/tools/timer.hpp" diff --git a/unittest/cholesky.cpp b/unittest/cholesky.cpp index 2e57d01d4..a0ca68179 100644 --- a/unittest/cholesky.cpp +++ b/unittest/cholesky.cpp @@ -26,7 +26,7 @@ #include "pinocchio/multibody/model.hpp" #include "pinocchio/algorithm/crba.hpp" #include "pinocchio/algorithm/cholesky.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/com.cpp b/unittest/com.cpp index 38b000a57..200f8e42a 100644 --- a/unittest/com.cpp +++ b/unittest/com.cpp @@ -21,7 +21,7 @@ #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/algorithm/center-of-mass.hpp" #include "pinocchio/tools/timer.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include <iostream> diff --git a/unittest/compute-all-terms.cpp b/unittest/compute-all-terms.cpp index 6577cdbd1..79167de74 100644 --- a/unittest/compute-all-terms.cpp +++ b/unittest/compute-all-terms.cpp @@ -30,7 +30,7 @@ #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/algorithm/jacobian.hpp" #include "pinocchio/algorithm/compute-all-terms.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #define BOOST_TEST_DYN_LINK diff --git a/unittest/crba.cpp b/unittest/crba.cpp index 0ca38b93a..a2ea0bd41 100644 --- a/unittest/crba.cpp +++ b/unittest/crba.cpp @@ -27,7 +27,7 @@ #include "pinocchio/algorithm/crba.hpp" #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/algorithm/center-of-mass.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/dynamics.cpp b/unittest/dynamics.cpp index 56534de3f..1b0ae862f 100644 --- a/unittest/dynamics.cpp +++ b/unittest/dynamics.cpp @@ -19,7 +19,7 @@ #include "pinocchio/multibody/model.hpp" #include "pinocchio/algorithm/jacobian.hpp" #include "pinocchio/algorithm/dynamics.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/energy.cpp b/unittest/energy.cpp index 7584c4401..59e74aa90 100644 --- a/unittest/energy.cpp +++ b/unittest/energy.cpp @@ -18,7 +18,7 @@ #include "pinocchio/algorithm/energy.hpp" #include "pinocchio/algorithm/crba.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE ComTest diff --git a/unittest/frames.cpp b/unittest/frames.cpp index afa8f0448..ff32af394 100644 --- a/unittest/frames.cpp +++ b/unittest/frames.cpp @@ -20,7 +20,7 @@ #include "pinocchio/algorithm/frames.hpp" #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/spatial/act-on-set.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/geom.cpp b/unittest/geom.cpp index 82ac54f9c..1ef097e09 100644 --- a/unittest/geom.cpp +++ b/unittest/geom.cpp @@ -32,14 +32,13 @@ #include <iomanip> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/algorithm/kinematics.hpp" #include "pinocchio/algorithm/collisions.hpp" -#include "pinocchio/multibody/parser/urdf.hpp" +#include "pinocchio/parsers/urdf.hpp" #include "pinocchio/spatial/explog.hpp" #include "pinocchio/multibody/geometry.hpp" -#include "pinocchio/multibody/parser/urdf-with-geometry.hpp" #include <vector> diff --git a/unittest/jacobian.cpp b/unittest/jacobian.cpp index 1197d4691..ff3c9dfd2 100644 --- a/unittest/jacobian.cpp +++ b/unittest/jacobian.cpp @@ -19,7 +19,7 @@ #include "pinocchio/algorithm/jacobian.hpp" #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/spatial/act-on-set.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/joint-configurations.cpp b/unittest/joint-configurations.cpp index 8c3542ca0..f42657a16 100644 --- a/unittest/joint-configurations.cpp +++ b/unittest/joint-configurations.cpp @@ -32,7 +32,7 @@ #include <iomanip> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/algorithm/kinematics.hpp" #include "pinocchio/algorithm/joint-configuration.hpp" #include "pinocchio/spatial/explog.hpp" diff --git a/unittest/joint.cpp b/unittest/joint.cpp index 8f1724f73..36e76337a 100644 --- a/unittest/joint.cpp +++ b/unittest/joint.cpp @@ -22,7 +22,7 @@ #include "pinocchio/algorithm/joint-configuration.hpp" #include "pinocchio/algorithm/compute-all-terms.hpp" #include "pinocchio/spatial/act-on-set.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include "pinocchio/multibody/joint/joint.hpp" @@ -140,4 +140,4 @@ BOOST_AUTO_TEST_CASE ( test_all_joints ) } -BOOST_AUTO_TEST_SUITE_END () \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END () diff --git a/unittest/lua.cpp b/unittest/lua.cpp index 583785717..39cef00f5 100644 --- a/unittest/lua.cpp +++ b/unittest/lua.cpp @@ -18,7 +18,7 @@ #include <iostream> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/lua.hpp" +#include "pinocchio/parsers/lua.hpp" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE LuaTest diff --git a/unittest/python_parser.cpp b/unittest/python_parser.cpp index 1c59ff01b..6512cb6a1 100644 --- a/unittest/python_parser.cpp +++ b/unittest/python_parser.cpp @@ -18,7 +18,7 @@ #include <iostream> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/python.hpp" +#include "pinocchio/parsers/python.hpp" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE PythonTest diff --git a/unittest/rnea.cpp b/unittest/rnea.cpp index 7a6e00757..7d4990eb6 100644 --- a/unittest/rnea.cpp +++ b/unittest/rnea.cpp @@ -27,7 +27,7 @@ #include "pinocchio/multibody/visitor.hpp" #include "pinocchio/multibody/model.hpp" #include "pinocchio/algorithm/rnea.hpp" -#include "pinocchio/multibody/parser/sample-models.hpp" +#include "pinocchio/parsers/sample-models.hpp" #include "pinocchio/tools/timer.hpp" #include <iostream> diff --git a/unittest/urdf.cpp b/unittest/urdf.cpp index 280c5a81d..5f260b62d 100644 --- a/unittest/urdf.cpp +++ b/unittest/urdf.cpp @@ -18,7 +18,7 @@ #include <iostream> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/urdf.hpp" +#include "pinocchio/parsers/urdf.hpp" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE UrdfTest diff --git a/unittest/value.cpp b/unittest/value.cpp index 85bf88cee..d0d9ed2da 100644 --- a/unittest/value.cpp +++ b/unittest/value.cpp @@ -32,7 +32,7 @@ #include <iomanip> #include "pinocchio/multibody/model.hpp" -#include "pinocchio/multibody/parser/urdf.hpp" + #include "pinocchio/parsers/urdf.hpp" #include "pinocchio/algorithm/rnea.hpp" #include "pinocchio/algorithm/kinematics.hpp" diff --git a/utils/pinocchio_read_model.cpp b/utils/pinocchio_read_model.cpp index aa9da9767..e64db62d6 100644 --- a/utils/pinocchio_read_model.cpp +++ b/utils/pinocchio_read_model.cpp @@ -22,14 +22,14 @@ #include "pinocchio/multibody/model.hpp" #ifdef WITH_URDFDOM - #include "pinocchio/multibody/parser/urdf.hpp" + #include "pinocchio/parsers/urdf.hpp" #endif #ifdef WITH_LUA - #include "pinocchio/multibody/parser/lua.hpp" + #include "pinocchio/parsers/lua.hpp" #endif -#include "pinocchio/multibody/parser/utils.hpp" +#include "pinocchio/parsers/utils.hpp" using namespace std; -- GitLab