-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
distance_to_shape_callback.h
293 lines (244 loc) · 11.9 KB
/
distance_to_shape_callback.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#pragma once
#include <unordered_map>
#include <vector>
#include <fcl/fcl.h>
#include "drake/common/eigen_types.h"
#include "drake/common/nice_type_name.h"
#include "drake/geometry/geometry_ids.h"
#include "drake/geometry/proximity/collision_filter.h"
#include "drake/geometry/proximity/proximity_utilities.h"
#include "drake/geometry/query_results/signed_distance_pair.h"
#include "drake/math/rigid_transform.h"
/** @file Provides the structures and logic to support signed distance queries
between shapes. */
namespace drake {
namespace geometry {
namespace internal {
namespace shape_distance {
/* Supporting data for the shape-to-shape signed distance callback (see
Callback below). It includes:
- A collision filter instance.
- The T-valued poses of _all_ geometries in the corresponding SceneGraph
keyed on their GeometryId.
- A vector of distance results -- one instance of SignedDistancePair for
every supported geometry which lies within the threshold.
@tparam T The computation scalar. */
template <typename T>
struct CallbackData {
/* Constructs the mostly-specified callback data. The fcl distance request is
left in its default constructed state for subsequent configuration. The
values are as described in the class documentation. The parameters are almost
all aliased in the data and require the aliased parameters to remain valid at
least as long as the CallbackData instance.
@param collision_filter_in The collision filter system. Aliased.
@param X_WGs_in The T-valued poses. Aliased.
@param max_distance_in The maximum distance at which a pair is
reported.
@param nearest_pairs_in[out] The output results. Aliased. */
CallbackData(
const CollisionFilter* collision_filter_in,
const std::unordered_map<GeometryId, math::RigidTransform<T>>* X_WGs_in,
double max_distance_in,
std::vector<SignedDistancePair<T>>* nearest_pairs_in)
: collision_filter(*collision_filter_in),
X_WGs(*X_WGs_in),
max_distance(max_distance_in),
nearest_pairs(*nearest_pairs_in) {
DRAKE_DEMAND(collision_filter_in != nullptr);
DRAKE_DEMAND(X_WGs_in != nullptr);
DRAKE_DEMAND(nearest_pairs_in != nullptr);
}
/* The collision filter system. */
const CollisionFilter& collision_filter;
/* The T-valued poses of all geometries. */
const std::unordered_map<GeometryId, math::RigidTransform<T>>& X_WGs;
/* The maximum distance at which a pair's distance will be reported. */
const double max_distance;
/* The distance query parameters. */
fcl::DistanceRequestd request;
/* The results of the distance query. */
std::vector<SignedDistancePair<T>>& nearest_pairs{};
};
/* A functor to support ComputeNarrowPhaseDistance(). It computes the signed
distance between a supported pair of geometries. Each overload to the call
operator reports the signed distance (encoded in SignedDistancePair<T>)
between the two given geometry arguments using the functor's stored poses.
@tparam T Computation scalar type. */
template <typename T>
class DistancePairGeometry {
public:
/* Constructs the functor caching all parameters that do _not_ depend on
the shape type.
@param id_A Identifier of the first geometry passed to operator().
@param id_B Identifier of the second geometry passed to operator().
@param X_WA Pose of geometry A in the world frame.
@param X_WB Pose of geometry B in the world frame
@param[out] result The signed distance values are stored here. */
DistancePairGeometry(const GeometryId& id_A, const GeometryId& id_B,
const math::RigidTransform<T>& X_WA,
const math::RigidTransform<T>& X_WB,
SignedDistancePair<T>* result)
: id_A_(id_A), id_B_(id_B), X_WA_(X_WA), X_WB_(X_WB), result_(result) {
DRAKE_ASSERT(result != nullptr);
}
/* @name Overloads in support of sphere-shape computation
Given a sphere A centered at Ao with radius r and another geometry B,
we want to compute
1. φ_A,B = the signed distance between the two objects, which is positive
for non-overlapping objects and equals the negative penetration depth
for overlapping objects.
2. Na, Nb = a pair of witness points, Na ∈ ∂A, Nb ∈ ∂B (not necessarily
unique), |Na-Nb| = |φ_A,B|.
Define these functions: (available from SignedDistanceToPoint)
φ_B:ℝ³→ℝ, φ_B(p) = signed distance to point p from B.
η_B:ℝ³→ℝ³, η_B(p) = a nearest point to p on the boundary ∂B (not
necessarily unique).
∇φ_B:ℝ³→ℝ³, ∇φ_B(p) = gradient vector of φ_B with respect to p.
It has unit length by construction.
Algorithm:
1. φ_A,B = φ_B(Ao) - r
2. Nb = η_B(Ao)
3. Na = Ao - r * ∇φ_B(Ao) */
//@{
void operator()(const fcl::Sphered& sphere_A, const fcl::Sphered& sphere_B);
void operator()(const fcl::Sphered& sphere_A, const fcl::Boxd& box_B);
void operator()(const fcl::Sphered& sphere_A,
const fcl::Cylinderd& cylinder_B);
void operator()(const fcl::Sphered& sphere_A,
const fcl::Halfspaced& halfspace_B);
void operator()(const fcl::Sphered& sphere_A, const fcl::Capsuled& capsule_B);
//@}
private:
// Distance computation between a sphere A and a generic shape B. We use
// the overloaded call operators above to limit the kinds of queries, and
// they all call this private template function to minimize code duplication.
template <typename FclShape>
void SphereShapeDistance(const fcl::Sphered& sphere_A,
const FclShape& shape_B);
GeometryId id_A_;
GeometryId id_B_;
math::RigidTransform<T> X_WA_;
math::RigidTransform<T> X_WB_;
SignedDistancePair<T>* result_;
};
/* @name Definition of fallback for missing primitive-primitive tests
Generally, we favor hand-crafted functions for determining the signed distance
between two shapes. However, just because we have no such function for a
particular geometry pair does not mean we have no recourse for computing
signed distance. Instead, we have the "fallback" function.
The fallback function is a simple interface that takes two fcl collision
objects (called `a` and `b`), fcl distance request parameters, and a pointer
to the SignedDistancePair which will be populated with the results of the
query.
Currently, our ability to fallback depends on the scalar type. This family
of functions defines the fallback logic for the various scalar types. It
applies a _whitelist_-based approach in that we assume there is no fallback
for a scalar type unless one is explicitly provided. */
//@{
/* For all non-whitelisted scalar types T, throws an exception declaring the
unsupported combination of geometry types and scalar type. */
template <typename T>
void CalcDistanceFallback(const fcl::CollisionObjectd& a,
const fcl::CollisionObjectd& b,
const fcl::DistanceRequestd&,
SignedDistancePair<T>* /* pair_data */) {
// By default, there is no fallback. For every scalar type for which one
// actually exists, it should be specialized below.
throw std::logic_error(fmt::format(
"Signed distance queries between shapes '{}' and '{}' "
"are not supported for scalar type {}",
GetGeometryName(a), GetGeometryName(b), NiceTypeName::Get<T>()));
}
/* For the double scalar, computes the signed distance between the two objects.
*/
template <>
void CalcDistanceFallback<double>(const fcl::CollisionObjectd& a,
const fcl::CollisionObjectd& b,
const fcl::DistanceRequestd& request,
SignedDistancePair<double>* pair_data);
//@}
/* Reports if the given geometries require using the fallback. */
bool RequiresFallback(const fcl::CollisionObjectd& a,
const fcl::CollisionObjectd& b);
/* Dispatches the narrowphase shape-shape query for the object pair (`a`, `b`)
to the appropriate primitive-primitive function (optionally defaulting to the
type- and shape-dependent fallback function).
@param a The first object in the pair.
@param X_WA The pose of object `a` expressed in the world frame.
@param b The second object in the pair.
@param X_WB The pose of object `b` expressed in the world frame.
@param request The distance request parameters.
@param result The structure to capture the computation results in.
@tparam T Computation scalar type.
@pre The pair should *not* be (Halfspace, X), unless X is Sphere. */
template <typename T>
void ComputeNarrowPhaseDistance(const fcl::CollisionObjectd& a,
const math::RigidTransform<T>& X_WA,
const fcl::CollisionObjectd& b,
const math::RigidTransform<T>& X_WB,
const fcl::DistanceRequestd& request,
SignedDistancePair<T>* result);
// TODO(SeanCurtis-TRI): Replace this clunky mechanism with a new mechanism
// which does this implicitly via ADL and templates.
/* @name Mechanism for reporting on which scalars and for which shape-pairs
shape-to-shape queries can be made.
By default, nothing is supported. For each supported scalar type, a class
specialization is provided which whitelists the supported shape types.
@tparam T The computational scalar type. */
//@{
template <typename T>
struct ScalarSupport {
static bool is_supported(fcl::NODE_TYPE, fcl::NODE_TYPE) {
return false;
}
};
/* Primitive support for double-valued query. */
template <>
struct ScalarSupport<double> {
static bool is_supported(fcl::NODE_TYPE, fcl::NODE_TYPE);
};
/* Primitive support for AutoDiff-valued query. */
template <>
struct ScalarSupport<AutoDiffXd> {
static bool is_supported(fcl::NODE_TYPE node1, fcl::NODE_TYPE node2) {
// TODO(SeanCurtis-TRI): Confirm derivatives for sphere-capsule.
// Explicitly permit the following pair types (with ordering
// permutations):
// (sphere, sphere)
// (sphere, box)
// (sphere, halfspace)
return (node1 == fcl::GEOM_SPHERE &&
(node2 == fcl::GEOM_SPHERE || node2 == fcl::GEOM_BOX ||
node2 == fcl::GEOM_HALFSPACE)) ||
(node2 == fcl::GEOM_SPHERE &&
(node1 == fcl::GEOM_BOX || node1 == fcl::GEOM_HALFSPACE));
}
};
//@}
/* The callback function for computing signed distance between two arbitrary
shapes.
This callback is used in the context where we're going to report the distance
between all O(N²) objects, regardless of the results. The final parameter
in the callback serves as a threshold to the FCL broadphase -- any objects
that are known to be farther than the `dist` value will not be dispatched to
this narrow phase callback. This query does not *reduce* the distance so
it does not set it.
@tparam T The scalar type for the query.
@param object_A_ptr Pointer to the first object in the pair (the order has
no significance).
@param object_B_ptr Pointer to the second object in the pair (the order has
no significance).
@param callback_data Supporting data to compute distance. This includes the
results of this narrowphase computation.
@param max_distance The maximum distance the broadphase should consider
for candidate pairs.
@returns False; the broadphase should *not* terminate its process. */
template <typename T>
bool Callback(fcl::CollisionObjectd* object_A_ptr,
fcl::CollisionObjectd* object_B_ptr,
// NOLINTNEXTLINE
void* callback_data, double& max_distance);
} // namespace shape_distance
} // namespace internal
} // namespace geometry
} // namespace drake