hpp-fcl  3.0.0
HPP fork of FCL -- The Flexible Collision Library
shape_shape_contact_patch_func.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2024, INRIA
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
37 #ifndef HPP_FCL_INTERNAL_SHAPE_SHAPE_CONTACT_PATCH_FUNC_H
38 #define HPP_FCL_INTERNAL_SHAPE_SHAPE_CONTACT_PATCH_FUNC_H
39 
40 #include "hpp/fcl/collision_data.h"
45 
46 namespace hpp {
47 namespace fcl {
48 
52 template <typename ShapeType1, typename ShapeType2>
54  static void run(const CollisionGeometry* o1, const Transform3f& tf1,
55  const CollisionGeometry* o2, const Transform3f& tf2,
56  const CollisionResult& collision_result,
57  const ContactPatchSolver* csolver,
58  const ContactPatchRequest& request,
59  ContactPatchResult& result) {
60  // Note: see specializations for Plane and Halfspace below.
61  if (!collision_result.isCollision()) {
62  return;
63  }
65  result.check(request),
66  "The contact patch result and request are incompatible (issue of "
67  "contact patch size or maximum number of contact patches). Make sure "
68  "result is initialized with request.",
69  std::logic_error);
70 
71  const ShapeType1& s1 = static_cast<const ShapeType1&>(*o1);
72  const ShapeType2& s2 = static_cast<const ShapeType2&>(*o2);
73  for (size_t i = 0; i < collision_result.numContacts(); ++i) {
74  if (i >= request.max_num_patch) {
75  break;
76  }
77  csolver->setSupportGuess(collision_result.cached_support_func_guess);
78  const Contact& contact = collision_result.getContact(i);
79  ContactPatch& contact_patch = result.getUnusedContactPatch();
80  csolver->computePatch(s1, tf1, s2, tf2, contact, contact_patch);
81  }
82  }
83 };
84 
90 template <bool InvertShapes, typename OtherShapeType, typename PlaneOrHalfspace>
91 void computePatchPlaneOrHalfspace(const OtherShapeType& s1,
92  const Transform3f& tf1,
93  const PlaneOrHalfspace& s2,
94  const Transform3f& tf2,
95  const ContactPatchSolver* csolver,
96  const Contact& contact,
97  ContactPatch& contact_patch) {
100  constructContactPatchFrameFromContact(contact, contact_patch);
102  // Only one point of contact; it has already been computed.
103  contact_patch.addPoint(contact.pos);
104  return;
105  }
106 
107  // We only need to compute the support set in the direction of the normal.
108  // We need to temporarily express the patch in the local frame of shape1.
109  SupportSet& support_set = csolver->support_set_shape1;
110  support_set.tf.rotation().noalias() =
111  tf1.rotation().transpose() * contact_patch.tf.rotation();
112  support_set.tf.translation().noalias() =
113  tf1.rotation().transpose() *
114  (contact_patch.tf.translation() - tf1.translation());
115 
116  // Note: for now, taking into account swept-sphere radius does not change
117  // anything to the support set computations. However it will be used in the
118  // future if we want to store the offsets to the support plane for each point
119  // in a support set.
121  if (InvertShapes) {
122  support_set.direction = ContactPatch::PatchDirection::INVERTED;
123  details::getShapeSupportSet<SupportOptions::WithSweptSphere>(
124  &s1, support_set, csolver->support_guess[1], csolver->supports_data[1],
125  csolver->num_samples_curved_shapes, csolver->patch_tolerance);
126  } else {
127  support_set.direction = ContactPatch::PatchDirection::DEFAULT;
128  details::getShapeSupportSet<SupportOptions::WithSweptSphere>(
129  &s1, support_set, csolver->support_guess[0], csolver->supports_data[0],
130  csolver->num_samples_curved_shapes, csolver->patch_tolerance);
131  }
132  csolver->getResult(contact, &(support_set.points()), contact_patch);
133 }
134 
135 #define PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH(PlaneOrHspace) \
136  template <typename OtherShapeType> \
137  struct ComputeShapeShapeContactPatch<OtherShapeType, PlaneOrHspace> { \
138  static void run(const CollisionGeometry* o1, const Transform3f& tf1, \
139  const CollisionGeometry* o2, const Transform3f& tf2, \
140  const CollisionResult& collision_result, \
141  const ContactPatchSolver* csolver, \
142  const ContactPatchRequest& request, \
143  ContactPatchResult& result) { \
144  if (!collision_result.isCollision()) { \
145  return; \
146  } \
147  HPP_FCL_ASSERT( \
148  result.check(request), \
149  "The contact patch result and request are incompatible (issue of " \
150  "contact patch size or maximum number of contact patches). Make " \
151  "sure " \
152  "result is initialized with request.", \
153  std::logic_error); \
154  \
155  const OtherShapeType& s1 = static_cast<const OtherShapeType&>(*o1); \
156  const PlaneOrHspace& s2 = static_cast<const PlaneOrHspace&>(*o2); \
157  for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
158  if (i >= request.max_num_patch) { \
159  break; \
160  } \
161  csolver->setSupportGuess(collision_result.cached_support_func_guess); \
162  const Contact& contact = collision_result.getContact(i); \
163  ContactPatch& contact_patch = result.getUnusedContactPatch(); \
164  computePatchPlaneOrHalfspace<false, OtherShapeType, PlaneOrHspace>( \
165  s1, tf1, s2, tf2, csolver, contact, contact_patch); \
166  } \
167  } \
168  }; \
169  \
170  template <typename OtherShapeType> \
171  struct ComputeShapeShapeContactPatch<PlaneOrHspace, OtherShapeType> { \
172  static void run(const CollisionGeometry* o1, const Transform3f& tf1, \
173  const CollisionGeometry* o2, const Transform3f& tf2, \
174  const CollisionResult& collision_result, \
175  const ContactPatchSolver* csolver, \
176  const ContactPatchRequest& request, \
177  ContactPatchResult& result) { \
178  if (!collision_result.isCollision()) { \
179  return; \
180  } \
181  HPP_FCL_ASSERT( \
182  result.check(request), \
183  "The contact patch result and request are incompatible (issue of " \
184  "contact patch size or maximum number of contact patches). Make " \
185  "sure " \
186  "result is initialized with request.", \
187  std::logic_error); \
188  \
189  const PlaneOrHspace& s1 = static_cast<const PlaneOrHspace&>(*o1); \
190  const OtherShapeType& s2 = static_cast<const OtherShapeType&>(*o2); \
191  for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
192  if (i >= request.max_num_patch) { \
193  break; \
194  } \
195  csolver->setSupportGuess(collision_result.cached_support_func_guess); \
196  const Contact& contact = collision_result.getContact(i); \
197  ContactPatch& contact_patch = result.getUnusedContactPatch(); \
198  computePatchPlaneOrHalfspace<true, OtherShapeType, PlaneOrHspace>( \
199  s2, tf2, s1, tf1, csolver, contact, contact_patch); \
200  } \
201  } \
202  };
203 
206 
207 #define PLANE_HSPACE_CONTACT_PATCH(PlaneOrHspace1, PlaneOrHspace2) \
208  template <> \
209  struct ComputeShapeShapeContactPatch<PlaneOrHspace1, PlaneOrHspace2> { \
210  static void run(const CollisionGeometry* o1, const Transform3f& tf1, \
211  const CollisionGeometry* o2, const Transform3f& tf2, \
212  const CollisionResult& collision_result, \
213  const ContactPatchSolver* csolver, \
214  const ContactPatchRequest& request, \
215  ContactPatchResult& result) { \
216  HPP_FCL_UNUSED_VARIABLE(o1); \
217  HPP_FCL_UNUSED_VARIABLE(tf1); \
218  HPP_FCL_UNUSED_VARIABLE(o2); \
219  HPP_FCL_UNUSED_VARIABLE(tf2); \
220  HPP_FCL_UNUSED_VARIABLE(csolver); \
221  if (!collision_result.isCollision()) { \
222  return; \
223  } \
224  HPP_FCL_ASSERT( \
225  result.check(request), \
226  "The contact patch result and request are incompatible (issue of " \
227  "contact patch size or maximum number of contact patches). Make " \
228  "sure " \
229  "result is initialized with request.", \
230  std::logic_error); \
231  \
232  for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
233  if (i >= request.max_num_patch) { \
234  break; \
235  } \
236  const Contact& contact = collision_result.getContact(i); \
237  ContactPatch& contact_patch = result.getUnusedContactPatch(); \
238  constructContactPatchFrameFromContact(contact, contact_patch); \
239  contact_patch.addPoint(contact.pos); \
240  } \
241  } \
242  };
243 
248 
249 #undef PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH
250 #undef PLANE_HSPACE_CONTACT_PATCH
251 
252 template <typename ShapeType1, typename ShapeType2>
254  const CollisionGeometry* o2, const Transform3f& tf2,
255  const CollisionResult& collision_result,
256  const ContactPatchSolver* csolver,
257  const ContactPatchRequest& request,
258  ContactPatchResult& result) {
260  o1, tf1, o2, tf2, collision_result, csolver, request, result);
261 }
262 
263 } // namespace fcl
264 } // namespace hpp
265 
266 #endif
The geometry for the object for collision or distance computation.
Definition: collision_object.h:95
Half Space: this is equivalent to the Plane in ODE. A Half space has a priviledged direction: the dir...
Definition: geometric_shapes.h:885
Infinite plane. A plane can be viewed as two half spaces; it has no priviledged direction....
Definition: geometric_shapes.h:976
Simple transform class used locally by InterpMotion.
Definition: transform.h:56
const Matrix3f & rotation() const
get rotation
Definition: transform.h:114
const Vec3f & translation() const
get translation
Definition: transform.h:105
#define HPP_FCL_ASSERT(check, message, exception)
Definition: fwd.hh:82
#define HPP_FCL_UNUSED_VARIABLE(var)
Definition: fwd.hh:56
SupportOptions
Options for the computation of support points. NoSweptSphere option is used when the support function...
Definition: support_functions.h:59
void computePatchPlaneOrHalfspace(const OtherShapeType &s1, const Transform3f &tf1, const PlaneOrHalfspace &s2, const Transform3f &tf2, const ContactPatchSolver *csolver, const Contact &contact, ContactPatch &contact_patch)
Computes the contact patch between a Plane/Halfspace and another shape.
Definition: shape_shape_contact_patch_func.h:91
void constructContactPatchFrameFromContact(const Contact &contact, ContactPatch &contact_patch)
Construct a frame from a Contact's position and normal. Because both Contact's position and normal ar...
Definition: collision_data.h:706
void ShapeShapeContactPatch(const CollisionGeometry *o1, const Transform3f &tf1, const CollisionGeometry *o2, const Transform3f &tf2, const CollisionResult &collision_result, const ContactPatchSolver *csolver, const ContactPatchRequest &request, ContactPatchResult &result)
Definition: shape_shape_contact_patch_func.h:253
Main namespace.
Definition: broadphase_bruteforce.h:44
#define PLANE_HSPACE_CONTACT_PATCH(PlaneOrHspace1, PlaneOrHspace2)
Definition: shape_shape_contact_patch_func.h:207
#define PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH(PlaneOrHspace)
Definition: shape_shape_contact_patch_func.h:135
collision result
Definition: collision_data.h:391
const Contact & getContact(size_t i) const
get the i-th contact calculated
Definition: collision_data.h:449
bool isCollision() const
return binary collision result
Definition: collision_data.h:443
size_t numContacts() const
number of contacts found
Definition: collision_data.h:446
Shape-shape contact patch computation. Assumes that csolver and the ContactPatchResult have already b...
Definition: shape_shape_contact_patch_func.h:53
static void run(const CollisionGeometry *o1, const Transform3f &tf1, const CollisionGeometry *o2, const Transform3f &tf2, const CollisionResult &collision_result, const ContactPatchSolver *csolver, const ContactPatchRequest &request, ContactPatchResult &result)
Definition: shape_shape_contact_patch_func.h:54
Request for a contact patch computation.
Definition: collision_data.h:726
size_t max_num_patch
Maximum number of contact patches that will be computed.
Definition: collision_data.h:728
Result for a contact patch computation.
Definition: collision_data.h:824
bool check(const ContactPatchRequest &request) const
Return true if this ContactPatchResult is aligned with the ContactPatchRequest given as input.
Definition: collision_data.h:933
ContactPatchRef getUnusedContactPatch()
Returns a new unused contact patch from the internal data vector.
Definition: collision_data.h:864
Solver to compute contact patches, i.e. the intersection between two contact surfaces projected onto ...
Definition: contact_patch_solver.h:60
void getResult(const Contact &contact, const ContactPatch::Polygon *result, ContactPatch &contact_patch) const
Retrieve result, adds a post-processing step if result has bigger size than this->max_patch_size.
Definition: contact_patch_solver.hxx:360
FCL_REAL patch_tolerance
Tolerance below which points are added to the shapes support sets. See ContactPatchRequest::m_patch_t...
Definition: contact_patch_solver.h:101
void computePatch(const ShapeType1 &s1, const Transform3f &tf1, const ShapeType2 &s2, const Transform3f &tf2, const Contact &contact, ContactPatch &contact_patch) const
Main API of the solver: compute a contact patch from a contact between shapes s1 and s2....
Definition: contact_patch_solver.hxx:77
support_func_guess_t support_guess
Guess for the support sets computation.
Definition: contact_patch_solver.h:113
SupportSet support_set_shape1
Holder for support set of shape 1, used for internal computation. After computePatch has been called,...
Definition: contact_patch_solver.h:117
size_t num_samples_curved_shapes
Number of points sampled for Cone and Cylinder when the normal is orthogonal to the shapes' basis....
Definition: contact_patch_solver.h:97
void setSupportGuess(const support_func_guess_t guess) const
Sets the support guess used during support set computation of shapes s1 and s2.
Definition: contact_patch_solver.h:153
std::array< ShapeSupportData, 2 > supports_data
Temporary data to compute the support sets on each shape.
Definition: contact_patch_solver.h:110
This structure allows to encode contact patches. A contact patch is defined by a set of points belong...
Definition: collision_data.h:512
void addPoint(const Vec3f &point_3d)
Add a 3D point to the set, expressed in the world frame.
Definition: collision_data.h:584
Transform3f tf
Frame of the set, expressed in the world coordinates. The z-axis of the frame's rotation is the conta...
Definition: collision_data.h:518
PatchDirection direction
Direction of this contact patch.
Definition: collision_data.h:532
Polygon & points()
Getter for the 2D points in the set.
Definition: collision_data.h:616
Contact information returned by collision.
Definition: collision_data.h:59
Vec3f pos
contact position, in world space
Definition: collision_data.h:103
support_func_guess_t cached_support_func_guess
stores the last support function vertex index, when relevant.
Definition: collision_data.h:281
Definition: geometric_shapes_traits.h:56