diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc4b724f519fe0ab86b6862de0be077852292fd9..fd5c5080ef87d472d14eb7af1a955b29dbb5e08b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,6 +57,8 @@ SET (${PROJECT_NAME}_HEADERS
   include/hpp/manipulation/robot.hh
   include/hpp/manipulation/roadmap.hh
   include/hpp/manipulation/manipulation-planner.hh
+  include/hpp/manipulation/path-projector.hh
+  include/hpp/manipulation/path-projector/dichotomy.hh
   include/hpp/manipulation/graph-path-validation.hh
   include/hpp/manipulation/graph-steering-method.hh
   include/hpp/manipulation/graph/node.hh
diff --git a/include/hpp/manipulation/fwd.hh b/include/hpp/manipulation/fwd.hh
index 503966d203e49398acaacc427c68cee79d735d97..bcc0762b5419b8be9133ba9383f88f0780f8c62f 100644
--- a/include/hpp/manipulation/fwd.hh
+++ b/include/hpp/manipulation/fwd.hh
@@ -76,6 +76,11 @@ namespace hpp {
     typedef boost::shared_ptr < GraphPathValidation > GraphPathValidationPtr_t;
     HPP_PREDEF_CLASS (GraphSteeringMethod);
     typedef boost::shared_ptr < GraphSteeringMethod > GraphSteeringMethodPtr_t;
+    HPP_PREDEF_CLASS (PathProjector);
+    typedef PathProjector* PathProjectorPtr_t;
+    namespace pathProjector {
+      HPP_PREDEF_CLASS (Dichotomy);
+    }
 
     typedef std::vector <DevicePtr_t> Devices_t;
     typedef std::vector <ObjectPtr_t> Objects_t;
diff --git a/include/hpp/manipulation/manipulation-planner.hh b/include/hpp/manipulation/manipulation-planner.hh
index 3045a16e7ce34d5c6159bfd8f8c46013c3a97ba0..b47ea3f562b9622b8fc0a6caba98fa65c750a50c 100644
--- a/include/hpp/manipulation/manipulation-planner.hh
+++ b/include/hpp/manipulation/manipulation-planner.hh
@@ -85,14 +85,15 @@ namespace hpp {
         enum TypeOfFailure {
           PROJECTION,
           STEERING_METHOD,
-          PATH_VALIDATION
+          PATH_VALIDATION,
+          PATH_PROJECTION
         };
         struct Reasons {
           typedef ::hpp::statistics::SuccessBin::Reason Reason;
-          Reason projFailed, smFailed, pvFailed;
+          Reason projFailed, smFailed, pvFailed, pprojFailed;
 
-          Reasons (const Reason& proj, const Reason& sm, const Reason& pv) :
-            projFailed (proj), smFailed (sm), pvFailed (pv) {}
+          Reasons (const Reason& proj, const Reason& sm, const Reason& pv, const Reason& pp) :
+            projFailed (proj), smFailed (sm), pvFailed (pv), pprojFailed (pp) {}
           const Reason& get (TypeOfFailure t)
           {
             switch (t) {
@@ -102,6 +103,8 @@ namespace hpp {
                 return smFailed;
               case PATH_VALIDATION:
                 return pvFailed;
+              case PATH_PROJECTION:
+                return pprojFailed;
             }
             return ::hpp::statistics::SuccessBin::REASON_UNKNOWN;
           }
@@ -112,6 +115,8 @@ namespace hpp {
 
         void addFailure (TypeOfFailure t, const graph::EdgePtr_t& edge);
 
+        PathProjectorPtr_t pathProjector_;
+
         mutable Configuration_t qProj_;
     };
   } // namespace manipulation
diff --git a/include/hpp/manipulation/path-projector.hh b/include/hpp/manipulation/path-projector.hh
new file mode 100644
index 0000000000000000000000000000000000000000..f1ba4fc26511f1311bdc4b213eddbb09edc6e580
--- /dev/null
+++ b/include/hpp/manipulation/path-projector.hh
@@ -0,0 +1,63 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HPP_MANIPULATION_PATHPROJECTOR_HH
+# define HPP_MANIPULATION_PATHPROJECTOR_HH
+
+# include "hpp/manipulation/config.hh"
+# include "hpp/manipulation/fwd.hh"
+
+# include <hpp/core/path.hh>
+# include <hpp/core/straight-path.hh>
+
+namespace hpp {
+  namespace manipulation {
+    /// This class projects a path using constraints.
+    class HPP_MANIPULATION_DLLAPI PathProjector
+    {
+      public:
+        typedef hpp::core::Path Path;
+        typedef hpp::core::PathPtr_t PathPtr_t;
+        typedef hpp::core::StraightPath StraightPath;
+        typedef hpp::core::StraightPathPtr_t StraightPathPtr_t;
+        typedef hpp::core::PathVector PathVector;
+        typedef hpp::core::PathVectorPtr_t PathVectorPtr_t;
+
+        /// Destructor
+        virtual ~PathProjector ();
+
+        /// Apply the constraints to the path.
+        /// \param[in] the input path,
+        /// \param[out] the output path.
+        /// \return True if projection succeded
+        bool apply (const PathPtr_t path, PathPtr_t& projection) const;
+
+      protected:
+        /// Constructor
+        PathProjector (const core::DistancePtr_t distance);
+
+        /// Method to be reimplemented by inherited class.
+        virtual bool impl_apply (const StraightPathPtr_t path, PathPtr_t& projection) const = 0;
+
+        value_type d (ConfigurationIn_t q1, ConfigurationIn_t q2) const;
+
+      private:
+        core::DistancePtr_t distance_;
+    };
+  } // namespace manipulation
+} // namespace hpp
+
+#endif // HPP_MANIPULATION_PATHPROJECTOR_HH
diff --git a/include/hpp/manipulation/path-projector/dichotomy.hh b/include/hpp/manipulation/path-projector/dichotomy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6e9871b3e188feaa9d635193064ecbbd2689feef
--- /dev/null
+++ b/include/hpp/manipulation/path-projector/dichotomy.hh
@@ -0,0 +1,38 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HPP_MANIPULATION_PATHPROJECTOR_DICHOTOMY_HH
+# define HPP_MANIPULATION_PATHPROJECTOR_DICHOTOMY_HH
+
+# include "hpp/manipulation/path-projector.hh"
+namespace hpp {
+  namespace manipulation {
+    namespace pathProjector {
+      class HPP_MANIPULATION_DLLAPI Dichotomy : public PathProjector
+      {
+        public:
+          Dichotomy (const core::DistancePtr_t distance, value_type maxPathLength);
+
+        protected:
+          bool impl_apply (const StraightPathPtr_t path, PathPtr_t& projection) const;
+
+        private:
+          value_type maxPathLength_;
+      };
+    } // namespace pathProjector
+  } // namespace manipulation
+} // namespace hpp
+#endif // HPP_MANIPULATION_PATHPROJECTOR_DICHOTOMY_HH
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3073519ccdb3e474d0606410f935a304c20b8ec5..23ca6b1c02b78f87b84f6e337da14145c4a6d667 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,9 @@ ADD_LIBRARY(${LIBRARY_NAME} SHARED
   graph-path-validation.cc
   graph-steering-method.cc
 
+  path-projector.cc
+  path-projector/dichotomy.cc
+
   graph/node.cc
   graph/edge.cc
   graph/graph.cc
diff --git a/src/manipulation-planner.cc b/src/manipulation-planner.cc
index 3fe36ae9914fd7e0f91ebfa16f0af81984488802..9f73089f1270f2a610b5516e936e0932b8b733a7 100644
--- a/src/manipulation-planner.cc
+++ b/src/manipulation-planner.cc
@@ -21,6 +21,8 @@
 #include "hpp/manipulation/graph/statistics.hh"
 #include "hpp/manipulation/robot.hh"
 #include "hpp/manipulation/problem.hh"
+#include "hpp/manipulation/path-projector.hh"
+#include "hpp/manipulation/path-projector/dichotomy.hh"
 #include "hpp/manipulation/manipulation-planner.hh"
 #include "hpp/manipulation/graph/edge.hh"
 
@@ -116,6 +118,11 @@ namespace hpp {
         addFailure (STEERING_METHOD, edge);
         return false;
       }
+      core::PathPtr_t projPath;
+      if (!pathProjector_->apply (path, projPath)) {
+        addFailure (PATH_PROJECTION, edge);
+        if (!projPath || projPath->length () == 0) return false;
+      }
       GraphPathValidationPtr_t pathValidation (problem_.pathValidation ());
       pathValidation->validate (path, false, validPath);
       if (validPath->length () == 0)
@@ -136,7 +143,8 @@ namespace hpp {
         std::string edgeStr = "(" + edge->name () + ")";
         Reasons r (SuccessBin::createReason ("Projection for " + edgeStr),
                    SuccessBin::createReason ("SteeringMethod for " + edgeStr),
-                   SuccessBin::createReason ("PathValidation returned length 0 for " + edgeStr));
+                   SuccessBin::createReason ("PathValidation returned length 0 for " + edgeStr),
+                   SuccessBin::createReason ("Path could not be fully projected for " + edgeStr));
         failureReasons_.insert (EdgeReasonPair (edge, r));
         extendStatistics_.addFailure (r.get (t));
         return;
@@ -187,7 +195,7 @@ namespace hpp {
         const core::RoadmapPtr_t& roadmap) :
       core::PathPlanner (problem, roadmap),
       shooter_ (new core::BasicConfigurationShooter (problem.robot ())),
-      problem_ (problem),
+      problem_ (problem), pathProjector_ (new pathProjector::Dichotomy (problem_.distance (), 0.1)),
       qProj_ (problem.robot ()->configSize ())
     {}
 
diff --git a/src/path-projector.cc b/src/path-projector.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c10f9301c04f37f1f8b15118684f9e1423d4a660
--- /dev/null
+++ b/src/path-projector.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#include <hpp/util/pointer.hh>
+#include <hpp/core/path-vector.hh>
+#include <hpp/core/distance.hh>
+
+#include "hpp/manipulation/path-projector.hh"
+
+namespace hpp {
+  namespace manipulation {
+    PathProjector::PathProjector (const core::DistancePtr_t distance) :
+      distance_ (distance)
+    {}
+
+    PathProjector::~PathProjector ()
+    {}
+
+    value_type PathProjector::d (ConfigurationIn_t q1, ConfigurationIn_t q2) const
+    {
+      assert (distance_ != NULL);
+      return (*distance_) (q1, q2);
+    }
+
+    bool PathProjector::apply (const PathPtr_t path, PathPtr_t& proj) const
+    {
+      assert (path);
+      PathVectorPtr_t pv = HPP_DYNAMIC_PTR_CAST (PathVector, path);
+      if (!pv) {
+        StraightPathPtr_t sp = HPP_DYNAMIC_PTR_CAST (StraightPath, path);
+        if (!sp) throw std::invalid_argument ("Unknow inherited class of Path");
+        return impl_apply (sp, proj);
+      }
+      else {
+        PathVectorPtr_t res = PathVector::create (pv->outputSize());
+        PathPtr_t part;
+        for (size_t i = 0; i < pv->numberPaths (); i++) {
+          if (!apply (pv->pathAtRank (i), part)) {
+            if (part && part->length () > 0) res->appendPath (part);
+            return false;
+          }
+          res->appendPath (part);
+        }
+      }
+      return true;
+    }
+  } // namespace manipulation
+} // namespace hpp
diff --git a/src/path-projector/dichotomy.cc b/src/path-projector/dichotomy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5643d6c07c3d48b3578c907347cb5e43d13b3691
--- /dev/null
+++ b/src/path-projector/dichotomy.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2014, LAAS-CNRS
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of hpp-manipulation.
+// hpp-manipulation is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// hpp-manipulation is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// hpp-manipulation. If not, see <http://www.gnu.org/licenses/>.
+
+#include "hpp/manipulation/path-projector/dichotomy.hh"
+
+#include <hpp/core/path-vector.hh>
+
+#include <queue>
+#include <stack>
+
+namespace hpp {
+  namespace manipulation {
+    namespace pathProjector {
+      Dichotomy::Dichotomy (const core::DistancePtr_t d, value_type maxPathLength) :
+        PathProjector (d), maxPathLength_ (maxPathLength)
+      {}
+
+      bool Dichotomy::impl_apply (const StraightPathPtr_t path, PathPtr_t& projection) const
+      {
+        ConstraintSetPtr_t constraints = path->constraints ();
+        const StraightPath& sp = *path;
+        core::interval_t timeRange = sp.timeRange ();
+        const Configuration_t& q1 = sp(timeRange.first);
+        const Configuration_t& q2 = sp(timeRange.second);
+        constraints->offsetFromConfig(q1);
+        if (!constraints->isSatisfied (q1) || !constraints->isSatisfied (q2)) {
+          return false;
+        }
+        if (!constraints->configProjector ()) {
+          projection = path;
+          return true;
+        }
+
+        bool pathIsFullyProjected = true;
+        std::queue <core::StraightPathPtr_t> paths;
+        std::stack <core::StraightPathPtr_t> pathToSplit;
+        Configuration_t qi (q1.size());
+        core::StraightPathPtr_t sPath = core::StraightPath::create (sp.device (), q1, q2, d (q1, q2));
+        pathToSplit.push (sPath);
+        while (!pathToSplit.empty ()) {
+          sPath = pathToSplit.top ();
+          const StraightPath& sPathRef = *sPath;
+          pathToSplit.pop ();
+          double l = sPathRef.length ();
+          if (l < maxPathLength_) {
+            paths.push (sPath);
+            continue;
+          }
+          timeRange = sPathRef.timeRange ();
+          const Configuration_t& qb = sPathRef (timeRange.first);
+          sPathRef (qi, timeRange.first + l / 2);
+          const Configuration_t& qe = sPathRef (timeRange.second);
+          if (!constraints->apply (qi)) {
+            pathIsFullyProjected = false;
+            break;
+          }
+          StraightPathPtr_t firstPart =
+            core::StraightPath::create (sp.device (), qb, qi, d (qb, qi));
+          StraightPathPtr_t secondPart =
+            core::StraightPath::create (sp.device (), qi, qe, d (qi, qe));
+          if (secondPart->length () == 0 || firstPart->length () == 0) {
+            pathIsFullyProjected = false;
+            break;
+          }
+          pathToSplit.push (secondPart);
+          pathToSplit.push (firstPart);
+        }
+        switch (paths.size ()) {
+          case 0:
+            return false;
+            break;
+          case 1:
+            projection = paths.front ();
+            projection->constraints (constraints);
+            break;
+          default:
+            core::PathVectorPtr_t pv = core::PathVector::create (sp.device ()->configSize ());
+            while (!paths.empty ()) {
+              paths.front ()->constraints (constraints);
+              pv->appendPath (paths.front ());
+              paths.pop ();
+            }
+            projection = pv;
+            break;
+        }
+        return pathIsFullyProjected;
+      }
+    } // namespace pathProjector
+  } // namespace manipulation
+} // namespace hpp