RSS.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2015, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #include <hpp/fcl/BV/RSS.h>
40 #include <hpp/fcl/internal/tools.h>
41 #include <hpp/fcl/collision_data.h>
42 
43 #include <iostream>
44 
45 namespace hpp {
46 namespace fcl {
47 
50  if (val < a)
51  val = a;
52  else if (val > b)
53  val = b;
54 }
55 
68  FCL_REAL A_dot_B, FCL_REAL A_dot_T, FCL_REAL B_dot_T) {
69  FCL_REAL denom = 1 - A_dot_B * A_dot_B;
70 
71  if (denom == 0)
72  t = 0;
73  else {
74  t = (A_dot_T - B_dot_T * A_dot_B) / denom;
75  clipToRange(t, 0, a);
76  }
77 
78  u = t * A_dot_B - B_dot_T;
79  if (u < 0) {
80  u = 0;
81  t = A_dot_T;
82  clipToRange(t, 0, a);
83  } else if (u > b) {
84  u = b;
85  t = u * A_dot_B + A_dot_T;
86  clipToRange(t, 0, a);
87  }
88 }
89 
95 bool inVoronoi(FCL_REAL a, FCL_REAL b, FCL_REAL Anorm_dot_B,
96  FCL_REAL Anorm_dot_T, FCL_REAL A_dot_B, FCL_REAL A_dot_T,
97  FCL_REAL B_dot_T) {
98  if (fabs(Anorm_dot_B) < 1e-7) return false;
99 
100  FCL_REAL t, u, v;
101 
102  u = -Anorm_dot_T / Anorm_dot_B;
103  clipToRange(u, 0, b);
104 
105  t = u * A_dot_B + A_dot_T;
106  clipToRange(t, 0, a);
107 
108  v = t * A_dot_B - B_dot_T;
109 
110  if (Anorm_dot_B > 0) {
111  if (v > (u + 1e-7)) return true;
112  } else {
113  if (v < (u - 1e-7)) return true;
114  }
115  return false;
116 }
117 
121 FCL_REAL rectDistance(const Matrix3f& Rab, Vec3f const& Tab,
122  const FCL_REAL a[2], const FCL_REAL b[2], Vec3f* P = NULL,
123  Vec3f* Q = NULL) {
124  FCL_REAL A0_dot_B0, A0_dot_B1, A1_dot_B0, A1_dot_B1;
125 
126  A0_dot_B0 = Rab(0, 0);
127  A0_dot_B1 = Rab(0, 1);
128  A1_dot_B0 = Rab(1, 0);
129  A1_dot_B1 = Rab(1, 1);
130 
131  FCL_REAL aA0_dot_B0, aA0_dot_B1, aA1_dot_B0, aA1_dot_B1;
132  FCL_REAL bA0_dot_B0, bA0_dot_B1, bA1_dot_B0, bA1_dot_B1;
133 
134  aA0_dot_B0 = a[0] * A0_dot_B0;
135  aA0_dot_B1 = a[0] * A0_dot_B1;
136  aA1_dot_B0 = a[1] * A1_dot_B0;
137  aA1_dot_B1 = a[1] * A1_dot_B1;
138  bA0_dot_B0 = b[0] * A0_dot_B0;
139  bA1_dot_B0 = b[0] * A1_dot_B0;
140  bA0_dot_B1 = b[1] * A0_dot_B1;
141  bA1_dot_B1 = b[1] * A1_dot_B1;
142 
143  Vec3f Tba(Rab.transpose() * Tab);
144 
145  Vec3f S;
146  FCL_REAL t, u;
147 
148  // determine if any edge pair contains the closest points
149 
150  FCL_REAL ALL_x, ALU_x, AUL_x, AUU_x;
151  FCL_REAL BLL_x, BLU_x, BUL_x, BUU_x;
152  FCL_REAL LA1_lx, LA1_ux, UA1_lx, UA1_ux, LB1_lx, LB1_ux, UB1_lx, UB1_ux;
153 
154  ALL_x = -Tba[0];
155  ALU_x = ALL_x + aA1_dot_B0;
156  AUL_x = ALL_x + aA0_dot_B0;
157  AUU_x = ALU_x + aA0_dot_B0;
158 
159  if (ALL_x < ALU_x) {
160  LA1_lx = ALL_x;
161  LA1_ux = ALU_x;
162  UA1_lx = AUL_x;
163  UA1_ux = AUU_x;
164  } else {
165  LA1_lx = ALU_x;
166  LA1_ux = ALL_x;
167  UA1_lx = AUU_x;
168  UA1_ux = AUL_x;
169  }
170 
171  BLL_x = Tab[0];
172  BLU_x = BLL_x + bA0_dot_B1;
173  BUL_x = BLL_x + bA0_dot_B0;
174  BUU_x = BLU_x + bA0_dot_B0;
175 
176  if (BLL_x < BLU_x) {
177  LB1_lx = BLL_x;
178  LB1_ux = BLU_x;
179  UB1_lx = BUL_x;
180  UB1_ux = BUU_x;
181  } else {
182  LB1_lx = BLU_x;
183  LB1_ux = BLL_x;
184  UB1_lx = BUU_x;
185  UB1_ux = BUL_x;
186  }
187 
188  // UA1, UB1
189 
190  if ((UA1_ux > b[0]) && (UB1_ux > a[0])) {
191  if (((UA1_lx > b[0]) ||
192  inVoronoi(b[1], a[1], A1_dot_B0, aA0_dot_B0 - b[0] - Tba[0], A1_dot_B1,
193  aA0_dot_B1 - Tba[1], -Tab[1] - bA1_dot_B0)) &&
194  ((UB1_lx > a[0]) ||
195  inVoronoi(a[1], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0 - a[0], A1_dot_B1,
196  Tab[1] + bA1_dot_B0, Tba[1] - aA0_dot_B1))) {
197  segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1] + bA1_dot_B0,
198  Tba[1] - aA0_dot_B1);
199 
200  S[0] = Tab[0] + Rab(0, 0) * b[0] + Rab(0, 1) * u - a[0];
201  S[1] = Tab[1] + Rab(1, 0) * b[0] + Rab(1, 1) * u - t;
202  S[2] = Tab[2] + Rab(2, 0) * b[0] + Rab(2, 1) * u;
203 
204  if (P && Q) {
205  *P << a[0], t, 0;
206  *Q = S + (*P);
207  }
208 
209  return S.norm();
210  }
211  }
212 
213  // UA1, LB1
214 
215  if ((UA1_lx < 0) && (LB1_ux > a[0])) {
216  if (((UA1_ux < 0) || inVoronoi(b[1], a[1], -A1_dot_B0, Tba[0] - aA0_dot_B0,
217  A1_dot_B1, aA0_dot_B1 - Tba[1], -Tab[1])) &&
218  ((LB1_lx > a[0]) ||
219  inVoronoi(a[1], b[1], A0_dot_B1, Tab[0] - a[0], A1_dot_B1, Tab[1],
220  Tba[1] - aA0_dot_B1))) {
221  segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1], Tba[1] - aA0_dot_B1);
222 
223  S[0] = Tab[0] + Rab(0, 1) * u - a[0];
224  S[1] = Tab[1] + Rab(1, 1) * u - t;
225  S[2] = Tab[2] + Rab(2, 1) * u;
226 
227  if (P && Q) {
228  *P << a[0], t, 0;
229  *Q = S + (*P);
230  }
231 
232  return S.norm();
233  }
234  }
235 
236  // LA1, UB1
237 
238  if ((LA1_ux > b[0]) && (UB1_lx < 0)) {
239  if (((LA1_lx > b[0]) ||
240  inVoronoi(b[1], a[1], A1_dot_B0, -Tba[0] - b[0], A1_dot_B1, -Tba[1],
241  -Tab[1] - bA1_dot_B0)) &&
242  ((UB1_ux < 0) || inVoronoi(a[1], b[1], -A0_dot_B1, -Tab[0] - bA0_dot_B0,
243  A1_dot_B1, Tab[1] + bA1_dot_B0, Tba[1]))) {
244  segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1] + bA1_dot_B0, Tba[1]);
245 
246  S[0] = Tab[0] + Rab(0, 0) * b[0] + Rab(0, 1) * u;
247  S[1] = Tab[1] + Rab(1, 0) * b[0] + Rab(1, 1) * u - t;
248  S[2] = Tab[2] + Rab(2, 0) * b[0] + Rab(2, 1) * u;
249 
250  if (P && Q) {
251  *P << 0, t, 0;
252  *Q = S + (*P);
253  }
254 
255  return S.norm();
256  }
257  }
258 
259  // LA1, LB1
260 
261  if ((LA1_lx < 0) && (LB1_lx < 0)) {
262  if (((LA1_ux < 0) || inVoronoi(b[1], a[1], -A1_dot_B0, Tba[0], A1_dot_B1,
263  -Tba[1], -Tab[1])) &&
264  ((LB1_ux < 0) || inVoronoi(a[1], b[1], -A0_dot_B1, -Tab[0], A1_dot_B1,
265  Tab[1], Tba[1]))) {
266  segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1], Tba[1]);
267 
268  S[0] = Tab[0] + Rab(0, 1) * u;
269  S[1] = Tab[1] + Rab(1, 1) * u - t;
270  S[2] = Tab[2] + Rab(2, 1) * u;
271 
272  if (P && Q) {
273  *P << 0, t, 0;
274  *Q = S + (*P);
275  }
276 
277  return S.norm();
278  }
279  }
280 
281  FCL_REAL ALL_y, ALU_y, AUL_y, AUU_y;
282 
283  ALL_y = -Tba[1];
284  ALU_y = ALL_y + aA1_dot_B1;
285  AUL_y = ALL_y + aA0_dot_B1;
286  AUU_y = ALU_y + aA0_dot_B1;
287 
288  FCL_REAL LA1_ly, LA1_uy, UA1_ly, UA1_uy, LB0_lx, LB0_ux, UB0_lx, UB0_ux;
289 
290  if (ALL_y < ALU_y) {
291  LA1_ly = ALL_y;
292  LA1_uy = ALU_y;
293  UA1_ly = AUL_y;
294  UA1_uy = AUU_y;
295  } else {
296  LA1_ly = ALU_y;
297  LA1_uy = ALL_y;
298  UA1_ly = AUU_y;
299  UA1_uy = AUL_y;
300  }
301 
302  if (BLL_x < BUL_x) {
303  LB0_lx = BLL_x;
304  LB0_ux = BUL_x;
305  UB0_lx = BLU_x;
306  UB0_ux = BUU_x;
307  } else {
308  LB0_lx = BUL_x;
309  LB0_ux = BLL_x;
310  UB0_lx = BUU_x;
311  UB0_ux = BLU_x;
312  }
313 
314  // UA1, UB0
315 
316  if ((UA1_uy > b[1]) && (UB0_ux > a[0])) {
317  if (((UA1_ly > b[1]) ||
318  inVoronoi(b[0], a[1], A1_dot_B1, aA0_dot_B1 - Tba[1] - b[1], A1_dot_B0,
319  aA0_dot_B0 - Tba[0], -Tab[1] - bA1_dot_B1)) &&
320  ((UB0_lx > a[0]) ||
321  inVoronoi(a[1], b[0], A0_dot_B0, Tab[0] - a[0] + bA0_dot_B1, A1_dot_B0,
322  Tab[1] + bA1_dot_B1, Tba[0] - aA0_dot_B0))) {
323  segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1] + bA1_dot_B1,
324  Tba[0] - aA0_dot_B0);
325 
326  S[0] = Tab[0] + Rab(0, 1) * b[1] + Rab(0, 0) * u - a[0];
327  S[1] = Tab[1] + Rab(1, 1) * b[1] + Rab(1, 0) * u - t;
328  S[2] = Tab[2] + Rab(2, 1) * b[1] + Rab(2, 0) * u;
329 
330  if (P && Q) {
331  *P << a[0], t, 0;
332  *Q = S + (*P);
333  }
334 
335  return S.norm();
336  }
337  }
338 
339  // UA1, LB0
340 
341  if ((UA1_ly < 0) && (LB0_ux > a[0])) {
342  if (((UA1_uy < 0) || inVoronoi(b[0], a[1], -A1_dot_B1, Tba[1] - aA0_dot_B1,
343  A1_dot_B0, aA0_dot_B0 - Tba[0], -Tab[1])) &&
344  ((LB0_lx > a[0]) ||
345  inVoronoi(a[1], b[0], A0_dot_B0, Tab[0] - a[0], A1_dot_B0, Tab[1],
346  Tba[0] - aA0_dot_B0))) {
347  segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1], Tba[0] - aA0_dot_B0);
348 
349  S[0] = Tab[0] + Rab(0, 0) * u - a[0];
350  S[1] = Tab[1] + Rab(1, 0) * u - t;
351  S[2] = Tab[2] + Rab(2, 0) * u;
352 
353  if (P && Q) {
354  *P << a[0], t, 0;
355  *Q = S + (*P);
356  }
357 
358  return S.norm();
359  }
360  }
361 
362  // LA1, UB0
363 
364  if ((LA1_uy > b[1]) && (UB0_lx < 0)) {
365  if (((LA1_ly > b[1]) ||
366  inVoronoi(b[0], a[1], A1_dot_B1, -Tba[1] - b[1], A1_dot_B0, -Tba[0],
367  -Tab[1] - bA1_dot_B1)) &&
368 
369  ((UB0_ux < 0) || inVoronoi(a[1], b[0], -A0_dot_B0, -Tab[0] - bA0_dot_B1,
370  A1_dot_B0, Tab[1] + bA1_dot_B1, Tba[0]))) {
371  segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1] + bA1_dot_B1, Tba[0]);
372 
373  S[0] = Tab[0] + Rab(0, 1) * b[1] + Rab(0, 0) * u;
374  S[1] = Tab[1] + Rab(1, 1) * b[1] + Rab(1, 0) * u - t;
375  S[2] = Tab[2] + Rab(2, 1) * b[1] + Rab(2, 0) * u;
376 
377  if (P && Q) {
378  *P << 0, t, 0;
379  *Q = S + (*P);
380  }
381 
382  return S.norm();
383  }
384  }
385 
386  // LA1, LB0
387 
388  if ((LA1_ly < 0) && (LB0_lx < 0)) {
389  if (((LA1_uy < 0) || inVoronoi(b[0], a[1], -A1_dot_B1, Tba[1], A1_dot_B0,
390  -Tba[0], -Tab[1])) &&
391  ((LB0_ux < 0) || inVoronoi(a[1], b[0], -A0_dot_B0, -Tab[0], A1_dot_B0,
392  Tab[1], Tba[0]))) {
393  segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1], Tba[0]);
394 
395  S[0] = Tab[0] + Rab(0, 0) * u;
396  S[1] = Tab[1] + Rab(1, 0) * u - t;
397  S[2] = Tab[2] + Rab(2, 0) * u;
398 
399  if (P && Q) {
400  *P << 0, t, 0;
401  *Q = S + (*P);
402  }
403 
404  return S.norm();
405  }
406  }
407 
408  FCL_REAL BLL_y, BLU_y, BUL_y, BUU_y;
409 
410  BLL_y = Tab[1];
411  BLU_y = BLL_y + bA1_dot_B1;
412  BUL_y = BLL_y + bA1_dot_B0;
413  BUU_y = BLU_y + bA1_dot_B0;
414 
415  FCL_REAL LA0_lx, LA0_ux, UA0_lx, UA0_ux, LB1_ly, LB1_uy, UB1_ly, UB1_uy;
416 
417  if (ALL_x < AUL_x) {
418  LA0_lx = ALL_x;
419  LA0_ux = AUL_x;
420  UA0_lx = ALU_x;
421  UA0_ux = AUU_x;
422  } else {
423  LA0_lx = AUL_x;
424  LA0_ux = ALL_x;
425  UA0_lx = AUU_x;
426  UA0_ux = ALU_x;
427  }
428 
429  if (BLL_y < BLU_y) {
430  LB1_ly = BLL_y;
431  LB1_uy = BLU_y;
432  UB1_ly = BUL_y;
433  UB1_uy = BUU_y;
434  } else {
435  LB1_ly = BLU_y;
436  LB1_uy = BLL_y;
437  UB1_ly = BUU_y;
438  UB1_uy = BUL_y;
439  }
440 
441  // UA0, UB1
442 
443  if ((UA0_ux > b[0]) && (UB1_uy > a[1])) {
444  if (((UA0_lx > b[0]) ||
445  inVoronoi(b[1], a[0], A0_dot_B0, aA1_dot_B0 - Tba[0] - b[0], A0_dot_B1,
446  aA1_dot_B1 - Tba[1], -Tab[0] - bA0_dot_B0)) &&
447  ((UB1_ly > a[1]) ||
448  inVoronoi(a[0], b[1], A1_dot_B1, Tab[1] - a[1] + bA1_dot_B0, A0_dot_B1,
449  Tab[0] + bA0_dot_B0, Tba[1] - aA1_dot_B1))) {
450  segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0,
451  Tba[1] - aA1_dot_B1);
452 
453  S[0] = Tab[0] + Rab(0, 0) * b[0] + Rab(0, 1) * u - t;
454  S[1] = Tab[1] + Rab(1, 0) * b[0] + Rab(1, 1) * u - a[1];
455  S[2] = Tab[2] + Rab(2, 0) * b[0] + Rab(2, 1) * u;
456 
457  if (P && Q) {
458  *P << t, a[1], 0;
459  *Q = S + (*P);
460  }
461 
462  return S.norm();
463  }
464  }
465 
466  // UA0, LB1
467 
468  if ((UA0_lx < 0) && (LB1_uy > a[1])) {
469  if (((UA0_ux < 0) || inVoronoi(b[1], a[0], -A0_dot_B0, Tba[0] - aA1_dot_B0,
470  A0_dot_B1, aA1_dot_B1 - Tba[1], -Tab[0])) &&
471  ((LB1_ly > a[1]) ||
472  inVoronoi(a[0], b[1], A1_dot_B1, Tab[1] - a[1], A0_dot_B1, Tab[0],
473  Tba[1] - aA1_dot_B1))) {
474  segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0], Tba[1] - aA1_dot_B1);
475 
476  S[0] = Tab[0] + Rab(0, 1) * u - t;
477  S[1] = Tab[1] + Rab(1, 1) * u - a[1];
478  S[2] = Tab[2] + Rab(2, 1) * u;
479 
480  if (P && Q) {
481  *P << t, a[1], 0;
482  *Q = S + (*P);
483  }
484 
485  return S.norm();
486  }
487  }
488 
489  // LA0, UB1
490 
491  if ((LA0_ux > b[0]) && (UB1_ly < 0)) {
492  if (((LA0_lx > b[0]) ||
493  inVoronoi(b[1], a[0], A0_dot_B0, -b[0] - Tba[0], A0_dot_B1, -Tba[1],
494  -bA0_dot_B0 - Tab[0])) &&
495  ((UB1_uy < 0) || inVoronoi(a[0], b[1], -A1_dot_B1, -Tab[1] - bA1_dot_B0,
496  A0_dot_B1, Tab[0] + bA0_dot_B0, Tba[1]))) {
497  segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0, Tba[1]);
498 
499  S[0] = Tab[0] + Rab(0, 0) * b[0] + Rab(0, 1) * u - t;
500  S[1] = Tab[1] + Rab(1, 0) * b[0] + Rab(1, 1) * u;
501  S[2] = Tab[2] + Rab(2, 0) * b[0] + Rab(2, 1) * u;
502 
503  if (P && Q) {
504  *P << t, 0, 0;
505  *Q = S + (*P);
506  }
507 
508  return S.norm();
509  }
510  }
511 
512  // LA0, LB1
513 
514  if ((LA0_lx < 0) && (LB1_ly < 0)) {
515  if (((LA0_ux < 0) || inVoronoi(b[1], a[0], -A0_dot_B0, Tba[0], A0_dot_B1,
516  -Tba[1], -Tab[0])) &&
517  ((LB1_uy < 0) || inVoronoi(a[0], b[1], -A1_dot_B1, -Tab[1], A0_dot_B1,
518  Tab[0], Tba[1]))) {
519  segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0], Tba[1]);
520 
521  S[0] = Tab[0] + Rab(0, 1) * u - t;
522  S[1] = Tab[1] + Rab(1, 1) * u;
523  S[2] = Tab[2] + Rab(2, 1) * u;
524 
525  if (P && Q) {
526  *P << t, 0, 0;
527  *Q = S + (*P);
528  }
529 
530  return S.norm();
531  }
532  }
533 
534  FCL_REAL LA0_ly, LA0_uy, UA0_ly, UA0_uy, LB0_ly, LB0_uy, UB0_ly, UB0_uy;
535 
536  if (ALL_y < AUL_y) {
537  LA0_ly = ALL_y;
538  LA0_uy = AUL_y;
539  UA0_ly = ALU_y;
540  UA0_uy = AUU_y;
541  } else {
542  LA0_ly = AUL_y;
543  LA0_uy = ALL_y;
544  UA0_ly = AUU_y;
545  UA0_uy = ALU_y;
546  }
547 
548  if (BLL_y < BUL_y) {
549  LB0_ly = BLL_y;
550  LB0_uy = BUL_y;
551  UB0_ly = BLU_y;
552  UB0_uy = BUU_y;
553  } else {
554  LB0_ly = BUL_y;
555  LB0_uy = BLL_y;
556  UB0_ly = BUU_y;
557  UB0_uy = BLU_y;
558  }
559 
560  // UA0, UB0
561 
562  if ((UA0_uy > b[1]) && (UB0_uy > a[1])) {
563  if (((UA0_ly > b[1]) ||
564  inVoronoi(b[0], a[0], A0_dot_B1, aA1_dot_B1 - Tba[1] - b[1], A0_dot_B0,
565  aA1_dot_B0 - Tba[0], -Tab[0] - bA0_dot_B1)) &&
566  ((UB0_ly > a[1]) ||
567  inVoronoi(a[0], b[0], A1_dot_B0, Tab[1] - a[1] + bA1_dot_B1, A0_dot_B0,
568  Tab[0] + bA0_dot_B1, Tba[0] - aA1_dot_B0))) {
569  segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0] + bA0_dot_B1,
570  Tba[0] - aA1_dot_B0);
571 
572  S[0] = Tab[0] + Rab(0, 1) * b[1] + Rab(0, 0) * u - t;
573  S[1] = Tab[1] + Rab(1, 1) * b[1] + Rab(1, 0) * u - a[1];
574  S[2] = Tab[2] + Rab(2, 1) * b[1] + Rab(2, 0) * u;
575 
576  if (P && Q) {
577  *P << t, a[1], 0;
578  *Q = S + (*P);
579  }
580 
581  return S.norm();
582  }
583  }
584 
585  // UA0, LB0
586 
587  if ((UA0_ly < 0) && (LB0_uy > a[1])) {
588  if (((UA0_uy < 0) || inVoronoi(b[0], a[0], -A0_dot_B1, Tba[1] - aA1_dot_B1,
589  A0_dot_B0, aA1_dot_B0 - Tba[0], -Tab[0])) &&
590  ((LB0_ly > a[1]) ||
591  inVoronoi(a[0], b[0], A1_dot_B0, Tab[1] - a[1], A0_dot_B0, Tab[0],
592  Tba[0] - aA1_dot_B0))) {
593  segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0], Tba[0] - aA1_dot_B0);
594 
595  S[0] = Tab[0] + Rab(0, 0) * u - t;
596  S[1] = Tab[1] + Rab(1, 0) * u - a[1];
597  S[2] = Tab[2] + Rab(2, 0) * u;
598 
599  if (P && Q) {
600  *P << t, a[1], 0;
601  *Q = S + (*P);
602  }
603 
604  return S.norm();
605  }
606  }
607 
608  // LA0, UB0
609 
610  if ((LA0_uy > b[1]) && (UB0_ly < 0)) {
611  if (((LA0_ly > b[1]) ||
612  inVoronoi(b[0], a[0], A0_dot_B1, -Tba[1] - b[1], A0_dot_B0, -Tba[0],
613  -Tab[0] - bA0_dot_B1)) &&
614 
615  ((UB0_uy < 0) || inVoronoi(a[0], b[0], -A1_dot_B0, -Tab[1] - bA1_dot_B1,
616  A0_dot_B0, Tab[0] + bA0_dot_B1, Tba[0]))) {
617  segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0] + bA0_dot_B1, Tba[0]);
618 
619  S[0] = Tab[0] + Rab(0, 1) * b[1] + Rab(0, 0) * u - t;
620  S[1] = Tab[1] + Rab(1, 1) * b[1] + Rab(1, 0) * u;
621  S[2] = Tab[2] + Rab(2, 1) * b[1] + Rab(2, 0) * u;
622 
623  if (P && Q) {
624  *P << t, 0, 0;
625  *Q = S + (*P);
626  }
627 
628  return S.norm();
629  }
630  }
631 
632  // LA0, LB0
633 
634  if ((LA0_ly < 0) && (LB0_ly < 0)) {
635  if (((LA0_uy < 0) || inVoronoi(b[0], a[0], -A0_dot_B1, Tba[1], A0_dot_B0,
636  -Tba[0], -Tab[0])) &&
637  ((LB0_uy < 0) || inVoronoi(a[0], b[0], -A1_dot_B0, -Tab[1], A0_dot_B0,
638  Tab[0], Tba[0]))) {
639  segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0], Tba[0]);
640 
641  S[0] = Tab[0] + Rab(0, 0) * u - t;
642  S[1] = Tab[1] + Rab(1, 0) * u;
643  S[2] = Tab[2] + Rab(2, 0) * u;
644 
645  if (P && Q) {
646  *P << t, 0, 0;
647  *Q = S + (*P);
648  }
649 
650  return S.norm();
651  }
652  }
653 
654  // no edges passed, take max separation along face normals
655 
656  FCL_REAL sep1, sep2;
657 
658  if (Tab[2] > 0.0) {
659  sep1 = Tab[2];
660  if (Rab(2, 0) < 0.0) sep1 += b[0] * Rab(2, 0);
661  if (Rab(2, 1) < 0.0) sep1 += b[1] * Rab(2, 1);
662  } else {
663  sep1 = -Tab[2];
664  if (Rab(2, 0) > 0.0) sep1 -= b[0] * Rab(2, 0);
665  if (Rab(2, 1) > 0.0) sep1 -= b[1] * Rab(2, 1);
666  }
667 
668  if (Tba[2] < 0) {
669  sep2 = -Tba[2];
670  if (Rab(0, 2) < 0.0) sep2 += a[0] * Rab(0, 2);
671  if (Rab(1, 2) < 0.0) sep2 += a[1] * Rab(1, 2);
672  } else {
673  sep2 = Tba[2];
674  if (Rab(0, 2) > 0.0) sep2 -= a[0] * Rab(0, 2);
675  if (Rab(1, 2) > 0.0) sep2 -= a[1] * Rab(1, 2);
676  }
677 
678  if (sep1 >= sep2 && sep1 >= 0) {
679  if (Tab[2] > 0)
680  S << 0, 0, sep1;
681  else
682  S << 0, 0, -sep1;
683 
684  if (P && Q) {
685  *Q = S;
686  P->setZero();
687  }
688  }
689 
690  if (sep2 >= sep1 && sep2 >= 0) {
691  Vec3f Q_(Tab[0], Tab[1], Tab[2]);
692  Vec3f P_;
693  if (Tba[2] < 0) {
694  P_[0] = Rab(0, 2) * sep2 + Tab[0];
695  P_[1] = Rab(1, 2) * sep2 + Tab[1];
696  P_[2] = Rab(2, 2) * sep2 + Tab[2];
697  } else {
698  P_[0] = -Rab(0, 2) * sep2 + Tab[0];
699  P_[1] = -Rab(1, 2) * sep2 + Tab[1];
700  P_[2] = -Rab(2, 2) * sep2 + Tab[2];
701  }
702 
703  S = Q_ - P_;
704 
705  if (P && Q) {
706  *P = P_;
707  *Q = Q_;
708  }
709  }
710 
711  FCL_REAL sep = (sep1 > sep2 ? sep1 : sep2);
712  return (sep > 0 ? sep : 0);
713 }
714 
715 bool RSS::overlap(const RSS& other) const {
719 
721  Vec3f T(axes.transpose() * (other.Tr - Tr));
722 
724  Matrix3f R(axes.transpose() * other.axes);
725 
726  FCL_REAL dist = rectDistance(R, T, length, other.length);
727  return (dist <= (radius + other.radius));
728 }
729 
730 bool overlap(const Matrix3f& R0, const Vec3f& T0, const RSS& b1,
731  const RSS& b2) {
732  // ROb2 = R0 . b2
733  // where b2 = [ b2.axis [0] | b2.axis [1] | b2.axis [2] ]
734 
735  // (1 0 0)^T R0b2^T axis [0] = (1 0 0)^T b2^T R0^T axis [0]
736  // R = b2^T RO^T b1
737  Vec3f Ttemp(R0.transpose() * (b2.Tr - T0) - b1.Tr);
738  Vec3f T(b1.axes.transpose() * Ttemp);
739  Matrix3f R(b1.axes.transpose() * R0.transpose() * b2.axes);
740 
741  FCL_REAL dist = rectDistance(R, T, b1.length, b2.length);
742  return (dist <= (b1.radius + b2.radius));
743 }
744 
745 bool overlap(const Matrix3f& R0, const Vec3f& T0, const RSS& b1, const RSS& b2,
746  const CollisionRequest& request, FCL_REAL& sqrDistLowerBound) {
747  // ROb2 = R0 . b2
748  // where b2 = [ b2.axis [0] | b2.axis [1] | b2.axis [2] ]
749 
750  // (1 0 0)^T R0b2^T axis [0] = (1 0 0)^T b2^T R0^T axis [0]
751  // R = b2^T RO^T b1
752  Vec3f Ttemp(R0.transpose() * (b2.Tr - T0) - b1.Tr);
753  Vec3f T(b1.axes.transpose() * Ttemp);
754  Matrix3f R(b1.axes.transpose() * R0.transpose() * b2.axes);
755 
756  FCL_REAL dist = rectDistance(R, T, b1.length, b2.length) - b1.radius -
757  b2.radius - request.security_margin;
758  if (dist <= 0) return true;
759  sqrDistLowerBound = dist * dist;
760  return false;
761 }
762 
763 bool RSS::contain(const Vec3f& p) const {
764  Vec3f local_p = p - Tr;
765  // FIXME: Vec3f proj (axes.transpose() * local_p);
766  FCL_REAL proj0 = local_p.dot(axes.col(0));
767  FCL_REAL proj1 = local_p.dot(axes.col(1));
768  FCL_REAL proj2 = local_p.dot(axes.col(2));
769  FCL_REAL abs_proj2 = fabs(proj2);
770  Vec3f proj(proj0, proj1, proj2);
771 
773  if ((proj0 < length[0]) && (proj0 > 0) && (proj1 < length[1]) &&
774  (proj1 > 0)) {
775  return (abs_proj2 < radius);
776  } else if ((proj0 < length[0]) && (proj0 > 0) &&
777  ((proj1 < 0) || (proj1 > length[1]))) {
778  FCL_REAL y = (proj1 > 0) ? length[1] : 0;
779  Vec3f v(proj0, y, 0);
780  return ((proj - v).squaredNorm() < radius * radius);
781  } else if ((proj1 < length[1]) && (proj1 > 0) &&
782  ((proj0 < 0) || (proj0 > length[0]))) {
783  FCL_REAL x = (proj0 > 0) ? length[0] : 0;
784  Vec3f v(x, proj1, 0);
785  return ((proj - v).squaredNorm() < radius * radius);
786  } else {
787  FCL_REAL x = (proj0 > 0) ? length[0] : 0;
788  FCL_REAL y = (proj1 > 0) ? length[1] : 0;
789  Vec3f v(x, y, 0);
790  return ((proj - v).squaredNorm() < radius * radius);
791  }
792 }
793 
795  Vec3f local_p = p - Tr;
796  FCL_REAL proj0 = local_p.dot(axes.col(0));
797  FCL_REAL proj1 = local_p.dot(axes.col(1));
798  FCL_REAL proj2 = local_p.dot(axes.col(2));
799  FCL_REAL abs_proj2 = fabs(proj2);
800  Vec3f proj(proj0, proj1, proj2);
801 
802  // projection is within the rectangle
803  if ((proj0 < length[0]) && (proj0 > 0) && (proj1 < length[1]) &&
804  (proj1 > 0)) {
805  if (abs_proj2 < radius)
806  ; // do nothing
807  else {
808  radius = 0.5 * (radius + abs_proj2); // enlarge the r
809  // change RSS origin position
810  if (proj2 > 0)
811  Tr[2] += 0.5 * (abs_proj2 - radius);
812  else
813  Tr[2] -= 0.5 * (abs_proj2 - radius);
814  }
815  } else if ((proj0 < length[0]) && (proj0 > 0) &&
816  ((proj1 < 0) || (proj1 > length[1]))) {
817  FCL_REAL y = (proj1 > 0) ? length[1] : 0;
818  Vec3f v(proj0, y, 0);
819  FCL_REAL new_r_sqr = (proj - v).squaredNorm();
820  if (new_r_sqr < radius * radius)
821  ; // do nothing
822  else {
823  if (abs_proj2 < radius) {
824  FCL_REAL delta_y =
825  -std::sqrt(radius * radius - proj2 * proj2) + fabs(proj1 - y);
826  length[1] += delta_y;
827  if (proj1 < 0) Tr[1] -= delta_y;
828  } else {
829  FCL_REAL delta_y = fabs(proj1 - y);
830  length[1] += delta_y;
831  if (proj1 < 0) Tr[1] -= delta_y;
832 
833  if (proj2 > 0)
834  Tr[2] += 0.5 * (abs_proj2 - radius);
835  else
836  Tr[2] -= 0.5 * (abs_proj2 - radius);
837  }
838  }
839  } else if ((proj1 < length[1]) && (proj1 > 0) &&
840  ((proj0 < 0) || (proj0 > length[0]))) {
841  FCL_REAL x = (proj0 > 0) ? length[0] : 0;
842  Vec3f v(x, proj1, 0);
843  FCL_REAL new_r_sqr = (proj - v).squaredNorm();
844  if (new_r_sqr < radius * radius)
845  ; // do nothing
846  else {
847  if (abs_proj2 < radius) {
848  FCL_REAL delta_x =
849  -std::sqrt(radius * radius - proj2 * proj2) + fabs(proj0 - x);
850  length[0] += delta_x;
851  if (proj0 < 0) Tr[0] -= delta_x;
852  } else {
853  FCL_REAL delta_x = fabs(proj0 - x);
854  length[0] += delta_x;
855  if (proj0 < 0) Tr[0] -= delta_x;
856 
857  if (proj2 > 0)
858  Tr[2] += 0.5 * (abs_proj2 - radius);
859  else
860  Tr[2] -= 0.5 * (abs_proj2 - radius);
861  }
862  }
863  } else {
864  FCL_REAL x = (proj0 > 0) ? length[0] : 0;
865  FCL_REAL y = (proj1 > 0) ? length[1] : 0;
866  Vec3f v(x, y, 0);
867  FCL_REAL new_r_sqr = (proj - v).squaredNorm();
868  if (new_r_sqr < radius * radius)
869  ; // do nothing
870  else {
871  if (abs_proj2 < radius) {
872  FCL_REAL diag = std::sqrt(new_r_sqr - proj2 * proj2);
873  FCL_REAL delta_diag =
874  -std::sqrt(radius * radius - proj2 * proj2) + diag;
875 
876  FCL_REAL delta_x = delta_diag / diag * fabs(proj0 - x);
877  FCL_REAL delta_y = delta_diag / diag * fabs(proj1 - y);
878  length[0] += delta_x;
879  length[1] += delta_y;
880 
881  if (proj0 < 0 && proj1 < 0) {
882  Tr[0] -= delta_x;
883  Tr[1] -= delta_y;
884  }
885  } else {
886  FCL_REAL delta_x = fabs(proj0 - x);
887  FCL_REAL delta_y = fabs(proj1 - y);
888 
889  length[0] += delta_x;
890  length[1] += delta_y;
891 
892  if (proj0 < 0 && proj1 < 0) {
893  Tr[0] -= delta_x;
894  Tr[1] -= delta_y;
895  }
896 
897  if (proj2 > 0)
898  Tr[2] += 0.5 * (abs_proj2 - radius);
899  else
900  Tr[2] -= 0.5 * (abs_proj2 - radius);
901  }
902  }
903  }
904 
905  return *this;
906 }
907 
908 RSS RSS::operator+(const RSS& other) const {
909  RSS bv;
910 
911  Vec3f v[16];
912  Vec3f d0_pos(other.axes.col(0) * (other.length[0] + other.radius));
913  Vec3f d1_pos(other.axes.col(1) * (other.length[1] + other.radius));
914  Vec3f d0_neg(other.axes.col(0) * (-other.radius));
915  Vec3f d1_neg(other.axes.col(1) * (-other.radius));
916  Vec3f d2_pos(other.axes.col(2) * other.radius);
917  Vec3f d2_neg(other.axes.col(2) * (-other.radius));
918 
919  v[0].noalias() = other.Tr + d0_pos + d1_pos + d2_pos;
920  v[1].noalias() = other.Tr + d0_pos + d1_pos + d2_neg;
921  v[2].noalias() = other.Tr + d0_pos + d1_neg + d2_pos;
922  v[3].noalias() = other.Tr + d0_pos + d1_neg + d2_neg;
923  v[4].noalias() = other.Tr + d0_neg + d1_pos + d2_pos;
924  v[5].noalias() = other.Tr + d0_neg + d1_pos + d2_neg;
925  v[6].noalias() = other.Tr + d0_neg + d1_neg + d2_pos;
926  v[7].noalias() = other.Tr + d0_neg + d1_neg + d2_neg;
927 
928  d0_pos.noalias() = axes.col(0) * (length[0] + radius);
929  d1_pos.noalias() = axes.col(1) * (length[1] + radius);
930  d0_neg.noalias() = axes.col(0) * (-radius);
931  d1_neg.noalias() = axes.col(1) * (-radius);
932  d2_pos.noalias() = axes.col(2) * radius;
933  d2_neg.noalias() = axes.col(2) * (-radius);
934 
935  v[8].noalias() = Tr + d0_pos + d1_pos + d2_pos;
936  v[9].noalias() = Tr + d0_pos + d1_pos + d2_neg;
937  v[10].noalias() = Tr + d0_pos + d1_neg + d2_pos;
938  v[11].noalias() = Tr + d0_pos + d1_neg + d2_neg;
939  v[12].noalias() = Tr + d0_neg + d1_pos + d2_pos;
940  v[13].noalias() = Tr + d0_neg + d1_pos + d2_neg;
941  v[14].noalias() = Tr + d0_neg + d1_neg + d2_pos;
942  v[15].noalias() = Tr + d0_neg + d1_neg + d2_neg;
943 
944  Matrix3f M; // row first matrix
945  Vec3f E[3]; // row first eigen-vectors
946  Matrix3f::Scalar s[3] = {0, 0, 0};
947 
948  getCovariance(v, NULL, NULL, NULL, 16, M);
949  eigen(M, s, E);
950 
951  int min, mid, max;
952  if (s[0] > s[1]) {
953  max = 0;
954  min = 1;
955  } else {
956  min = 0;
957  max = 1;
958  }
959  if (s[2] < s[min]) {
960  mid = min;
961  min = 2;
962  } else if (s[2] > s[max]) {
963  mid = max;
964  max = 2;
965  } else {
966  mid = 2;
967  }
968 
969  // column first matrix, as the axis in RSS
970  bv.axes.col(0) << E[0][max], E[1][max], E[2][max];
971  bv.axes.col(1) << E[0][mid], E[1][mid], E[2][mid];
972  bv.axes.col(2) << E[1][max] * E[2][mid] - E[1][mid] * E[2][max],
973  E[0][mid] * E[2][max] - E[0][max] * E[2][mid],
974  E[0][max] * E[1][mid] - E[0][mid] * E[1][max];
975 
976  // set rss origin, rectangle size and radius
977  getRadiusAndOriginAndRectangleSize(v, NULL, NULL, NULL, 16, bv.axes, bv.Tr,
978  bv.length, bv.radius);
979 
980  return bv;
981 }
982 
983 FCL_REAL RSS::distance(const RSS& other, Vec3f* P, Vec3f* Q) const {
984  // compute what transform [R,T] that takes us from cs1 to cs2.
985  // [R,T] = [R1,T1]'[R2,T2] = [R1',-R1'T][R2,T2] = [R1'R2, R1'(T2-T1)]
986  // First compute the rotation part, then translation part
987  Matrix3f R(axes.transpose() * other.axes);
988  Vec3f T(axes.transpose() * (other.Tr - Tr));
989 
990  FCL_REAL dist = rectDistance(R, T, length, other.length, P, Q);
991  dist -= (radius + other.radius);
992  return (dist < (FCL_REAL)0.0) ? (FCL_REAL)0.0 : dist;
993 }
994 
995 FCL_REAL distance(const Matrix3f& R0, const Vec3f& T0, const RSS& b1,
996  const RSS& b2, Vec3f* P, Vec3f* Q) {
997  Matrix3f R(b1.axes.transpose() * R0 * b2.axes);
998  Vec3f Ttemp(R0 * b2.Tr + T0 - b1.Tr);
999 
1000  Vec3f T(b1.axes.transpose() * Ttemp);
1001 
1002  FCL_REAL dist = rectDistance(R, T, b1.length, b2.length, P, Q);
1003  dist -= (b1.radius + b2.radius);
1004  return (dist < (FCL_REAL)0.0) ? (FCL_REAL)0.0 : dist;
1005 }
1006 
1007 RSS translate(const RSS& bv, const Vec3f& t) {
1008  RSS res(bv);
1009  res.Tr += t;
1010  return res;
1011 }
1012 
1013 } // namespace fcl
1014 
1015 } // namespace hpp
bool contain(const Vec3f &p) const
Check whether the RSS contains a point.
Definition: RSS.cpp:763
y
void clipToRange(FCL_REAL &val, FCL_REAL a, FCL_REAL b)
Clip value between a and b.
Definition: RSS.cpp:49
Main namespace.
t
Matrix3f axes
Orientation of RSS. axis[i] is the ith column of the orientation matrix for the RSS; it is also the i...
Definition: BV/RSS.h:59
const char * sep
Definition: obb.cpp:92
RSS & operator+=(const Vec3f &p)
A simple way to merge the RSS and a point, not compact.
Definition: RSS.cpp:794
Eigen::Matrix< FCL_REAL, 3, 3 > Matrix3f
Definition: data_types.h:68
void eigen(const Eigen::MatrixBase< Derived > &m, typename Derived::Scalar dout[3], Vector *vout)
compute the eigen vector and eigen vector of a matrix. dout is the eigen values, vout is the eigen ve...
Definition: tools.h:105
HPP_FCL_DLLAPI void getRadiusAndOriginAndRectangleSize(Vec3f *ps, Vec3f *ps2, Triangle *ts, unsigned int *indices, unsigned int n, const Matrix3f &axes, Vec3f &origin, FCL_REAL l[2], FCL_REAL &r)
Compute the RSS bounding volume parameters: radius, rectangle size and the origin, given the BV axises.
P
void segCoords(FCL_REAL &t, FCL_REAL &u, FCL_REAL a, FCL_REAL b, FCL_REAL A_dot_B, FCL_REAL A_dot_T, FCL_REAL B_dot_T)
Finds the parameters t & u corresponding to the two closest points on a pair of line segments. The first segment is defined as Pa + A*t, 0 <= t <= a, where "Pa" is one endpoint of the segment, "A" is a unit vector pointing to the other endpoint, and t is a scalar that produces all the points between the two endpoints. Since "A" is a unit vector, "a" is the segment&#39;s length. The second segment is defined as Pb + B*u, 0 <= u <= b. Many of the terms needed by the algorithm are already computed for other purposes,so we just pass these terms into the function instead of complete specifications of each segment. "T" in the dot products is the vector betweeen Pa and Pb. Reference: "On fast computation of distance between line segments." Vladimir J. Lumelsky, in Information Processing Letters, no. 21, pages 55-61, 1985.
Definition: RSS.cpp:67
list v
Definition: obb.py:45
request to the collision algorithm
RSS operator+(const RSS &other) const
Return the merged RSS of current RSS and the other one.
Definition: RSS.cpp:908
HPP_FCL_DLLAPI void getCovariance(Vec3f *ps, Vec3f *ps2, Triangle *ts, unsigned int *indices, unsigned int n, Matrix3f &M)
Compute the covariance matrix for a set or subset of points. if ts = null, then indices refer to poin...
Vec3f Tr
Origin of the rectangle in RSS.
Definition: BV/RSS.h:62
double FCL_REAL
Definition: data_types.h:65
x
A class for rectangle sphere-swept bounding volume.
Definition: BV/RSS.h:53
R
static AABB translate(const AABB &aabb, const Vec3f &t)
translate the center of AABB by t
Definition: BV/AABB.h:226
bool overlap(const RSS &other) const
Check collision between two RSS.
Definition: RSS.cpp:715
FCL_REAL radius
Radius of sphere summed with rectangle to form RSS.
Definition: BV/RSS.h:68
FCL_REAL distance(const RSS &other, Vec3f *P=NULL, Vec3f *Q=NULL) const
the distance between two RSS; P and Q, if not NULL, return the nearest points
Definition: RSS.cpp:983
bool inVoronoi(FCL_REAL a, FCL_REAL b, FCL_REAL Anorm_dot_B, FCL_REAL Anorm_dot_T, FCL_REAL A_dot_B, FCL_REAL A_dot_T, FCL_REAL B_dot_T)
Returns whether the nearest point on rectangle edge Pb + B*u, 0 <= u <= b, to the rectangle edge...
Definition: RSS.cpp:95
res
FCL_REAL length[2]
Side lengths of rectangle.
Definition: BV/RSS.h:65
Eigen::Matrix< FCL_REAL, 3, 1 > Vec3f
Definition: data_types.h:66
M
FCL_REAL rectDistance(const Matrix3f &Rab, Vec3f const &Tab, const FCL_REAL a[2], const FCL_REAL b[2], Vec3f *P=NULL, Vec3f *Q=NULL)
Distance between two oriented rectangles; P and Q (optional return values) are the closest points in ...
Definition: RSS.cpp:121
FCL_REAL security_margin
Distance below which objects are considered in collision. See Collision.


hpp-fcl
Author(s):
autogenerated on Fri Jun 2 2023 02:39:02