FCL  0.6.0
Flexible Collision Library
capsule_capsule-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, 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 #ifndef FCL_NARROWPHASE_DETAIL_CAPSULECAPSULE_INL_H
39 #define FCL_NARROWPHASE_DETAIL_CAPSULECAPSULE_INL_H
40 
41 #include "fcl/narrowphase/detail/primitive_shape_algorithm/capsule_capsule.h"
42 
43 namespace fcl
44 {
45 
46 namespace detail
47 {
48 
49 //==============================================================================
50 extern template
51 double clamp(double n, double min, double max);
52 
53 //==============================================================================
54 extern template
55 double closestPtSegmentSegment(
56  Vector3d p1, Vector3d q1, Vector3d p2, Vector3d q2,
57  double &s, double& t, Vector3d &c1, Vector3d &c2);
58 
59 //==============================================================================
60 extern template
61 bool capsuleCapsuleDistance(
62  const Capsule<double>& s1, const Transform3<double>& tf1,
63  const Capsule<double>& s2, const Transform3<double>& tf2,
64  double* dist, Vector3d* p1_res, Vector3d* p2_res);
65 
66 //==============================================================================
67 template <typename S>
68 S clamp(S n, S min, S max)
69 {
70  if (n < min) return min;
71  if (n > max) return max;
72  return n;
73 }
74 
75 //==============================================================================
76 template <typename S>
77 S closestPtSegmentSegment(
78  Vector3<S> p1, Vector3<S> q1, Vector3<S> p2, Vector3<S> q2,
79  S &s, S &t, Vector3<S> &c1, Vector3<S> &c2)
80 {
81  const S EPSILON = 0.001;
82  Vector3<S> d1 = q1 - p1; // Direction vector of segment S1
83  Vector3<S> d2 = q2 - p2; // Direction vector of segment S2
84  Vector3<S> r = p1 - p2;
85  S a = d1.dot(d1); // Squared length of segment S1, always nonnegative
86 
87  S e = d2.dot(d2); // Squared length of segment S2, always nonnegative
88  S f = d2.dot(r);
89  // Check if either or both segments degenerate into points
90  if (a <= EPSILON && e <= EPSILON) {
91  // Both segments degenerate into points
92  s = t = 0.0;
93  c1 = p1;
94  c2 = p2;
95  Vector3<S> diff = c1-c2;
96  S res = diff.dot(diff);
97  return res;
98  }
99  if (a <= EPSILON) {
100  // First segment degenerates into a point
101  s = 0.0;
102  t = f / e; // s = 0 => t = (b*s + f) / e = f / e
103  t = clamp(t, (S)0.0, (S)1.0);
104  } else {
105  S c = d1.dot(r);
106  if (e <= EPSILON) {
107  // Second segment degenerates into a point
108  t = 0.0;
109  s = clamp(-c / a, (S)0.0, (S)1.0); // t = 0 => s = (b*t - c) / a = -c / a
110  } else {
111  // The general nondegenerate case starts here
112  S b = d1.dot(d2);
113  S denom = a*e-b*b; // Always nonnegative
114  // If segments not parallel, compute closest point on L1 to L2 and
115  // clamp to segment S1. Else pick arbitrary s (here 0)
116  if (denom != 0.0) {
117  std::cerr << "denominator equals zero, using 0 as reference" << std::endl;
118  s = clamp((b*f - c*e) / denom, (S)0.0, (S)1.0);
119  } else s = 0.0;
120  // Compute point on L2 closest to S1(s) using
121  // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
122  t = (b*s + f) / e;
123 
124  //
125  //If t in [0,1] done. Else clamp t, recompute s for the new value
126  //of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
127  //and clamp s to [0, 1]
128  if(t < 0.0) {
129  t = 0.0;
130  s = clamp(-c / a, (S)0.0, (S)1.0);
131  } else if (t > 1.0) {
132  t = 1.0;
133  s = clamp((b - c) / a, (S)0.0, (S)1.0);
134  }
135  }
136  }
137  c1 = p1 + d1 * s;
138  c2 = p2 + d2 * t;
139  Vector3<S> diff = c1-c2;
140  S res = diff.dot(diff);
141  return res;
142 }
143 
144 //==============================================================================
145 template <typename S>
146 bool capsuleCapsuleDistance(const Capsule<S>& s1, const Transform3<S>& tf1,
147  const Capsule<S>& s2, const Transform3<S>& tf2,
148  S* dist, Vector3<S>* p1_res, Vector3<S>* p2_res)
149 {
150 
151  Vector3<S> p1(tf1.translation());
152  Vector3<S> p2(tf2.translation());
153 
154  // line segment composes two points. First point is given by the origin, second point is computed by the origin transformed along z.
155  // extension along z-axis means transformation with identity matrix and translation vector z pos
156  Transform3<S> transformQ1 = tf1 * Translation3<S>(Vector3<S>(0,0,s1.lz));
157  Vector3<S> q1 = transformQ1.translation();
158 
159  Transform3<S> transformQ2 = tf2 * Translation3<S>(Vector3<S>(0,0,s2.lz));
160  Vector3<S> q2 = transformQ2.translation();
161 
162  // s and t correspont to the length of the line segment
163  S s, t;
164  Vector3<S> c1, c2;
165 
166  S result = closestPtSegmentSegment(p1, q1, p2, q2, s, t, c1, c2);
167  *dist = sqrt(result)-s1.radius-s2.radius;
168 
169  // getting directional unit vector
170  Vector3<S> distVec = c2 -c1;
171  distVec.normalize();
172 
173  // extend the point to be border of the capsule.
174  // Done by following the directional unit vector for the length of the capsule radius
175  *p1_res = c1 + distVec*s1.radius;
176 
177  distVec = c1-c2;
178  distVec.normalize();
179 
180  *p2_res = c2 + distVec*s2.radius;
181 
182  return true;
183 }
184 
185 } // namespace detail
186 } // namespace fcl
187 
188 #endif
Main namespace.
Definition: broadphase_bruteforce-inl.h:45