diff --git a/include/fcl/narrowphase/narrowphase.h b/include/fcl/narrowphase/narrowphase.h
index 36c361013d87f7ca308a4b8b4d5aa9ed6c14ff5a..54e3459a1542cd9d3c1ca78ac3f808521139b4f3 100644
--- a/include/fcl/narrowphase/narrowphase.h
+++ b/include/fcl/narrowphase/narrowphase.h
@@ -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,
diff --git a/src/narrowphase/narrowphase.cpp b/src/narrowphase/narrowphase.cpp
index cbdec59204c6c714f6593c37e91107c6d016f624..4102e0314dcf430d091f932a3de9636d4ed53ca7 100644
--- a/src/narrowphase/narrowphase.cpp
+++ b/src/narrowphase/narrowphase.cpp
@@ -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,
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5c21b4cc501e616f778670dba7c12403445149b3..6638b19ef5847404a4aeaecba8315c50a32e90cd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -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()
diff --git a/test/test_fcl_sphere_capsule.cpp b/test/test_fcl_sphere_capsule.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eb4a421d3c5268f3d290624f6e5895e1143a4a2f
--- /dev/null
+++ b/test/test_fcl_sphere_capsule.cpp
@@ -0,0 +1,185 @@
+/*
+ *  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.);
+}