coal 3.0.1
Coal, The Collision Detection Library. Previously known as HPP-FCL, fork of FCL -- The Flexible Collision Library
Loading...
Searching...
No Matches
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 COAL_INTERNAL_SHAPE_SHAPE_CONTACT_PATCH_FUNC_H
38#define COAL_INTERNAL_SHAPE_SHAPE_CONTACT_PATCH_FUNC_H
39
40#include "coal/collision_data.h"
45
46#include "coal/tracy.hh"
47
48namespace coal {
49
53template <typename ShapeType1, typename ShapeType2>
55 static void run(const CollisionGeometry* o1, const Transform3s& tf1,
56 const CollisionGeometry* o2, const Transform3s& tf2,
57 const CollisionResult& collision_result,
58 const ContactPatchSolver* csolver,
59 const ContactPatchRequest& request,
60 ContactPatchResult& result) {
61 // Note: see specializations for Plane and Halfspace below.
62 if (!collision_result.isCollision()) {
63 return;
64 }
66 result.check(request),
67 "The contact patch result and request are incompatible (issue of "
68 "contact patch size or maximum number of contact patches). Make sure "
69 "result is initialized with request.",
70 std::logic_error);
71
72 const ShapeType1& s1 = static_cast<const ShapeType1&>(*o1);
73 const ShapeType2& s2 = static_cast<const ShapeType2&>(*o2);
74 for (size_t i = 0; i < collision_result.numContacts(); ++i) {
75 if (i >= request.max_num_patch) {
76 break;
77 }
78 csolver->setSupportGuess(collision_result.cached_support_func_guess);
79 const Contact& contact = collision_result.getContact(i);
80 ContactPatch& contact_patch = result.getUnusedContactPatch();
81 csolver->computePatch(s1, tf1, s2, tf2, contact, contact_patch);
82 }
83 }
84};
85
91template <bool InvertShapes, typename OtherShapeType, typename PlaneOrHalfspace>
92void computePatchPlaneOrHalfspace(const OtherShapeType& s1,
93 const Transform3s& tf1,
94 const PlaneOrHalfspace& s2,
95 const Transform3s& tf2,
96 const ContactPatchSolver* csolver,
97 const Contact& contact,
98 ContactPatch& contact_patch) {
101 constructContactPatchFrameFromContact(contact, contact_patch);
103 // Only one point of contact; it has already been computed.
104 contact_patch.addPoint(contact.pos);
105 return;
106 }
107
108 // We only need to compute the support set in the direction of the normal.
109 // We need to temporarily express the patch in the local frame of shape1.
110 SupportSet& support_set = csolver->support_set_shape1;
111 support_set.tf.rotation().noalias() =
112 tf1.rotation().transpose() * contact_patch.tf.rotation();
113 support_set.tf.translation().noalias() =
114 tf1.rotation().transpose() *
115 (contact_patch.tf.translation() - tf1.translation());
116
117 // Note: for now, taking into account swept-sphere radius does not change
118 // anything to the support set computations. However it will be used in the
119 // future if we want to store the offsets to the support plane for each point
120 // in a support set.
121 using SupportOptions = details::SupportOptions;
122 if (InvertShapes) {
124 details::getShapeSupportSet<SupportOptions::WithSweptSphere>(
125 &s1, support_set, csolver->support_guess[1], csolver->supports_data[1],
126 csolver->num_samples_curved_shapes, csolver->patch_tolerance);
127 } else {
129 details::getShapeSupportSet<SupportOptions::WithSweptSphere>(
130 &s1, support_set, csolver->support_guess[0], csolver->supports_data[0],
131 csolver->num_samples_curved_shapes, csolver->patch_tolerance);
132 }
133 csolver->getResult(contact, &(support_set.points()), contact_patch);
134}
135
136#define PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH(PlaneOrHspace) \
137 template <typename OtherShapeType> \
138 struct ComputeShapeShapeContactPatch<OtherShapeType, PlaneOrHspace> { \
139 static void run(const CollisionGeometry* o1, const Transform3s& tf1, \
140 const CollisionGeometry* o2, const Transform3s& tf2, \
141 const CollisionResult& collision_result, \
142 const ContactPatchSolver* csolver, \
143 const ContactPatchRequest& request, \
144 ContactPatchResult& result) { \
145 COAL_TRACY_ZONE_SCOPED_N( \
146 "coal::ComputeShapeShapeContactPatch<OtherShapeType, " \
147 "PlaneOrHspace>::run"); \
148 if (!collision_result.isCollision()) { \
149 return; \
150 } \
151 COAL_ASSERT( \
152 result.check(request), \
153 "The contact patch result and request are incompatible (issue of " \
154 "contact patch size or maximum number of contact patches). Make " \
155 "sure " \
156 "result is initialized with request.", \
157 std::logic_error); \
158 \
159 const OtherShapeType& s1 = static_cast<const OtherShapeType&>(*o1); \
160 const PlaneOrHspace& s2 = static_cast<const PlaneOrHspace&>(*o2); \
161 for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
162 if (i >= request.max_num_patch) { \
163 break; \
164 } \
165 csolver->setSupportGuess(collision_result.cached_support_func_guess); \
166 const Contact& contact = collision_result.getContact(i); \
167 ContactPatch& contact_patch = result.getUnusedContactPatch(); \
168 computePatchPlaneOrHalfspace<false, OtherShapeType, PlaneOrHspace>( \
169 s1, tf1, s2, tf2, csolver, contact, contact_patch); \
170 } \
171 } \
172 }; \
173 \
174 template <typename OtherShapeType> \
175 struct ComputeShapeShapeContactPatch<PlaneOrHspace, OtherShapeType> { \
176 static void run(const CollisionGeometry* o1, const Transform3s& tf1, \
177 const CollisionGeometry* o2, const Transform3s& tf2, \
178 const CollisionResult& collision_result, \
179 const ContactPatchSolver* csolver, \
180 const ContactPatchRequest& request, \
181 ContactPatchResult& result) { \
182 COAL_TRACY_ZONE_SCOPED_N( \
183 "coal::ComputeShapeShapeContactPatch<PlaneOrHspace, " \
184 "OtherShapeType>::run"); \
185 if (!collision_result.isCollision()) { \
186 return; \
187 } \
188 COAL_ASSERT( \
189 result.check(request), \
190 "The contact patch result and request are incompatible (issue of " \
191 "contact patch size or maximum number of contact patches). Make " \
192 "sure " \
193 "result is initialized with request.", \
194 std::logic_error); \
195 \
196 const PlaneOrHspace& s1 = static_cast<const PlaneOrHspace&>(*o1); \
197 const OtherShapeType& s2 = static_cast<const OtherShapeType&>(*o2); \
198 for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
199 if (i >= request.max_num_patch) { \
200 break; \
201 } \
202 csolver->setSupportGuess(collision_result.cached_support_func_guess); \
203 const Contact& contact = collision_result.getContact(i); \
204 ContactPatch& contact_patch = result.getUnusedContactPatch(); \
205 computePatchPlaneOrHalfspace<true, OtherShapeType, PlaneOrHspace>( \
206 s2, tf2, s1, tf1, csolver, contact, contact_patch); \
207 } \
208 } \
209 };
210
213
214#define PLANE_HSPACE_CONTACT_PATCH(PlaneOrHspace1, PlaneOrHspace2) \
215 template <> \
216 struct ComputeShapeShapeContactPatch<PlaneOrHspace1, PlaneOrHspace2> { \
217 static void run(const CollisionGeometry* o1, const Transform3s& tf1, \
218 const CollisionGeometry* o2, const Transform3s& tf2, \
219 const CollisionResult& collision_result, \
220 const ContactPatchSolver* csolver, \
221 const ContactPatchRequest& request, \
222 ContactPatchResult& result) { \
223 COAL_UNUSED_VARIABLE(o1); \
224 COAL_UNUSED_VARIABLE(tf1); \
225 COAL_UNUSED_VARIABLE(o2); \
226 COAL_UNUSED_VARIABLE(tf2); \
227 COAL_UNUSED_VARIABLE(csolver); \
228 if (!collision_result.isCollision()) { \
229 return; \
230 } \
231 COAL_ASSERT( \
232 result.check(request), \
233 "The contact patch result and request are incompatible (issue of " \
234 "contact patch size or maximum number of contact patches). Make " \
235 "sure " \
236 "result is initialized with request.", \
237 std::logic_error); \
238 \
239 for (size_t i = 0; i < collision_result.numContacts(); ++i) { \
240 if (i >= request.max_num_patch) { \
241 break; \
242 } \
243 const Contact& contact = collision_result.getContact(i); \
244 ContactPatch& contact_patch = result.getUnusedContactPatch(); \
245 constructContactPatchFrameFromContact(contact, contact_patch); \
246 contact_patch.addPoint(contact.pos); \
247 } \
248 } \
249 };
250
255
256#undef PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH
257#undef PLANE_HSPACE_CONTACT_PATCH
258
259template <typename ShapeType1, typename ShapeType2>
261 const CollisionGeometry* o2, const Transform3s& tf2,
262 const CollisionResult& collision_result,
263 const ContactPatchSolver* csolver,
264 const ContactPatchRequest& request,
265 ContactPatchResult& result) {
266 COAL_TRACY_ZONE_SCOPED_N("coal::ShapeShapeContactPatch");
268 o1, tf1, o2, tf2, collision_result, csolver, request, result);
269}
270
271} // namespace coal
272
273#endif
The geometry for the object for collision or distance computation.
Definition collision_object.h:96
Half Space: this is equivalent to the Plane in ODE. A Half space has a priviledged direction: the dir...
Definition geometric_shapes.h:963
Infinite plane. A plane can be viewed as two half spaces; it has no priviledged direction....
Definition geometric_shapes.h:1054
Simple transform class used locally by InterpMotion.
Definition transform.h:55
const Matrix3s & rotation() const
get rotation
Definition transform.h:113
const Vec3s & translation() const
get translation
Definition transform.h:104
#define COAL_ASSERT(check, message, exception)
Definition fwd.hh:82
#define COAL_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_data.h:56
Main namespace.
Definition broadphase_bruteforce.h:44
void computePatchPlaneOrHalfspace(const OtherShapeType &s1, const Transform3s &tf1, const PlaneOrHalfspace &s2, const Transform3s &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:92
void ShapeShapeContactPatch(const CollisionGeometry *o1, const Transform3s &tf1, const CollisionGeometry *o2, const Transform3s &tf2, const CollisionResult &collision_result, const ContactPatchSolver *csolver, const ContactPatchRequest &request, ContactPatchResult &result)
Definition shape_shape_contact_patch_func.h:260
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:703
#define PLANE_HSPACE_CONTACT_PATCH(PlaneOrHspace1, PlaneOrHspace2)
Definition shape_shape_contact_patch_func.h:214
#define PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH(PlaneOrHspace)
Definition shape_shape_contact_patch_func.h:136
collision result
Definition collision_data.h:390
size_t numContacts() const
number of contacts found
Definition collision_data.h:445
bool isCollision() const
return binary collision result
Definition collision_data.h:442
const Contact & getContact(size_t i) const
get the i-th contact calculated
Definition collision_data.h:448
Shape-shape contact patch computation. Assumes that csolver and the ContactPatchResult have already b...
Definition shape_shape_contact_patch_func.h:54
static void run(const CollisionGeometry *o1, const Transform3s &tf1, const CollisionGeometry *o2, const Transform3s &tf2, const CollisionResult &collision_result, const ContactPatchSolver *csolver, const ContactPatchRequest &request, ContactPatchResult &result)
Definition shape_shape_contact_patch_func.h:55
Request for a contact patch computation.
Definition collision_data.h:723
size_t max_num_patch
Maximum number of contact patches that will be computed.
Definition collision_data.h:725
Result for a contact patch computation.
Definition collision_data.h:821
ContactPatchRef getUnusedContactPatch()
Returns a new unused contact patch from the internal data vector.
Definition collision_data.h:861
bool check(const ContactPatchRequest &request) const
Return true if this ContactPatchResult is aligned with the ContactPatchRequest given as input.
Definition collision_data.h:930
Solver to compute contact patches, i.e. the intersection between two contact surfaces projected onto ...
Definition contact_patch_solver.h:59
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:96
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:152
std::array< ShapeSupportData, 2 > supports_data
Temporary data to compute the support sets on each shape.
Definition contact_patch_solver.h:109
Scalar patch_tolerance
Tolerance below which points are added to the shapes support sets. See ContactPatchRequest::m_patch_t...
Definition contact_patch_solver.h:100
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:116
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:362
support_func_guess_t support_guess
Guess for the support sets computation.
Definition contact_patch_solver.h:112
void computePatch(const ShapeType1 &s1, const Transform3s &tf1, const ShapeType2 &s2, const Transform3s &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:78
This structure allows to encode contact patches. A contact patch is defined by a set of points belong...
Definition collision_data.h:511
PatchDirection direction
Direction of this contact patch.
Definition collision_data.h:531
@ DEFAULT
Definition collision_data.h:528
@ INVERTED
Definition collision_data.h:528
Polygon & points()
Getter for the 2D points in the set.
Definition collision_data.h:615
void addPoint(const Vec3s &point_3d)
Add a 3D point to the set, expressed in the world frame.
Definition collision_data.h:583
Transform3s 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:517
Contact information returned by collision.
Definition collision_data.h:58
Vec3s pos
contact position, in world space
Definition collision_data.h:102
support_func_guess_t cached_support_func_guess
stores the last support function vertex index, when relevant.
Definition collision_data.h:280
Definition geometric_shapes_traits.h:55
#define COAL_TRACY_ZONE_SCOPED_N(x)
Definition tracy.hh:26