fcl_utils.cpp
Go to the documentation of this file.
1 
47 #include <fcl/geometry/shape/plane-inl.h>
52 #include <memory>
53 #include <stdexcept>
55 
59 
61 {
63 {
64  return std::make_shared<fcl::Planed>(geom->getA(), geom->getB(), geom->getC(), geom->getD());
65 }
66 
68 {
69  return std::make_shared<fcl::Boxd>(geom->getX(), geom->getY(), geom->getZ());
70 }
71 
73 {
74  return std::make_shared<fcl::Sphered>(geom->getRadius());
75 }
76 
78 {
79  return std::make_shared<fcl::Cylinderd>(geom->getRadius(), geom->getLength());
80 }
81 
83 {
84  return std::make_shared<fcl::Coned>(geom->getRadius(), geom->getLength());
85 }
86 
88 {
89  return std::make_shared<fcl::Capsuled>(geom->getRadius(), geom->getLength());
90 }
91 
93 {
94  int vertice_count = geom->getVertexCount();
95  int triangle_count = geom->getFaceCount();
96  const tesseract_common::VectorVector3d& vertices = *(geom->getVertices());
97  const Eigen::VectorXi& triangles = *(geom->getFaces());
98 
99  auto g = std::make_shared<fcl::BVHModel<fcl::OBBRSSd>>();
100  if (vertice_count > 0 && triangle_count > 0)
101  {
102  std::vector<fcl::Triangle> tri_indices(static_cast<size_t>(triangle_count));
103  for (int i = 0; i < triangle_count; ++i)
104  {
105  assert(triangles[4L * i] == 3);
106  tri_indices[static_cast<size_t>(i)] = fcl::Triangle(static_cast<size_t>(triangles[(4 * i) + 1]),
107  static_cast<size_t>(triangles[(4 * i) + 2]),
108  static_cast<size_t>(triangles[(4 * i) + 3]));
109  }
110 
111  g->beginModel();
112  g->addSubModel(vertices, tri_indices);
113  g->endModel();
114 
115  return g;
116  }
117 
118  CONSOLE_BRIDGE_logError("The mesh is empty!");
119  return nullptr;
120 }
121 
123 {
124  int vertice_count = geom->getVertexCount();
125  int face_count = geom->getFaceCount();
126 
127  if (vertice_count > 0 && face_count > 0)
128  {
129  auto faces = std::make_shared<const std::vector<int>>(geom->getFaces()->data(),
130  geom->getFaces()->data() + geom->getFaces()->size());
131  return std::make_shared<fcl::Convexd>(geom->getVertices(), face_count, faces);
132  }
133 
134  CONSOLE_BRIDGE_logError("The mesh is empty!");
135  return nullptr;
136 }
137 
139 {
140  switch (geom->getSubType())
141  {
143  {
144  return std::make_shared<fcl::OcTreed>(geom->getOctree());
145  }
146  default:
147  {
148  CONSOLE_BRIDGE_logError("This fcl octree sub shape type (%d) is not supported for geometry octree",
149  static_cast<int>(geom->getSubType()));
150  return nullptr;
151  }
152  }
153 }
154 
156 {
157  switch (geom->getType())
158  {
160  {
161  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Plane>(geom));
162  }
164  {
165  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Box>(geom));
166  }
168  {
169  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Sphere>(geom));
170  }
172  {
173  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Cylinder>(geom));
174  }
176  {
177  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Cone>(geom));
178  }
180  {
181  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Capsule>(geom));
182  }
184  {
185  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Mesh>(geom));
186  }
188  {
189  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::ConvexMesh>(geom));
190  }
192  {
193  return createShapePrimitive(std::static_pointer_cast<const tesseract_geometry::Octree>(geom));
194  }
196  {
197  throw std::runtime_error("CompundMesh type should not be passed to this function!");
198  }
199  default:
200  {
201  CONSOLE_BRIDGE_logError("This geometric shape type (%d) is not supported using fcl yet",
202  static_cast<int>(geom->getType()));
203  return nullptr;
204  }
205  }
206 }
207 
209 {
211  if (shape != nullptr)
212  return shape;
213 
214  shape = createShapePrimitiveHelper(geom);
216  return shape;
217 }
218 
220 {
221  auto* cdata = reinterpret_cast<ContactTestData*>(data); // NOLINT
222 
223  if (cdata->done)
224  return true;
225 
226  const auto* cd1 = static_cast<const CollisionObjectWrapper*>(o1->getUserData());
227  const auto* cd2 = static_cast<const CollisionObjectWrapper*>(o2->getUserData());
228 
229  bool needs_collision = cd1->m_enabled && cd2->m_enabled &&
230  (cd1->m_collisionFilterGroup & cd2->m_collisionFilterMask) && // NOLINT
231  (cd2->m_collisionFilterGroup & cd1->m_collisionFilterMask) && // NOLINT
232  !isContactAllowed(cd1->getName(), cd2->getName(), cdata->validator, false);
233 
234  assert(std::find(cdata->active->begin(), cdata->active->end(), cd1->getName()) != cdata->active->end() ||
235  std::find(cdata->active->begin(), cdata->active->end(), cd2->getName()) != cdata->active->end());
236 
237  if (!needs_collision)
238  return false;
239 
240  std::size_t num_contacts = (cdata->req.contact_limit > 0) ? static_cast<std::size_t>(cdata->req.contact_limit) :
241  std::numeric_limits<std::size_t>::max();
242  if (cdata->req.type == ContactTestType::FIRST)
243  num_contacts = 1;
244 
245  fcl::CollisionResultd col_result;
246  fcl::collide(o1, o2, fcl::CollisionRequestd(num_contacts, cdata->req.calculate_penetration, 1, false), col_result);
247 
248  if (col_result.isCollision())
249  {
250  const Eigen::Isometry3d& tf1 = cd1->getCollisionObjectsTransform();
251  const Eigen::Isometry3d& tf2 = cd2->getCollisionObjectsTransform();
252  Eigen::Isometry3d tf1_inv = tf1.inverse();
253  Eigen::Isometry3d tf2_inv = tf2.inverse();
254 
255  for (size_t i = 0; i < col_result.numContacts(); ++i)
256  {
257  const fcl::Contactd& fcl_contact = col_result.getContact(i);
258  ContactResult contact;
259  contact.link_names[0] = cd1->getName();
260  contact.link_names[1] = cd2->getName();
263  contact.subshape_id[0] = static_cast<int>(fcl_contact.b1);
264  contact.subshape_id[1] = static_cast<int>(fcl_contact.b2);
265  contact.nearest_points[0] = fcl_contact.pos;
266  contact.nearest_points[1] = fcl_contact.pos;
267  contact.nearest_points_local[0] = tf1_inv * contact.nearest_points[0];
268  contact.nearest_points_local[1] = tf2_inv * contact.nearest_points[1];
269  contact.transform[0] = tf1;
270  contact.transform[1] = tf2;
271  contact.type_id[0] = cd1->getTypeID();
272  contact.type_id[1] = cd2->getTypeID();
273  contact.distance = -1.0 * fcl_contact.penetration_depth;
274  contact.normal = fcl_contact.normal;
275 
276  ObjectPairKey pc = tesseract_common::makeOrderedLinkPair(cd1->getName(), cd2->getName());
277  const auto it = cdata->res->find(pc);
278  bool found = (it != cdata->res->end() && !it->second.empty());
279 
280  processResult(*cdata, contact, pc, found);
281  }
282  }
283 
284  return cdata->done;
285 }
286 
288 {
289  auto* cdata = reinterpret_cast<ContactTestData*>(data); // NOLINT
290 
291  if (cdata->done)
292  return true;
293 
294  const auto* cd1 = static_cast<const CollisionObjectWrapper*>(o1->getUserData());
295  const auto* cd2 = static_cast<const CollisionObjectWrapper*>(o2->getUserData());
296 
297  bool needs_collision = cd1->m_enabled && cd2->m_enabled &&
298  (cd1->m_collisionFilterGroup & cd2->m_collisionFilterMask) && // NOLINT
299  (cd2->m_collisionFilterGroup & cd1->m_collisionFilterMask) && // NOLINT
300  !isContactAllowed(cd1->getName(), cd2->getName(), cdata->validator, false);
301 
302  assert(std::find(cdata->active->begin(), cdata->active->end(), cd1->getName()) != cdata->active->end() ||
303  std::find(cdata->active->begin(), cdata->active->end(), cd2->getName()) != cdata->active->end());
304 
305  if (!needs_collision)
306  return false;
307 
308  fcl::DistanceResultd fcl_result;
309  fcl::DistanceRequestd fcl_request(true, true);
310  double d = fcl::distance(o1, o2, fcl_request, fcl_result);
311 
312  if (d < cdata->collision_margin_data.getMaxCollisionMargin())
313  {
314  const Eigen::Isometry3d& tf1 = cd1->getCollisionObjectsTransform();
315  const Eigen::Isometry3d& tf2 = cd2->getCollisionObjectsTransform();
316  Eigen::Isometry3d tf1_inv = tf1.inverse();
317  Eigen::Isometry3d tf2_inv = tf2.inverse();
318 
319  ContactResult contact;
320  contact.link_names[0] = cd1->getName();
321  contact.link_names[1] = cd2->getName();
324  contact.subshape_id[0] = static_cast<int>(fcl_result.b1);
325  contact.subshape_id[1] = static_cast<int>(fcl_result.b2);
326  contact.nearest_points[0] = fcl_result.nearest_points[0];
327  contact.nearest_points[1] = fcl_result.nearest_points[1];
328  contact.nearest_points_local[0] = tf1_inv * contact.nearest_points[0];
329  contact.nearest_points_local[1] = tf2_inv * contact.nearest_points[1];
330  contact.transform[0] = tf1;
331  contact.transform[1] = tf2;
332  contact.type_id[0] = cd1->getTypeID();
333  contact.type_id[1] = cd2->getTypeID();
334  contact.distance = fcl_result.min_distance;
335  contact.normal = (fcl_result.min_distance * (contact.nearest_points[1] - contact.nearest_points[0])).normalized();
336 
337  // TODO: There is an issue with FCL need to track down
338  assert(!std::isnan(contact.nearest_points[0](0)));
339 
340  ObjectPairKey pc = tesseract_common::makeOrderedLinkPair(cd1->getName(), cd2->getName());
341  const auto it = cdata->res->find(pc);
342  bool found = (it != cdata->res->end() && !it->second.empty());
343 
344  processResult(*cdata, contact, pc, found);
345  }
346 
347  return cdata->done;
348 }
349 
351  const int& type_id,
352  CollisionShapesConst shapes,
354  : name_(std::move(name)), type_id_(type_id), shapes_(std::move(shapes)), shape_poses_(std::move(shape_poses))
355 {
356  assert(!shapes_.empty()); // NOLINT
357  assert(!shape_poses_.empty()); // NOLINT
358  assert(!name_.empty()); // NOLINT
359  assert(shapes_.size() == shape_poses_.size()); // NOLINT
360 
363 
364  collision_geometries_.reserve(shapes_.size());
365  collision_objects_.reserve(shapes_.size());
366  collision_objects_raw_.reserve(shapes_.size());
367  for (std::size_t i = 0; i < shapes_.size(); ++i) // NOLINT
368  {
370  {
371  const auto& meshes = std::static_pointer_cast<const tesseract_geometry::CompoundMesh>(shapes_[i])->getMeshes();
372  for (const auto& mesh : meshes)
373  {
375  if (subshape != nullptr)
376  {
377  collision_geometries_.push_back(subshape);
378  auto co = std::make_shared<FCLCollisionObjectWrapper>(subshape);
379  co->setUserData(this);
380  co->setShapeIndex(static_cast<int>(i));
381  co->setTransform(shape_poses_[i]);
382  co->updateAABB();
383  collision_objects_.push_back(co);
384  collision_objects_raw_.push_back(co.get());
385  }
386  }
387  }
388  else
389  {
391  if (subshape != nullptr)
392  {
393  collision_geometries_.push_back(subshape);
394  auto co = std::make_shared<FCLCollisionObjectWrapper>(subshape);
395  co->setUserData(this);
396  co->setShapeIndex(static_cast<int>(i));
397  co->setTransform(shape_poses_[i]);
398  co->updateAABB();
399  collision_objects_.push_back(co);
400  collision_objects_raw_.push_back(co.get());
401  }
402  }
403  }
404 }
405 
407 {
408  return static_cast<const FCLCollisionObjectWrapper*>(co)->getShapeIndex();
409 }
410 
411 } // namespace tesseract_collision::tesseract_collision_fcl
cylinder-inl.h
tesseract_common::VectorIsometry3d
AlignedVector< Eigen::Isometry3d > VectorIsometry3d
octree-inl.h
box-inl.h
fcl::DistanceRequest
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::shapes_
CollisionShapesConst shapes_
Definition: fcl_utils.h:176
tesseract_geometry::Box::ConstPtr
std::shared_ptr< const Box > ConstPtr
tesseract_collision::ContactTestData
This data is intended only to be used internal to the collision checkers as a container and should no...
Definition: types.h:328
tesseract_collision::isContactAllowed
bool isContactAllowed(const std::string &name1, const std::string &name2, const std::shared_ptr< const tesseract_common::ContactAllowedValidator > &validator, bool verbose=false)
Determine if contact is allowed between two objects.
Definition: common.cpp:85
tesseract_geometry::GeometryType::COMPOUND_MESH
@ COMPOUND_MESH
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::collision_objects_
std::vector< CollisionObjectPtr > collision_objects_
Definition: fcl_utils.h:179
tesseract_geometry::GeometryType::CONE
@ CONE
tesseract_collision::ContactResult::shape_id
std::array< int, 2 > shape_id
The two shapes that are in contact. Each link can be made up of multiple shapes.
Definition: types.h:94
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::collision_geometries_
std::vector< CollisionGeometryPtr > collision_geometries_
Definition: fcl_utils.h:178
fcl::DistanceResult::b1
intptr_t b1
fcl::Contact
tesseract_collision::tesseract_collision_fcl::StaticFilter
@ StaticFilter
Definition: fcl_utils.h:68
tesseract_collision::ContactResult::normal
Eigen::Vector3d normal
The normal vector to move the two objects out of contact in world coordinates.
Definition: types.h:109
fcl::DistanceResult::nearest_points
Vector3< S > nearest_points[2]
fcl::CollisionResult::isCollision
bool isCollision() const
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::getShapeIndex
static int getShapeIndex(const fcl::CollisionObjectd *co)
Given fcl collision shape get the index to the links collision shape.
Definition: fcl_utils.cpp:406
fcl::DistanceResult::b2
intptr_t b2
fcl::Contact::normal
Vector3< S > normal
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
tesseract_geometry::GeometryType::MESH
@ MESH
tesseract_collision::tesseract_collision_fcl::collisionCallback
bool collisionCallback(fcl::CollisionObjectd *o1, fcl::CollisionObjectd *o2, void *data)
Definition: fcl_utils.cpp:219
tesseract_collision::tesseract_collision_fcl::FCLCollisionGeometryCache::get
static std::shared_ptr< fcl::CollisionGeometryd > get(const std::shared_ptr< const tesseract_geometry::Geometry > &key)
Retrieve the cache entry by key.
Definition: fcl_collision_geometry_cache.cpp:49
convex-inl.h
fcl::Contact::b1
intptr_t b1
tesseract_geometry::GeometryType::CYLINDER
@ CYLINDER
tesseract_geometry::Sphere::ConstPtr
std::shared_ptr< const Sphere > ConstPtr
fcl::CollisionResult
tesseract_collision::tesseract_collision_fcl::CollisionGeometryPtr
std::shared_ptr< fcl::CollisionGeometryd > CollisionGeometryPtr
Definition: fcl_utils.h:60
fcl::Contact::b2
intptr_t b2
sphere-inl.h
fcl::Triangle
tesseract_geometry::Cone::ConstPtr
std::shared_ptr< const Cone > ConstPtr
geometries.h
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::m_enabled
bool m_enabled
Definition: fcl_utils.h:93
fcl::DistanceResult
name
std::string name
fcl::distance
template double distance(const CollisionGeometry< double > *o1, const Transform3< double > &tf1, const CollisionGeometry< double > *o2, const Transform3< double > &tf2, const DistanceRequest< double > &request, DistanceResult< double > &result)
tesseract_geometry::Plane::ConstPtr
std::shared_ptr< const Plane > ConstPtr
tesseract_collision::ContactResult::subshape_id
std::array< int, 2 > subshape_id
Some shapes like octomap and mesh have subshape (boxes and triangles)
Definition: types.h:96
tesseract_collision::ObjectPairKey
std::pair< std::string, std::string > ObjectPairKey
Definition: common.h:40
fcl_collision_geometry_cache.h
This is a static cache mapping tesseract geometry shared pointers to fcl collision geometry to avoid ...
tesseract_geometry::Mesh::ConstPtr
std::shared_ptr< const Mesh > ConstPtr
tesseract_collision::tesseract_collision_fcl::KinematicFilter
@ KinematicFilter
Definition: fcl_utils.h:69
tesseract_collision::tesseract_collision_fcl::distanceCallback
bool distanceCallback(fcl::CollisionObjectd *o1, fcl::CollisionObjectd *o2, void *data)
Definition: fcl_utils.cpp:287
tesseract_geometry::GeometryType::PLANE
@ PLANE
fcl::Contact::pos
Vector3< S > pos
tesseract_geometry::GeometryType::SPHERE
@ SPHERE
fcl::CollisionRequest
fcl::CollisionResult::numContacts
size_t numContacts() const
tesseract_common::VectorVector3d
std::vector< Eigen::Vector3d > VectorVector3d
tesseract_geometry::GeometryType::CAPSULE
@ CAPSULE
tesseract_collision::tesseract_collision_fcl::createShapePrimitive
CollisionGeometryPtr createShapePrimitive(const CollisionShapeConstPtr &geom)
Definition: fcl_utils.cpp:208
tesseract_collision::tesseract_collision_fcl
Definition: fcl_collision_geometry_cache.h:42
tesseract_collision::CollisionShapesConst
std::vector< CollisionShapeConstPtr > CollisionShapesConst
Definition: types.h:51
fcl::collide
template FCL_EXPORT std::size_t collide(const CollisionGeometry< double > *o1, const Transform3< double > &tf1, const CollisionGeometry< double > *o2, const Transform3< double > &tf2, const CollisionRequest< double > &request, CollisionResult< double > &result)
fcl::DistanceResult::min_distance
S min_distance
cone-inl.h
tesseract_collision::ContactResult::type_id
std::array< int, 2 > type_id
A user defined type id that is added to the contact shapes.
Definition: types.h:90
TESSERACT_COMMON_IGNORE_WARNINGS_POP
Definition: create_convex_hull.cpp:37
fcl::CollisionObject::getUserData
void * getUserData() const
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::CollisionObjectWrapper
CollisionObjectWrapper()=default
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::m_collisionFilterGroup
short int m_collisionFilterGroup
Definition: fcl_utils.h:91
fcl_utils.h
Tesseract ROS FCL Utility Functions.
tesseract_geometry::Octree::ConstPtr
std::shared_ptr< const Octree > ConstPtr
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::name_
std::string name_
Definition: fcl_utils.h:173
tesseract_collision::ContactTestType::FIRST
@ FIRST
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper
This is a Tesseract link collision object wrapper which add items specific to tesseract....
Definition: fcl_utils.h:77
tesseract_collision::tesseract_collision_fcl::createShapePrimitiveHelper
CollisionGeometryPtr createShapePrimitiveHelper(const CollisionShapeConstPtr &geom)
Definition: fcl_utils.cpp:155
tesseract_collision::ContactResult::distance
EIGEN_MAKE_ALIGNED_OPERATOR_NEW double distance
The distance between two links.
Definition: types.h:88
tesseract_collision::CollisionShapeConstPtr
std::shared_ptr< const tesseract_geometry::Geometry > CollisionShapeConstPtr
Definition: types.h:49
fcl::Contact::penetration_depth
S penetration_depth
fcl::CollisionResult::getContact
const Contact< S > & getContact(size_t i) const
tesseract_geometry::GeometryType::BOX
@ BOX
tesseract_geometry::ConvexMesh::ConstPtr
std::shared_ptr< const ConvexMesh > ConstPtr
tesseract_collision::tesseract_collision_fcl::FCLCollisionGeometryCache::insert
static void insert(const std::shared_ptr< const tesseract_geometry::Geometry > &key, const std::shared_ptr< fcl::CollisionGeometryd > &value)
Insert a new entry into the cache.
Definition: fcl_collision_geometry_cache.cpp:40
tesseract_common::makeOrderedLinkPair
LinkNamesPair makeOrderedLinkPair(const std::string &link_name1, const std::string &link_name2)
tesseract_collision::ContactResult::transform
std::array< Eigen::Isometry3d, 2 > transform
The transform of link in world coordinates.
Definition: types.h:102
tesseract_geometry::GeometryType::OCTREE
@ OCTREE
BVH_model-inl.h
tesseract_collision::tesseract_collision_fcl::FCLCollisionObjectWrapper
This is a wrapper around FCL Collision Object Class which allows you to expand the AABB by the contac...
Definition: fcl_collision_object_wrapper.h:41
tesseract_collision::ContactResult::nearest_points
std::array< Eigen::Vector3d, 2 > nearest_points
The nearest point on both links in world coordinates.
Definition: types.h:98
tesseract_geometry::GeometryType::CONVEX_MESH
@ CONVEX_MESH
tesseract_geometry::Cylinder::ConstPtr
std::shared_ptr< const Cylinder > ConstPtr
tesseract_collision::ContactResult::nearest_points_local
std::array< Eigen::Vector3d, 2 > nearest_points_local
The nearest point on both links in local(link) coordinates.
Definition: types.h:100
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::m_collisionFilterMask
short int m_collisionFilterMask
Definition: fcl_utils.h:92
macros.h
tesseract_collision::processResult
ContactResult * processResult(ContactTestData &cdata, ContactResult &contact, const std::pair< std::string, std::string > &key, bool found)
processResult Processes the ContactResult based on the information in the ContactTestData
Definition: common.cpp:112
tesseract_collision::ContactResult::link_names
std::array< std::string, 2 > link_names
The two links that are in contact.
Definition: types.h:92
fcl::CollisionObject< double >
tesseract_collision::ContactResult
Definition: types.h:81
capsule-inl.h
tesseract_geometry::Capsule::ConstPtr
std::shared_ptr< const Capsule > ConstPtr
tesseract_geometry::OctreeSubType::BOX
@ BOX
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::shape_poses_
tesseract_common::VectorIsometry3d shape_poses_
Definition: fcl_utils.h:177
tesseract_collision::tesseract_collision_fcl::CollisionObjectWrapper::collision_objects_raw_
std::vector< CollisionObjectRawPtr > collision_objects_raw_
The raw pointer is also stored because FCL accepts vectors for batch process. Note: They are updating...
Definition: fcl_utils.h:184


tesseract_collision
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:01:52