Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Guilhem Saurel
hpp-fcl
Commits
9cbd349b
Commit
9cbd349b
authored
Apr 25, 2013
by
isucan
Browse files
Merge pull request #10 from martinfelis/master
Added sphere-capsule routines
parents
00829132
95a27ab4
Changes
4
Hide whitespace changes
Inline
Side-by-side
include/fcl/narrowphase/narrowphase.h
View file @
9cbd349b
...
...
@@ -195,6 +195,12 @@ struct GJKSolver_libccd
};
/// @brief Fast implementation for sphere-capsule collision
template
<
>
bool
GJKSolver_libccd
::
shapeIntersect
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal
)
const
;
/// @brief Fast implementation for sphere-sphere collision
template
<
>
bool
GJKSolver_libccd
::
shapeIntersect
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
...
...
@@ -296,6 +302,12 @@ template<>
bool
GJKSolver_libccd
::
shapeTriangleIntersect
(
const
Plane
&
s
,
const
Transform3f
&
tf1
,
const
Vec3f
&
P1
,
const
Vec3f
&
P2
,
const
Vec3f
&
P3
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal
)
const
;
/// @brief Fast implementation for sphere-capsule distance
template
<
>
bool
GJKSolver_libccd
::
shapeDistance
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
FCL_REAL
*
dist
)
const
;
/// @brief Fast implementation for sphere-sphere distance
template
<
>
bool
GJKSolver_libccd
::
shapeDistance
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
...
...
src/narrowphase/narrowphase.cpp
View file @
9cbd349b
...
...
@@ -45,6 +45,91 @@ namespace fcl
namespace
details
{
// Compute the point on a line segment that is the closest point on the
// segment to to another point. The code is inspired by the explanation
// given by Dan Sunday's page:
// http://geomalgorithms.com/a02-_lines.html
static
inline
void
lineSegmentPointClosestToPoint
(
const
Vec3f
&
p
,
const
Vec3f
&
s1
,
const
Vec3f
&
s2
,
Vec3f
&
sp
)
{
Vec3f
v
=
s2
-
s1
;
Vec3f
w
=
p
-
s1
;
FCL_REAL
c1
=
w
.
dot
(
v
);
FCL_REAL
c2
=
v
.
dot
(
v
);
if
(
c1
<=
0
)
{
sp
=
s1
;
}
else
if
(
c2
<=
c1
)
{
sp
=
s2
;
}
else
{
FCL_REAL
b
=
c1
/
c2
;
Vec3f
Pb
=
s1
+
v
*
b
;
sp
=
Pb
;
}
}
bool
sphereCapsuleIntersect
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal_
)
{
Transform3f
tf2_inv
(
tf2
);
tf2_inv
.
inverse
();
Vec3f
pos1
(
0.
,
0.
,
0.5
*
s2
.
lz
);
Vec3f
pos2
(
0.
,
0.
,
-
0.5
*
s2
.
lz
);
Vec3f
s_c
=
tf2_inv
.
transform
(
tf1
.
transform
(
Vec3f
()));
Vec3f
segment_point
;
lineSegmentPointClosestToPoint
(
s_c
,
pos1
,
pos2
,
segment_point
);
Vec3f
diff
=
s_c
-
segment_point
;
FCL_REAL
distance
=
diff
.
length
()
-
s1
.
radius
-
s2
.
radius
;
if
(
distance
>
0
)
return
false
;
Vec3f
normal
=
diff
.
normalize
()
*
-
FCL_REAL
(
1
);
if
(
distance
<
0
&&
penetration_depth
)
*
penetration_depth
=
-
distance
;
if
(
normal_
)
*
normal_
=
tf2
.
getQuatRotation
().
transform
(
normal
);
if
(
contact_points
)
{
*
contact_points
=
tf2
.
transform
(
segment_point
+
normal
*
distance
);
}
return
true
;
}
bool
sphereCapsuleDistance
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
FCL_REAL
*
dist
)
{
Transform3f
tf2_inv
(
tf2
);
tf2_inv
.
inverse
();
Vec3f
pos1
(
0.
,
0.
,
0.5
*
s2
.
lz
);
Vec3f
pos2
(
0.
,
0.
,
-
0.5
*
s2
.
lz
);
Vec3f
s_c
=
tf2_inv
.
transform
(
tf1
.
transform
(
Vec3f
()));
Vec3f
segment_point
;
lineSegmentPointClosestToPoint
(
s_c
,
pos1
,
pos2
,
segment_point
);
Vec3f
diff
=
s_c
-
segment_point
;
FCL_REAL
distance
=
diff
.
length
()
-
s1
.
radius
-
s2
.
radius
;
if
(
distance
<=
0
)
return
false
;
if
(
dist
)
*
dist
=
distance
;
return
true
;
}
bool
sphereSphereIntersect
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Sphere
&
s2
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal
)
...
...
@@ -2290,6 +2375,13 @@ bool planeIntersect(const Plane& s1, const Transform3f& tf1,
}
// details
template
<
>
bool
GJKSolver_libccd
::
shapeIntersect
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal
)
const
{
return
details
::
sphereCapsuleIntersect
(
s1
,
tf1
,
s2
,
tf2
,
contact_points
,
penetration_depth
,
normal
);
}
template
<
>
bool
GJKSolver_libccd
::
shapeIntersect
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
...
...
@@ -2464,6 +2556,14 @@ bool GJKSolver_libccd::shapeTriangleIntersect(const Plane& s, const Transform3f&
template
<
>
bool
GJKSolver_libccd
::
shapeDistance
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
FCL_REAL
*
dist
)
const
{
return
details
::
sphereCapsuleDistance
(
s1
,
tf1
,
s2
,
tf2
,
dist
);
}
template
<
>
bool
GJKSolver_libccd
::
shapeDistance
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Sphere
&
s2
,
const
Transform3f
&
tf2
,
...
...
@@ -2492,7 +2592,13 @@ bool GJKSolver_libccd::shapeTriangleDistance<Sphere>(const Sphere& s, const Tran
template
<
>
bool
GJKSolver_indep
::
shapeIntersect
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
Vec3f
*
contact_points
,
FCL_REAL
*
penetration_depth
,
Vec3f
*
normal
)
const
{
return
details
::
sphereCapsuleIntersect
(
s1
,
tf1
,
s2
,
tf2
,
contact_points
,
penetration_depth
,
normal
);
}
template
<
>
bool
GJKSolver_indep
::
shapeIntersect
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
...
...
@@ -2665,6 +2771,14 @@ bool GJKSolver_indep::shapeTriangleIntersect(const Plane& s, const Transform3f&
}
template
<
>
bool
GJKSolver_indep
::
shapeDistance
<
Sphere
,
Capsule
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Capsule
&
s2
,
const
Transform3f
&
tf2
,
FCL_REAL
*
dist
)
const
{
return
details
::
sphereCapsuleDistance
(
s1
,
tf1
,
s2
,
tf2
,
dist
);
}
template
<
>
bool
GJKSolver_indep
::
shapeDistance
<
Sphere
,
Sphere
>
(
const
Sphere
&
s1
,
const
Transform3f
&
tf1
,
const
Sphere
&
s2
,
const
Transform3f
&
tf2
,
...
...
test/CMakeLists.txt
View file @
9cbd349b
...
...
@@ -27,6 +27,8 @@ add_fcl_test(test_fcl_shape_mesh_consistency test_fcl_shape_mesh_consistency.cpp
add_fcl_test
(
test_fcl_frontlist test_fcl_frontlist.cpp test_fcl_utility.cpp
)
add_fcl_test
(
test_fcl_math test_fcl_math.cpp test_fcl_utility.cpp
)
add_fcl_test
(
test_fcl_sphere_capsule test_fcl_sphere_capsule.cpp
)
if
(
FCL_HAVE_OCTOMAP
)
add_fcl_test
(
test_fcl_octomap test_fcl_octomap.cpp test_fcl_utility.cpp
)
endif
()
test/test_fcl_sphere_capsule.cpp
0 → 100644
View file @
9cbd349b
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2011, Willow Garage, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Willow Garage, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** \author Martin Felis <martin.felis@iwr.uni-heidelberg.de> */
#define BOOST_TEST_MODULE "FCL_SPHERE_CAPSULE"
#include
<boost/test/unit_test.hpp>
#include
"fcl/collision.h"
#include
"fcl/shape/geometric_shapes.h"
#include
"fcl/narrowphase/narrowphase.h"
using
namespace
fcl
;
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_separated_z
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
0.
,
0.
,
200
));
BOOST_CHECK
(
!
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
NULL
,
NULL
,
NULL
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_separated_z_negative
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
0.
,
0.
,
-
200
));
BOOST_CHECK
(
!
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
NULL
,
NULL
,
NULL
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_separated_x
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
150.
,
0.
,
0.
));
BOOST_CHECK
(
!
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
NULL
,
NULL
,
NULL
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_separated_capsule_rotated
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Matrix3f
rotation
;
rotation
.
setEulerZYX
(
M_PI
*
0.5
,
0.
,
0.
);
Transform3f
capsule_transform
(
rotation
,
Vec3f
(
150.
,
0.
,
0.
));
BOOST_CHECK
(
!
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
NULL
,
NULL
,
NULL
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_penetration_z
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
0.
,
0.
,
125
));
FCL_REAL
penetration
=
0.
;
Vec3f
contact_point
;
Vec3f
normal
;
bool
is_intersecting
=
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
&
contact_point
,
&
penetration
,
&
normal
);
BOOST_CHECK
(
is_intersecting
);
BOOST_CHECK
(
penetration
==
25.
);
BOOST_CHECK
(
Vec3f
(
0.
,
0.
,
1.
).
equal
(
normal
));
BOOST_CHECK
(
Vec3f
(
0.
,
0.
,
0.
).
equal
(
contact_point
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Intersect_test_penetration_z_rotated
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
0
));
Capsule
capsule
(
50
,
200.
);
Matrix3f
rotation
;
rotation
.
setEulerZYX
(
M_PI
*
0.5
,
0.
,
0.
);
Transform3f
capsule_transform
(
rotation
,
Vec3f
(
0.
,
50.
,
75
));
FCL_REAL
penetration
=
0.
;
Vec3f
contact_point
;
Vec3f
normal
;
bool
is_intersecting
=
solver
.
shapeIntersect
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
&
contact_point
,
&
penetration
,
&
normal
);
BOOST_CHECK
(
is_intersecting
);
BOOST_CHECK_CLOSE
(
25
,
penetration
,
solver
.
collision_tolerance
);
BOOST_CHECK
(
Vec3f
(
0.
,
0.
,
1.
).
equal
(
normal
));
BOOST_CHECK
(
Vec3f
(
0.
,
0.
,
50.
).
equal
(
contact_point
,
solver
.
collision_tolerance
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Distance_test_collision
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
0.
,
0.
,
100
));
FCL_REAL
distance
;
BOOST_CHECK
(
!
solver
.
shapeDistance
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
&
distance
));
}
BOOST_AUTO_TEST_CASE
(
Sphere_Capsule_Distance_test_separated
)
{
GJKSolver_libccd
solver
;
Sphere
sphere1
(
50
);
Transform3f
sphere1_transform
;
sphere1_transform
.
setTranslation
(
Vec3f
(
0.
,
0.
,
-
50
));
Capsule
capsule
(
50
,
200.
);
Transform3f
capsule_transform
(
Vec3f
(
0.
,
0.
,
175
));
FCL_REAL
distance
=
0.
;
bool
is_separated
=
solver
.
shapeDistance
(
sphere1
,
sphere1_transform
,
capsule
,
capsule_transform
,
&
distance
);
BOOST_CHECK
(
is_separated
);
BOOST_CHECK
(
distance
==
25.
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment