| Directory: | ./ |
|---|---|
| File: | src/parsers/urdf/geometry.cpp |
| Date: | 2025-02-12 21:03:38 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 157 | 174 | 90.2% |
| Branches: | 201 | 403 | 49.9% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright (c) 2015-2020 CNRS INRIA | ||
| 3 | // | ||
| 4 | |||
| 5 | #include "pinocchio/parsers/urdf.hpp" | ||
| 6 | #include "pinocchio/parsers/urdf/types.hpp" | ||
| 7 | #include "pinocchio/parsers/urdf/utils.hpp" | ||
| 8 | #include "pinocchio/parsers/utils.hpp" | ||
| 9 | |||
| 10 | #include <boost/property_tree/xml_parser.hpp> | ||
| 11 | #include <boost/property_tree/ptree.hpp> | ||
| 12 | |||
| 13 | #include <urdf_model/model.h> | ||
| 14 | #include <urdf_parser/urdf_parser.h> | ||
| 15 | |||
| 16 | #ifdef PINOCCHIO_WITH_HPP_FCL | ||
| 17 | |||
| 18 | #include <hpp/fcl/mesh_loader/loader.h> | ||
| 19 | #include <hpp/fcl/mesh_loader/assimp.h> | ||
| 20 | |||
| 21 | #endif // PINOCCHIO_WITH_HPP_FCL | ||
| 22 | |||
| 23 | namespace pinocchio | ||
| 24 | { | ||
| 25 | namespace urdf | ||
| 26 | { | ||
| 27 | /// \internal | ||
| 28 | namespace details | ||
| 29 | { | ||
| 30 | struct UrdfTree | ||
| 31 | { | ||
| 32 | typedef boost::property_tree::ptree ptree; | ||
| 33 | typedef std::map<std::string, const ptree &> LinkMap_t; | ||
| 34 | |||
| 35 | 76 | void parse(const std::string & xmlStr) | |
| 36 | { | ||
| 37 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | urdf_ = ::urdf::parseURDF(xmlStr); |
| 38 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
|
76 | if (!urdf_) |
| 39 | { | ||
| 40 | ✗ | throw std::invalid_argument("Unable to parse URDF"); | |
| 41 | } | ||
| 42 | |||
| 43 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | std::istringstream iss(xmlStr); |
| 44 | using namespace boost::property_tree; | ||
| 45 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | read_xml(iss, tree_, xml_parser::no_comments); |
| 46 | |||
| 47 |
20/34✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 76 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 76 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 76 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 76 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 76 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 76 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 7169 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 7169 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 7169 times.
✓ Branch 32 taken 7169 times.
✓ Branch 33 taken 7169 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 7169 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 7245 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 7245 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 7169 times.
✓ Branch 44 taken 76 times.
✓ Branch 45 taken 7169 times.
✓ Branch 46 taken 76 times.
|
14414 | BOOST_FOREACH (const ptree::value_type & link, tree_.get_child("robot")) |
| 48 | { | ||
| 49 |
2/2✓ Branch 1 taken 3000 times.
✓ Branch 2 taken 4169 times.
|
7169 | if (link.first == "link") |
| 50 | { | ||
| 51 |
2/4✓ Branch 1 taken 3000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3000 times.
✗ Branch 5 not taken.
|
3000 | std::string name = link.second.get<std::string>("<xmlattr>.name"); |
| 52 |
2/4✓ Branch 1 taken 3000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3000 times.
✗ Branch 5 not taken.
|
3000 | links_.insert(std::pair<std::string, const ptree &>(name, link.second)); |
| 53 | 3000 | } | |
| 54 | } // BOOST_FOREACH | ||
| 55 | 76 | } | |
| 56 | |||
| 57 | 59 | bool isCapsule(const std::string & linkName, const std::string & geomName) const | |
| 58 | { | ||
| 59 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | LinkMap_t::const_iterator _link = links_.find(linkName); |
| 60 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
|
59 | assert(_link != links_.end()); |
| 61 | 59 | const ptree & link = _link->second; | |
| 62 |
4/6✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 59 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 56 times.
✓ Branch 10 taken 3 times.
|
59 | if (link.count("collision_checking") == 0) |
| 63 | 56 | return false; | |
| 64 |
15/34✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 3 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 3 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 3 times.
✗ Branch 46 not taken.
|
3 | BOOST_FOREACH (const ptree::value_type & cc, link.get_child("collision_checking")) |
| 65 | { | ||
| 66 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (cc.first == "capsule") |
| 67 | { | ||
| 68 | #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME | ||
| 69 | std::cerr << "Warning: support for tag link/collision_checking/capsule" | ||
| 70 | " is not available for URDFDOM < 0.3.0" | ||
| 71 | << std::endl; | ||
| 72 | #else | ||
| 73 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | std::string name = cc.second.get<std::string>("<xmlattr>.name"); |
| 74 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (geomName == name) |
| 75 | 3 | return true; | |
| 76 | #endif | ||
| 77 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | } |
| 78 | } // BOOST_FOREACH | ||
| 79 | |||
| 80 | ✗ | return false; | |
| 81 | } | ||
| 82 | |||
| 83 | 1428 | bool isMeshConvex(const std::string & linkName, const std::string & geomName) const | |
| 84 | { | ||
| 85 |
1/2✓ Branch 1 taken 1428 times.
✗ Branch 2 not taken.
|
1428 | LinkMap_t::const_iterator _link = links_.find(linkName); |
| 86 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1428 times.
|
1428 | assert(_link != links_.end()); |
| 87 | 1428 | const ptree & link = _link->second; | |
| 88 |
4/6✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1428 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1425 times.
✓ Branch 10 taken 3 times.
|
1428 | if (link.count("collision_checking") == 0) |
| 89 | 1425 | return false; | |
| 90 |
18/34✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 6 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 6 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 6 times.
✓ Branch 32 taken 3 times.
✓ Branch 33 taken 3 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 3 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 6 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 6 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 6 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 6 times.
✗ Branch 46 not taken.
|
9 | BOOST_FOREACH (const ptree::value_type & cc, link.get_child("collision_checking")) |
| 91 | { | ||
| 92 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
|
6 | if (cc.first == "convex") |
| 93 | { | ||
| 94 | #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME | ||
| 95 | std::cerr << "Warning: support for tag link/collision_checking/convex" | ||
| 96 | " is not available for URDFDOM < 0.3.0" | ||
| 97 | << std::endl; | ||
| 98 | #else | ||
| 99 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | std::string name = cc.second.get<std::string>("<xmlattr>.name"); |
| 100 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (geomName == name) |
| 101 | 3 | return true; | |
| 102 | #endif | ||
| 103 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | } |
| 104 | } // BOOST_FOREACH | ||
| 105 | |||
| 106 | ✗ | return false; | |
| 107 | } | ||
| 108 | |||
| 109 | // For standard URDF tags | ||
| 110 | ::urdf::ModelInterfaceSharedPtr urdf_; | ||
| 111 | // For other tags | ||
| 112 | ptree tree_; | ||
| 113 | // A mapping from link name to corresponding child of tree_ | ||
| 114 | LinkMap_t links_; | ||
| 115 | }; | ||
| 116 | |||
| 117 | template<typename Vector3> | ||
| 118 | 1428 | static void retrieveMeshScale( | |
| 119 | const ::urdf::MeshSharedPtr & mesh, const Eigen::MatrixBase<Vector3> & scale) | ||
| 120 | { | ||
| 121 | 1428 | Vector3 & scale_ = PINOCCHIO_EIGEN_CONST_CAST(Vector3, scale); | |
| 122 |
2/4✓ Branch 4 taken 1428 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1428 times.
✗ Branch 9 not taken.
|
1428 | scale_ << mesh->scale.x, mesh->scale.y, mesh->scale.z; |
| 123 | 1428 | } | |
| 124 | |||
| 125 | #ifdef PINOCCHIO_WITH_HPP_FCL | ||
| 126 | /** | ||
| 127 | * @brief Get a fcl::CollisionObject from a URDF geometry, searching | ||
| 128 | * for it in specified package directories | ||
| 129 | * | ||
| 130 | * @param[in] urdf_geometry A shared pointer on the input urdf Geometry | ||
| 131 | * @param[in] package_dirs A vector containing the different directories where to search | ||
| 132 | * for packages | ||
| 133 | * @param[out] meshPath The Absolute path of the mesh currently read | ||
| 134 | * @param[out] meshScale Scale of transformation currently applied to the mesh | ||
| 135 | * | ||
| 136 | * @return A shared pointer on the geometry converted as a fcl::CollisionGeometry | ||
| 137 | */ | ||
| 138 | 1507 | std::shared_ptr<fcl::CollisionGeometry> inline retrieveCollisionGeometry( | |
| 139 | const UrdfTree & tree, | ||
| 140 | fcl::MeshLoaderPtr & meshLoader, | ||
| 141 | const std::string & linkName, | ||
| 142 | const std::string & geomName, | ||
| 143 | const ::urdf::GeometrySharedPtr urdf_geometry, | ||
| 144 | const std::vector<std::string> & package_dirs, | ||
| 145 | std::string & meshPath, | ||
| 146 | Eigen::Vector3d & meshScale) | ||
| 147 | { | ||
| 148 | 1507 | std::shared_ptr<fcl::CollisionGeometry> geometry; | |
| 149 | |||
| 150 | // Handle the case where collision geometry is a mesh | ||
| 151 |
2/2✓ Branch 1 taken 1428 times.
✓ Branch 2 taken 79 times.
|
1507 | if (urdf_geometry->type == ::urdf::Geometry::MESH) |
| 152 | { | ||
| 153 | const ::urdf::MeshSharedPtr urdf_mesh = | ||
| 154 | 1428 | ::urdf::static_pointer_cast<::urdf::Mesh>(urdf_geometry); | |
| 155 |
1/2✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
|
1428 | std::string collisionFilename = urdf_mesh->filename; |
| 156 | |||
| 157 |
1/2✓ Branch 1 taken 1428 times.
✗ Branch 2 not taken.
|
1428 | meshPath = retrieveResourcePath(collisionFilename, package_dirs); |
| 158 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1428 times.
|
1428 | if (meshPath == "") |
| 159 | { | ||
| 160 | ✗ | std::stringstream ss; | |
| 161 | ✗ | ss << "Mesh " << collisionFilename << " could not be found."; | |
| 162 | ✗ | throw std::invalid_argument(ss.str()); | |
| 163 | } | ||
| 164 | |||
| 165 |
1/2✓ Branch 4 taken 1428 times.
✗ Branch 5 not taken.
|
1428 | fcl::Vec3f scale = fcl::Vec3f(urdf_mesh->scale.x, urdf_mesh->scale.y, urdf_mesh->scale.z); |
| 166 | |||
| 167 |
1/2✓ Branch 1 taken 1428 times.
✗ Branch 2 not taken.
|
1428 | retrieveMeshScale(urdf_mesh, meshScale); |
| 168 | |||
| 169 | // Create FCL mesh by parsing Collada file. | ||
| 170 |
1/2✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
|
1428 | hpp::fcl::BVHModelPtr_t bvh = meshLoader->load(meshPath, scale); |
| 171 |
1/2✓ Branch 1 taken 1428 times.
✗ Branch 2 not taken.
|
1428 | bool convex = tree.isMeshConvex(linkName, geomName); |
| 172 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1425 times.
|
1428 | if (convex) |
| 173 | { | ||
| 174 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | bvh->buildConvexRepresentation(false); |
| 175 |
1/2✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
|
9 | geometry = std::shared_ptr<fcl::CollisionGeometry>( |
| 176 | 9 | bvh->convex.get(), [bvh](...) mutable { bvh->convex.reset(); }); | |
| 177 | } | ||
| 178 | else | ||
| 179 | { | ||
| 180 |
1/2✓ Branch 3 taken 1425 times.
✗ Branch 4 not taken.
|
2850 | geometry = std::shared_ptr<fcl::CollisionGeometry>( |
| 181 | 2654 | bvh.get(), [bvh](...) mutable { bvh.reset(); }); | |
| 182 | } | ||
| 183 | 1428 | } | |
| 184 | |||
| 185 | // Handle the case where collision geometry is a cylinder | ||
| 186 | // Use FCL capsules for cylinders | ||
| 187 |
2/2✓ Branch 1 taken 59 times.
✓ Branch 2 taken 20 times.
|
79 | else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER) |
| 188 | { | ||
| 189 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | const bool is_capsule = tree.isCapsule(linkName, geomName); |
| 190 |
3/6✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 59 times.
✗ Branch 8 not taken.
|
59 | meshScale << 1, 1, 1; |
| 191 | const ::urdf::CylinderSharedPtr collisionGeometry = | ||
| 192 | 59 | ::urdf::static_pointer_cast<::urdf::Cylinder>(urdf_geometry); | |
| 193 | |||
| 194 | 59 | double radius = collisionGeometry->radius; | |
| 195 | 59 | double length = collisionGeometry->length; | |
| 196 | |||
| 197 | // Create fcl capsule geometry. | ||
| 198 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 56 times.
|
59 | if (is_capsule) |
| 199 | { | ||
| 200 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | meshPath = "CAPSULE"; |
| 201 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
3 | geometry = std::shared_ptr<fcl::CollisionGeometry>(new fcl::Capsule(radius, length)); |
| 202 | } | ||
| 203 | else | ||
| 204 | { | ||
| 205 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | meshPath = "CYLINDER"; |
| 206 |
3/6✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 56 times.
✗ Branch 8 not taken.
|
56 | geometry = std::shared_ptr<fcl::CollisionGeometry>(new fcl::Cylinder(radius, length)); |
| 207 | } | ||
| 208 | 59 | } | |
| 209 | // Handle the case where collision geometry is a box. | ||
| 210 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | else if (urdf_geometry->type == ::urdf::Geometry::BOX) |
| 211 | { | ||
| 212 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | meshPath = "BOX"; |
| 213 |
3/6✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
|
20 | meshScale << 1, 1, 1; |
| 214 | const ::urdf::BoxSharedPtr collisionGeometry = | ||
| 215 | 20 | ::urdf::static_pointer_cast<::urdf::Box>(urdf_geometry); | |
| 216 | |||
| 217 | 20 | double x = collisionGeometry->dim.x; | |
| 218 | 20 | double y = collisionGeometry->dim.y; | |
| 219 | 20 | double z = collisionGeometry->dim.z; | |
| 220 | |||
| 221 |
3/6✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
|
20 | geometry = std::shared_ptr<fcl::CollisionGeometry>(new fcl::Box(x, y, z)); |
| 222 | 20 | } | |
| 223 | // Handle the case where collision geometry is a sphere. | ||
| 224 | ✗ | else if (urdf_geometry->type == ::urdf::Geometry::SPHERE) | |
| 225 | { | ||
| 226 | ✗ | meshPath = "SPHERE"; | |
| 227 | ✗ | meshScale << 1, 1, 1; | |
| 228 | const ::urdf::SphereSharedPtr collisionGeometry = | ||
| 229 | ✗ | ::urdf::static_pointer_cast<::urdf::Sphere>(urdf_geometry); | |
| 230 | |||
| 231 | ✗ | double radius = collisionGeometry->radius; | |
| 232 | |||
| 233 | ✗ | geometry = std::shared_ptr<fcl::CollisionGeometry>(new fcl::Sphere(radius)); | |
| 234 | } | ||
| 235 | else | ||
| 236 | ✗ | throw std::invalid_argument("Unknown geometry type :"); | |
| 237 | |||
| 238 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1507 times.
|
1507 | if (!geometry) |
| 239 | { | ||
| 240 | ✗ | throw std::invalid_argument("The polyhedron retrieved is empty"); | |
| 241 | } | ||
| 242 | |||
| 243 | 1507 | return geometry; | |
| 244 | } | ||
| 245 | #endif // PINOCCHIO_WITH_HPP_FCL | ||
| 246 | |||
| 247 | /** | ||
| 248 | * @brief Get the first geometry attached to a link | ||
| 249 | * | ||
| 250 | * @param[in] link The URDF link | ||
| 251 | * | ||
| 252 | * @return Either the first collision or visual | ||
| 253 | */ | ||
| 254 | template<typename T> | ||
| 255 | inline PINOCCHIO_URDF_SHARED_PTR(const T) | ||
| 256 | getLinkGeometry(const ::urdf::LinkConstSharedPtr link); | ||
| 257 | |||
| 258 | template<> | ||
| 259 | inline ::urdf::CollisionConstSharedPtr | ||
| 260 | 2331 | getLinkGeometry<::urdf::Collision>(const ::urdf::LinkConstSharedPtr link) | |
| 261 | { | ||
| 262 | 2331 | return link->collision; | |
| 263 | } | ||
| 264 | |||
| 265 | template<> | ||
| 266 | inline ::urdf::VisualConstSharedPtr | ||
| 267 | 669 | getLinkGeometry<::urdf::Visual>(const ::urdf::LinkConstSharedPtr link) | |
| 268 | { | ||
| 269 | 669 | return link->visual; | |
| 270 | } | ||
| 271 | |||
| 272 | /** | ||
| 273 | * @brief Get the material values from the link visual object | ||
| 274 | * | ||
| 275 | * @param[in] Visual/Collision The Visual or the Collision object. | ||
| 276 | * @param[out] meshTexturePath The absolute file path containing the texture description. | ||
| 277 | * @param[out] meshColor The mesh RGBA vector. | ||
| 278 | * @param[in] package_dirs A vector containing the different directories where to search | ||
| 279 | * for packages | ||
| 280 | * | ||
| 281 | */ | ||
| 282 | template<typename urdfObject> | ||
| 283 | inline bool getVisualMaterial( | ||
| 284 | const PINOCCHIO_URDF_SHARED_PTR(urdfObject) urdf_object, | ||
| 285 | std::string & meshTexturePath, | ||
| 286 | Eigen::Vector4d & meshColor, | ||
| 287 | const std::vector<std::string> & package_dirs); | ||
| 288 | |||
| 289 | template<> | ||
| 290 | 1074 | inline bool getVisualMaterial<::urdf::Collision>( | |
| 291 | const ::urdf::CollisionSharedPtr, | ||
| 292 | std::string & meshTexturePath, | ||
| 293 | Eigen::Vector4d & meshColor, | ||
| 294 | const std::vector<std::string> &) | ||
| 295 | { | ||
| 296 |
4/8✓ Branch 1 taken 1074 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1074 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1074 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1074 times.
✗ Branch 11 not taken.
|
1074 | meshColor << 0.9, 0.9, 0.9, 1.; |
| 297 | 1074 | meshTexturePath = ""; | |
| 298 | 1074 | return false; | |
| 299 | } | ||
| 300 | |||
| 301 | template<> | ||
| 302 | 433 | inline bool getVisualMaterial<::urdf::Visual>( | |
| 303 | const ::urdf::VisualSharedPtr urdf_visual, | ||
| 304 | std::string & meshTexturePath, | ||
| 305 | Eigen::Vector4d & meshColor, | ||
| 306 | const std::vector<std::string> & package_dirs) | ||
| 307 | { | ||
| 308 |
4/8✓ Branch 1 taken 433 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 433 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 433 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 433 times.
✗ Branch 11 not taken.
|
433 | meshColor << 0.9, 0.9, 0.9, 1.; |
| 309 | 433 | meshTexturePath = ""; | |
| 310 | 433 | bool overrideMaterial = false; | |
| 311 |
2/2✓ Branch 2 taken 218 times.
✓ Branch 3 taken 215 times.
|
433 | if (urdf_visual->material) |
| 312 | { | ||
| 313 | 218 | overrideMaterial = true; | |
| 314 |
2/4✓ Branch 3 taken 218 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 218 times.
✗ Branch 9 not taken.
|
218 | meshColor << urdf_visual->material->color.r, urdf_visual->material->color.g, |
| 315 |
2/4✓ Branch 3 taken 218 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 218 times.
✗ Branch 9 not taken.
|
218 | urdf_visual->material->color.b, urdf_visual->material->color.a; |
| 316 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 218 times.
|
218 | if (urdf_visual->material->texture_filename != "") |
| 317 | meshTexturePath = | ||
| 318 | ✗ | retrieveResourcePath((urdf_visual)->material->texture_filename, package_dirs); | |
| 319 | } | ||
| 320 | 433 | return overrideMaterial; | |
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * @brief Get the array of geometries attached to a link | ||
| 325 | * | ||
| 326 | * @param[in] link The URDF link | ||
| 327 | * | ||
| 328 | * @return the array of either collisions or visuals | ||
| 329 | */ | ||
| 330 | template<typename T> | ||
| 331 | inline const std::vector<PINOCCHIO_URDF_SHARED_PTR(T)> & | ||
| 332 | getLinkGeometryArray(const ::urdf::LinkConstSharedPtr link); | ||
| 333 | |||
| 334 | template<> | ||
| 335 | inline const std::vector<::urdf::CollisionSharedPtr> & | ||
| 336 | 1065 | getLinkGeometryArray<::urdf::Collision>(const ::urdf::LinkConstSharedPtr link) | |
| 337 | { | ||
| 338 | 1065 | return link->collision_array; | |
| 339 | } | ||
| 340 | |||
| 341 | template<> | ||
| 342 | inline const std::vector<::urdf::VisualSharedPtr> & | ||
| 343 | 433 | getLinkGeometryArray<::urdf::Visual>(const ::urdf::LinkConstSharedPtr link) | |
| 344 | { | ||
| 345 | 433 | return link->visual_array; | |
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * @brief Add the geometries attached to a URDF link to a GeometryModel, looking | ||
| 350 | * either for collisions or visuals | ||
| 351 | * | ||
| 352 | * @param[in] tree The URDF kinematic tree | ||
| 353 | * @param[in] meshLoader The FCL mesh loader to avoid duplications of already loaded | ||
| 354 | * geometries | ||
| 355 | * @param[in] link The current URDF link | ||
| 356 | * @param model The model to which is the GeometryModel associated | ||
| 357 | * @param geomModel The GeometryModel where the Collision Objects must be added | ||
| 358 | * @param[in] package_dirs A vector containing the different directories where to search | ||
| 359 | * for packages | ||
| 360 | * | ||
| 361 | */ | ||
| 362 | template<typename GeometryType> | ||
| 363 | 6000 | static void addLinkGeometryToGeomModel( | |
| 364 | const UrdfTree & tree, | ||
| 365 | ::hpp::fcl::MeshLoaderPtr & meshLoader, | ||
| 366 | ::urdf::LinkConstSharedPtr link, | ||
| 367 | UrdfGeomVisitorBase & visitor, | ||
| 368 | GeometryModel & geomModel, | ||
| 369 | const std::vector<std::string> & package_dirs) | ||
| 370 | { | ||
| 371 | #ifndef PINOCCHIO_WITH_HPP_FCL | ||
| 372 | PINOCCHIO_UNUSED_VARIABLE(tree); | ||
| 373 | PINOCCHIO_UNUSED_VARIABLE(meshLoader); | ||
| 374 | #endif // PINOCCHIO_WITH_HPP_FCL | ||
| 375 | |||
| 376 | typedef std::vector<PINOCCHIO_URDF_SHARED_PTR(GeometryType)> VectorSharedT; | ||
| 377 | typedef GeometryModel::SE3 SE3; | ||
| 378 | |||
| 379 |
2/2✓ Branch 5 taken 1498 times.
✓ Branch 6 taken 1502 times.
|
6000 | if (getLinkGeometry<GeometryType>(link)) |
| 380 | { | ||
| 381 |
1/2✓ Branch 2 taken 1498 times.
✗ Branch 3 not taken.
|
2996 | std::string meshPath = ""; |
| 382 | |||
| 383 |
2/4✓ Branch 1 taken 1498 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1498 times.
✗ Branch 5 not taken.
|
2996 | Eigen::Vector3d meshScale(Eigen::Vector3d::Ones()); |
| 384 | |||
| 385 | 2996 | const std::string & link_name = link->name; | |
| 386 | |||
| 387 |
1/2✓ Branch 3 taken 1498 times.
✗ Branch 4 not taken.
|
2996 | VectorSharedT geometries_array = getLinkGeometryArray<GeometryType>(link); |
| 388 | |||
| 389 | FrameIndex frame_id; | ||
| 390 |
1/2✓ Branch 1 taken 1498 times.
✗ Branch 2 not taken.
|
2996 | UrdfGeomVisitorBase::Frame frame = visitor.getBodyFrame(link_name, frame_id); |
| 391 |
1/2✓ Branch 1 taken 1498 times.
✗ Branch 2 not taken.
|
2996 | const SE3 & body_placement = frame.placement.cast<SE3::Scalar>(); |
| 392 | |||
| 393 | 2996 | std::size_t objectId = 0; | |
| 394 | 6010 | for (typename VectorSharedT::const_iterator i = geometries_array.begin(); | |
| 395 |
2/2✓ Branch 3 taken 1507 times.
✓ Branch 4 taken 1498 times.
|
6010 | i != geometries_array.end(); ++i) |
| 396 | { | ||
| 397 | 3014 | meshPath.clear(); | |
| 398 | #ifdef PINOCCHIO_WITH_HPP_FCL | ||
| 399 | |||
| 400 | #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME | ||
| 401 | const std::string & geom_name = (*i)->group_name; | ||
| 402 | #else | ||
| 403 | 3014 | const std::string & geom_name = (*i)->name; | |
| 404 | #endif // PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME | ||
| 405 |
1/2✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
|
3014 | const GeometryObject::CollisionGeometryPtr geometry = retrieveCollisionGeometry( |
| 406 | 3014 | tree, meshLoader, link_name, geom_name, (*i)->geometry, package_dirs, meshPath, | |
| 407 | meshScale); | ||
| 408 | #else | ||
| 409 | ::urdf::MeshSharedPtr urdf_mesh = | ||
| 410 | ::urdf::dynamic_pointer_cast<::urdf::Mesh>((*i)->geometry); | ||
| 411 | if (urdf_mesh) | ||
| 412 | { | ||
| 413 | meshPath = retrieveResourcePath(urdf_mesh->filename, package_dirs); | ||
| 414 | retrieveMeshScale(urdf_mesh, meshScale); | ||
| 415 | } | ||
| 416 | |||
| 417 | const std::shared_ptr<fcl::CollisionGeometry> geometry(new fcl::CollisionGeometry()); | ||
| 418 | #endif // PINOCCHIO_WITH_HPP_FCL | ||
| 419 | |||
| 420 |
1/2✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
|
3014 | Eigen::Vector4d meshColor; |
| 421 | 3014 | std::string meshTexturePath; | |
| 422 | bool overrideMaterial = | ||
| 423 |
1/2✓ Branch 3 taken 1507 times.
✗ Branch 4 not taken.
|
3014 | getVisualMaterial<GeometryType>((*i), meshTexturePath, meshColor, package_dirs); |
| 424 | |||
| 425 |
2/4✓ Branch 3 taken 1507 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1507 times.
✗ Branch 7 not taken.
|
3014 | const SE3 geomPlacement = body_placement * convertFromUrdf((*i)->origin); |
| 426 |
1/2✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
|
3014 | std::ostringstream geometry_object_suffix; |
| 427 |
2/4✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1507 times.
✗ Branch 5 not taken.
|
3014 | geometry_object_suffix << "_" << objectId; |
| 428 |
2/4✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1507 times.
✗ Branch 5 not taken.
|
3014 | const std::string & geometry_object_name = |
| 429 | std::string(link_name + geometry_object_suffix.str()); | ||
| 430 |
2/4✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1507 times.
✗ Branch 5 not taken.
|
3014 | GeometryObject geometry_object( |
| 431 | geometry_object_name, frame.parentJoint, frame_id, geomPlacement, geometry, meshPath, | ||
| 432 | meshScale, overrideMaterial, meshColor, meshTexturePath); | ||
| 433 |
1/2✓ Branch 1 taken 1507 times.
✗ Branch 2 not taken.
|
3014 | geomModel.addGeometryObject(geometry_object); |
| 434 | 3014 | ++objectId; | |
| 435 | } | ||
| 436 | 2996 | } | |
| 437 | 6000 | } | |
| 438 | |||
| 439 | /** | ||
| 440 | * @brief Recursive procedure for reading the URDF tree, looking for geometries | ||
| 441 | * This function fill the geometric model with geometry objects retrieved from the | ||
| 442 | * URDF tree | ||
| 443 | * | ||
| 444 | * @param[in] tree The URDF kinematic tree | ||
| 445 | * @param[in] meshLoader The FCL mesh loader to avoid duplications of already loaded | ||
| 446 | * geometries | ||
| 447 | * @param[in] link The current URDF link | ||
| 448 | * @param model The model to which is the GeometryModel associated | ||
| 449 | * @param geomModel The GeometryModel where the Collision Objects must be added | ||
| 450 | * @param[in] package_dirs A vector containing the different directories where to search | ||
| 451 | * for packages | ||
| 452 | * @param[in] type The type of objects that must be loaded ( can be VISUAL or | ||
| 453 | * COLLISION) | ||
| 454 | * | ||
| 455 | */ | ||
| 456 | 3000 | void recursiveParseTreeForGeom( | |
| 457 | const UrdfTree & tree, | ||
| 458 | ::hpp::fcl::MeshLoaderPtr & meshLoader, | ||
| 459 | ::urdf::LinkConstSharedPtr link, | ||
| 460 | UrdfGeomVisitorBase & visitor, | ||
| 461 | GeometryModel & geomModel, | ||
| 462 | const std::vector<std::string> & package_dirs, | ||
| 463 | const GeometryType type) | ||
| 464 | { | ||
| 465 | |||
| 466 |
2/3✓ Branch 0 taken 2331 times.
✓ Branch 1 taken 669 times.
✗ Branch 2 not taken.
|
3000 | switch (type) |
| 467 | { | ||
| 468 | 2331 | case COLLISION: | |
| 469 |
1/2✓ Branch 2 taken 2331 times.
✗ Branch 3 not taken.
|
2331 | addLinkGeometryToGeomModel<::urdf::Collision>( |
| 470 | tree, meshLoader, link, visitor, geomModel, package_dirs); | ||
| 471 | 2331 | break; | |
| 472 | 669 | case VISUAL: | |
| 473 |
1/2✓ Branch 2 taken 669 times.
✗ Branch 3 not taken.
|
669 | addLinkGeometryToGeomModel<::urdf::Visual>( |
| 474 | tree, meshLoader, link, visitor, geomModel, package_dirs); | ||
| 475 | 669 | break; | |
| 476 | ✗ | default: | |
| 477 | ✗ | break; | |
| 478 | } | ||
| 479 | |||
| 480 |
18/30✓ Branch 2 taken 3000 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3000 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3000 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3000 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3000 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 3000 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 2924 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 2924 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 2924 times.
✓ Branch 27 taken 2924 times.
✓ Branch 28 taken 2924 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 2924 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 5924 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 5924 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2924 times.
✓ Branch 39 taken 3000 times.
✓ Branch 40 taken 2924 times.
✓ Branch 41 taken 3000 times.
|
8848 | BOOST_FOREACH (::urdf::LinkConstSharedPtr child, link->child_links) |
| 481 | { | ||
| 482 |
1/2✓ Branch 2 taken 2924 times.
✗ Branch 3 not taken.
|
2924 | recursiveParseTreeForGeom( |
| 483 | tree, meshLoader, child, visitor, geomModel, package_dirs, type); | ||
| 484 | 2924 | } | |
| 485 | 3000 | } | |
| 486 | |||
| 487 | 76 | void parseTreeForGeom( | |
| 488 | UrdfGeomVisitorBase & visitor, | ||
| 489 | const std::istream & xmlStream, | ||
| 490 | const GeometryType type, | ||
| 491 | GeometryModel & geomModel, | ||
| 492 | const std::vector<std::string> & package_dirs, | ||
| 493 | ::hpp::fcl::MeshLoaderPtr meshLoader) | ||
| 494 | { | ||
| 495 | 76 | std::string xmlStr; | |
| 496 | { | ||
| 497 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | std::ostringstream os; |
| 498 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
76 | os << xmlStream.rdbuf(); |
| 499 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | xmlStr = os.str(); |
| 500 | 76 | } | |
| 501 | |||
| 502 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | details::UrdfTree tree; |
| 503 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | tree.parse(xmlStr); |
| 504 | |||
| 505 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | std::vector<std::string> hint_directories(package_dirs); |
| 506 | |||
| 507 | // Append the ROS_PACKAGE_PATH | ||
| 508 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | std::vector<std::string> ros_pkg_paths = rosPaths(); |
| 509 |
1/2✓ Branch 5 taken 76 times.
✗ Branch 6 not taken.
|
76 | hint_directories.insert(hint_directories.end(), ros_pkg_paths.begin(), ros_pkg_paths.end()); |
| 510 | |||
| 511 | #ifdef PINOCCHIO_WITH_HPP_FCL | ||
| 512 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | if (!meshLoader) |
| 513 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 76 times.
✗ Branch 6 not taken.
|
76 | meshLoader = fcl::MeshLoaderPtr(new fcl::MeshLoader); |
| 514 | #endif // ifdef PINOCCHIO_WITH_HPP_FCL | ||
| 515 | |||
| 516 |
1/2✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
|
76 | recursiveParseTreeForGeom( |
| 517 | 152 | tree, meshLoader, tree.urdf_->getRoot(), visitor, geomModel, hint_directories, type); | |
| 518 | 76 | } | |
| 519 | } // namespace details | ||
| 520 | /// \endinternal | ||
| 521 | } // namespace urdf | ||
| 522 | } // namespace pinocchio | ||
| 523 |