diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c31180fde33d969aba79ddec970c05288bbb36ce..23688c2226e9c4d4b05548680edb1bfc43dd9e9e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -53,6 +53,8 @@ set(${LIBRARY_NAME}_SOURCES
   distance_capsule_capsule.cpp
   distance_capsule_halfspace.cpp
   distance_capsule_plane.cpp
+  distance_cone_halfspace.cpp
+  distance_cone_plane.cpp
   distance_cylinder_halfspace.cpp
   distance_cylinder_plane.cpp
   distance_sphere_sphere.cpp
diff --git a/src/distance_cone_halfspace.cpp b/src/distance_cone_halfspace.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f895ac0b6f96112310f86d2302ec1bbbadcac9b6
--- /dev/null
+++ b/src/distance_cone_halfspace.cpp
@@ -0,0 +1,81 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011-2014, Willow Garage, Inc.
+ *  Copyright (c) 2014-2015, Open Source Robotics Foundation
+ *  Copyright (c) 2018-2019, Center National de la Recherche Scientifique
+ *  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 Open Source Robotics Foundation 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 Florent Lamiraux */
+
+#include <cmath>
+#include <limits>
+#include <hpp/fcl/math/transform.h>
+#include <hpp/fcl/shape/geometric_shapes.h>
+#include "distance_func_matrix.h"
+#include "../src/narrowphase/details.h"
+
+namespace fcl {
+    class GJKSolver_indep;
+
+  template <>
+  FCL_REAL ShapeShapeDistance <Cone, Halfspace, GJKSolver_indep>
+  (const CollisionGeometry* o1, const Transform3f& tf1,
+   const CollisionGeometry* o2, const Transform3f& tf2,
+   const GJKSolver_indep*, const DistanceRequest& request,
+   DistanceResult& result)
+  {
+    const Cone& s1 = static_cast <const Cone&> (*o1);
+    const Halfspace& s2 = static_cast <const Halfspace&> (*o2);
+    bool col = details::coneHalfspaceIntersect
+      (s1, tf1, s2, tf2, result.min_distance, result.nearest_points [0],
+       result.nearest_points [1], result.normal);
+    result.o1 = o1; result.o2 = o2; result.b1 = -1; result.b2 = -1;
+    return result.min_distance;
+  }
+
+  template <>
+  FCL_REAL ShapeShapeDistance <Halfspace, Cone, GJKSolver_indep>
+  (const CollisionGeometry* o1, const Transform3f& tf1,
+   const CollisionGeometry* o2, const Transform3f& tf2,
+   const GJKSolver_indep*, const DistanceRequest& request,
+   DistanceResult& result)
+  {
+    const Halfspace& s1 = static_cast <const Halfspace&> (*o1);
+    const Cone& s2 = static_cast <const Cone&> (*o2);
+    bool col = details::coneHalfspaceIntersect
+      (s2, tf2, s1, tf1, result.min_distance, result.nearest_points [1],
+       result.nearest_points [0], result.normal);
+    result.o1 = o1; result.o2 = o2; result.b1 = -1; result.b2 = -1;
+    result.normal = -result.normal;
+    return result.min_distance;
+  }
+} // namespace fcl
diff --git a/src/distance_cone_plane.cpp b/src/distance_cone_plane.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6087cda7c467b3ba6bf8dd039a0065d6e3b56934
--- /dev/null
+++ b/src/distance_cone_plane.cpp
@@ -0,0 +1,81 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ *  Copyright (c) 2011-2014, Willow Garage, Inc.
+ *  Copyright (c) 2014-2015, Open Source Robotics Foundation
+ *  Copyright (c) 2018-2019, Center National de la Recherche Scientifique
+ *  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 Open Source Robotics Foundation 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 Florent Lamiraux */
+
+#include <cmath>
+#include <limits>
+#include <hpp/fcl/math/transform.h>
+#include <hpp/fcl/shape/geometric_shapes.h>
+#include "distance_func_matrix.h"
+#include "../src/narrowphase/details.h"
+
+namespace fcl {
+    class GJKSolver_indep;
+
+  template <>
+  FCL_REAL ShapeShapeDistance <Cone, Plane, GJKSolver_indep>
+  (const CollisionGeometry* o1, const Transform3f& tf1,
+   const CollisionGeometry* o2, const Transform3f& tf2,
+   const GJKSolver_indep*, const DistanceRequest& request,
+   DistanceResult& result)
+  {
+    const Cone& s1 = static_cast <const Cone&> (*o1);
+    const Plane& s2 = static_cast <const Plane&> (*o2);
+    bool col = details::conePlaneIntersect
+      (s1, tf1, s2, tf2, result.min_distance, result.nearest_points [0],
+       result.nearest_points [1], result.normal);
+    result.o1 = o1; result.o2 = o2; result.b1 = -1; result.b2 = -1;
+    return result.min_distance;
+  }
+
+  template <>
+  FCL_REAL ShapeShapeDistance <Plane, Cone, GJKSolver_indep>
+  (const CollisionGeometry* o1, const Transform3f& tf1,
+   const CollisionGeometry* o2, const Transform3f& tf2,
+   const GJKSolver_indep*, const DistanceRequest& request,
+   DistanceResult& result)
+  {
+    const Plane& s1 = static_cast <const Plane&> (*o1);
+    const Cone& s2 = static_cast <const Cone&> (*o2);
+    bool col = details::conePlaneIntersect
+      (s2, tf2, s1, tf1, result.min_distance, result.nearest_points [1],
+       result.nearest_points [0], result.normal);
+    result.o1 = o1; result.o2 = o2; result.b1 = -1; result.b2 = -1;
+    result.normal = -result.normal;
+    return result.min_distance;
+  }
+} // namespace fcl
diff --git a/src/narrowphase/details.h b/src/narrowphase/details.h
index 817a6b7ab44e8a7f53f6b79f23a032a2e8ebada3..3cc3f63682a5e1838de83bbae1519ffc1542af40 100644
--- a/src/narrowphase/details.h
+++ b/src/narrowphase/details.h
@@ -1651,7 +1651,8 @@ namespace fcl {
     inline bool coneHalfspaceIntersect
       (const Cone& s1, const Transform3f& tf1,
        const Halfspace& s2, const Transform3f& tf2,
-       Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal)
+       FCL_REAL& distance, Vec3f& p1, Vec3f& p2,
+       Vec3f& normal)
     {
       Halfspace new_s2 = transform(s2, tf2);
 
@@ -1664,20 +1665,24 @@ namespace fcl {
       if(cosa < halfspaceIntersectTolerance<FCL_REAL>())
         {
           FCL_REAL signed_dist = new_s2.signedDistance(T);
-          FCL_REAL depth = s1.radius - signed_dist;
-          if(depth < 0) return false;
+          distance = signed_dist - s1.radius;
+          if(distance > 0) {
+            p1 = p2 = Vec3f (0, 0, 0);
+            return false;
+          }
           else
             {
-              if(penetration_depth) *penetration_depth = depth;
-              if(normal) *normal = -new_s2.n;
-              if(contact_points) *contact_points = T - dir_z * (s1.lz * 0.5) + new_s2.n * (0.5 * depth - s1.radius);
+              normal = -new_s2.n;
+              p1 = p2 = T - dir_z * (s1.lz * 0.5) -
+                new_s2.n * (0.5 * distance + s1.radius);
               return true;
             }
         }
       else
         {
           Vec3f C = dir_z * cosa - new_s2.n;
-          if(std::abs(cosa + 1) < halfspaceIntersectTolerance<FCL_REAL>() || std::abs(cosa - 1) < halfspaceIntersectTolerance<FCL_REAL>())
+          if(std::abs(cosa + 1) < halfspaceIntersectTolerance<FCL_REAL>() ||
+             std::abs(cosa - 1) < halfspaceIntersectTolerance<FCL_REAL>())
             C = Vec3f(0, 0, 0);
           else
             {
@@ -1686,19 +1691,18 @@ namespace fcl {
               C *= s;
             }
 
-          Vec3f p1 = T + dir_z * (0.5 * s1.lz);
-          Vec3f p2 = T - dir_z * (0.5 * s1.lz) + C;
+          Vec3f a1 = T + dir_z * (0.5 * s1.lz);
+          Vec3f a2 = T - dir_z * (0.5 * s1.lz) + C;
 
-          FCL_REAL d1 = new_s2.signedDistance(p1);
-          FCL_REAL d2 = new_s2.signedDistance(p2);
+          FCL_REAL d1 = new_s2.signedDistance(a1);
+          FCL_REAL d2 = new_s2.signedDistance(a2);
 
           if(d1 > 0 && d2 > 0) return false;
           else
             {
-              FCL_REAL depth = -std::min(d1, d2);
-              if(penetration_depth) *penetration_depth = depth;
-              if(normal) *normal = -new_s2.n;
-              if(contact_points) *contact_points = ((d1 < d2) ? p1 : p2) + new_s2.n * (0.5 * depth);
+              distance = std::min(d1, d2);
+              normal = -new_s2.n;
+              p1 = p2 = ((d1 < d2) ? a1 : a2) - (0.5 * distance) * new_s2.n;
               return true;
             }
         }
@@ -2215,7 +2219,8 @@ namespace fcl {
     inline bool conePlaneIntersect
       (const Cone& s1, const Transform3f& tf1,
        const Plane& s2, const Transform3f& tf2,
-       Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal)
+       FCL_REAL& distance, Vec3f& p1, Vec3f& p2,
+       Vec3f& normal)
     {
       Plane new_s2 = transform(s2, tf2);
 
@@ -2228,20 +2233,24 @@ namespace fcl {
       if(std::abs(cosa) < planeIntersectTolerance<FCL_REAL>())
         {
           FCL_REAL d = new_s2.signedDistance(T);
-          FCL_REAL depth = s1.radius - std::abs(d);
-          if(depth < 0) return false;
+          distance = std::abs(d) - s1.radius;
+          if(distance > 0) {
+            p1 = p2 = Vec3f (0,0,0);
+            return false;
+          }
           else
             {
-              if(penetration_depth) *penetration_depth = depth;
-              if(normal) { if (d < 0) *normal = new_s2.n; else *normal = -new_s2.n; }
-              if(contact_points) *contact_points = T - dir_z * (0.5 * s1.lz) + dir_z * (0.5 * depth / s1.radius * s1.lz) - new_s2.n * d;
+              if (d < 0) normal = new_s2.n; else normal = -new_s2.n;
+              p1 = p2 = T - dir_z * (0.5 * s1.lz) +
+                dir_z * (-0.5 * distance / s1.radius * s1.lz) - new_s2.n * d;
               return true;
             }
         }
       else
         {
           Vec3f C = dir_z * cosa - new_s2.n;
-          if(std::abs(cosa + 1) < planeIntersectTolerance<FCL_REAL>() || std::abs(cosa - 1) < planeIntersectTolerance<FCL_REAL>())
+          if(std::abs(cosa + 1) < planeIntersectTolerance<FCL_REAL>() ||
+             std::abs(cosa - 1) < planeIntersectTolerance<FCL_REAL>())
             C = Vec3f(0, 0, 0);
           else
             {
@@ -2260,7 +2269,8 @@ namespace fcl {
           d[1] = new_s2.signedDistance(c[1]);
           d[2] = new_s2.signedDistance(c[2]);
 
-          if((d[0] >= 0 && d[1] >= 0 && d[2] >= 0) || (d[0] <= 0 && d[1] <= 0 && d[2] <= 0))
+          if((d[0] >= 0 && d[1] >= 0 && d[2] >= 0) ||
+             (d[0] <= 0 && d[1] <= 0 && d[2] <= 0))
             return false;
           else
             {
@@ -2283,43 +2293,41 @@ namespace fcl {
                     }
                 }
 
-              if(penetration_depth) *penetration_depth = std::min(d_positive, d_negative);
-              if(normal) { if (d_positive > d_negative) *normal = -new_s2.n; else *normal = new_s2.n; }
-              if(contact_points)
-                {
-                  Vec3f p[2];
-                  Vec3f q;
-
-                  FCL_REAL p_d[2];
-                  FCL_REAL q_d(0);
+              distance = -std::min(d_positive, d_negative);
+              if (d_positive > d_negative) normal = -new_s2.n;
+              else normal = new_s2.n;
+              Vec3f p[2];
+              Vec3f q;
 
-                  if(n_positive == 2)
-                    {
-                      for(std::size_t i = 0, j = 0; i < 3; ++i)
-                        {
-                          if(positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
-                          else { q = c[i]; q_d = d[i]; }
-                        }
+              FCL_REAL p_d[2];
+              FCL_REAL q_d(0);
 
-                      Vec3f t1 = (-p[0] * q_d + q * p_d[0]) / (-q_d + p_d[0]);
-                      Vec3f t2 = (-p[1] * q_d + q * p_d[1]) / (-q_d + p_d[1]);
-                      *contact_points = (t1 + t2) * 0.5;
-                    }
-                  else
-                    {
-                      for(std::size_t i = 0, j = 0; i < 3; ++i)
-                        {
-                          if(!positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
-                          else { q = c[i]; q_d = d[i]; }
-                        }
+              if(n_positive == 2)
+              {
+                for(std::size_t i = 0, j = 0; i < 3; ++i)
+                {
+                  if(positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
+                  else { q = c[i]; q_d = d[i]; }
+                }
 
-                      Vec3f t1 = (p[0] * q_d - q * p_d[0]) / (q_d - p_d[0]);
-                      Vec3f t2 = (p[1] * q_d - q * p_d[1]) / (q_d - p_d[1]);
-                      *contact_points = (t1 + t2) * 0.5;
-                    }
+                Vec3f t1 = (-p[0] * q_d + q * p_d[0]) / (-q_d + p_d[0]);
+                Vec3f t2 = (-p[1] * q_d + q * p_d[1]) / (-q_d + p_d[1]);
+                p1 = p2 = (t1 + t2) * 0.5;
+              }
+              else
+              {
+                for(std::size_t i = 0, j = 0; i < 3; ++i)
+                {
+                  if(!positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
+                  else { q = c[i]; q_d = d[i]; }
                 }
-              return true;
+
+                Vec3f t1 = (p[0] * q_d - q * p_d[0]) / (q_d - p_d[0]);
+                Vec3f t2 = (p[1] * q_d - q * p_d[1]) / (q_d - p_d[1]);
+                p1 = p2 = (t1 + t2) * 0.5;
+              }
             }
+          return true;
         }
     }
 
diff --git a/src/narrowphase/narrowphase.cpp b/src/narrowphase/narrowphase.cpp
index b3b52d6c1f92f2d9a24ffb4d8ce2d64485f50d2a..7f32458d31949009200c8923af05ee21dd022d12 100644
--- a/src/narrowphase/narrowphase.cpp
+++ b/src/narrowphase/narrowphase.cpp
@@ -266,20 +266,32 @@ bool GJKSolver_indep::shapeIntersect<Halfspace, Cylinder>
 }
 
 template<>
-bool GJKSolver_indep::shapeIntersect<Cone, Halfspace>(const Cone& s1, const Transform3f& tf1,
-                                                      const Halfspace& s2, const Transform3f& tf2,
-                                                      Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
+bool GJKSolver_indep::shapeIntersect<Cone, Halfspace>
+(const Cone& s1, const Transform3f& tf1,
+ const Halfspace& s2, const Transform3f& tf2,
+ Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
 {
-  return details::coneHalfspaceIntersect(s1, tf1, s2, tf2, contact_points, penetration_depth, normal);
+  FCL_REAL distance;
+  Vec3f p1, p2;
+  bool res =  details::coneHalfspaceIntersect
+    (s1, tf1, s2, tf2, distance, p1, p2, *normal);
+  *contact_points = p1;
+  *penetration_depth = -distance;
 }
 
 template<>
-bool GJKSolver_indep::shapeIntersect<Halfspace, Cone>(const Halfspace& s1, const Transform3f& tf1,
-                                                      const Cone& s2, const Transform3f& tf2,
-                                                      Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
+bool GJKSolver_indep::shapeIntersect<Halfspace, Cone>
+(const Halfspace& s1, const Transform3f& tf1,
+ const Cone& s2, const Transform3f& tf2,
+ Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
 {
-  const bool res = details::coneHalfspaceIntersect(s2, tf2, s1, tf1, contact_points, penetration_depth, normal);
-  if (normal) (*normal) *= -1.0;
+  FCL_REAL distance;
+  Vec3f p1, p2;
+  bool res =  details::coneHalfspaceIntersect
+    (s2, tf2, s1, tf1, distance, p1, p2, *normal);
+  *contact_points = p1;
+  *penetration_depth = -distance;
+  (*normal) *= -1.0;
   return res;
 }
 
@@ -431,20 +443,33 @@ bool GJKSolver_indep::shapeIntersect<Plane, Cylinder>
 }
 
 template<>
-bool GJKSolver_indep::shapeIntersect<Cone, Plane>(const Cone& s1, const Transform3f& tf1,
-                                                  const Plane& s2, const Transform3f& tf2,
-                                                  Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
+bool GJKSolver_indep::shapeIntersect<Cone, Plane>
+(const Cone& s1, const Transform3f& tf1,
+ const Plane& s2, const Transform3f& tf2,
+ Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
 {
-  return details::conePlaneIntersect(s1, tf1, s2, tf2, contact_points, penetration_depth, normal);
+  FCL_REAL distance;
+  Vec3f p1, p2;
+  bool res = details::conePlaneIntersect
+    (s1, tf1, s2, tf2, distance, p1, p2, *normal);
+  *contact_points = p1;
+  *penetration_depth = -distance;
+  return res;
 }
 
 template<>
-bool GJKSolver_indep::shapeIntersect<Plane, Cone>(const Plane& s1, const Transform3f& tf1,
-                                                  const Cone& s2, const Transform3f& tf2,
-                                                  Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
+bool GJKSolver_indep::shapeIntersect<Plane, Cone>
+(const Plane& s1, const Transform3f& tf1,
+ const Cone& s2, const Transform3f& tf2,
+ Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
 {
-  const bool res = details::conePlaneIntersect(s2, tf2, s1, tf1, contact_points, penetration_depth, normal);
-  if (normal) (*normal) *= -1.0;
+  FCL_REAL distance;
+  Vec3f p1, p2;
+  bool res = details::conePlaneIntersect
+    (s2, tf2, s1, tf1, distance, p1, p2, *normal);
+  *contact_points = p1;
+  *penetration_depth = -distance;
+  (*normal) *= -1.0;
   return res;
 }