diff --git a/doc/constraint-graph.png b/doc/constraint-graph.png
new file mode 100644
index 0000000000000000000000000000000000000000..c28a8da7e529fc2e9ccc490756027554127f1c53
Binary files /dev/null and b/doc/constraint-graph.png differ
diff --git a/include/hpp/manipulation/graph/edge.hh b/include/hpp/manipulation/graph/edge.hh
index 40403654678c9b80740950c2875bf8b37fe5a200..d69dcd0277768470588eb0de89eb74b6fa1c90c2 100644
--- a/include/hpp/manipulation/graph/edge.hh
+++ b/include/hpp/manipulation/graph/edge.hh
@@ -376,7 +376,78 @@ namespace hpp {
           WaypointEdgeWkPtr_t wkPtr_;
       }; // class WaypointEdge
 
-      /// Edge that find intersection of level set.
+      /// Edge that handles crossed foliations
+      ///
+      /// Let us consider the following simple constraint graph
+      /// corresponding to a robot grasping an object with one gripper.
+      ///
+      /// \image html constraint-graph.png "Simple constraint graph corresponding to a robot grasping an object."
+      ///
+      /// In order to disambiguate, we assume here that
+      /// \li transition <b>Grasp object</b> is in \b Placement state,
+      /// \li transition <b>Release object</b> is in \b Grasp state.
+      ///
+      /// If state \b Placement is defined by the object lying on a planar
+      /// polygonal surface, then
+      /// \li state \b Placement,
+      /// \li transition \b Transit, and
+      /// \li transition <b>Grasp object</b>
+      ///
+      /// are all constrained in a foliated manifold parameterized by the
+      /// position of the box on the surface.
+      ///
+      /// Likewise, if the object is cylindrical the grasp may have a degree
+      /// of freedom corresponding to the angle around z-axis of the gripper
+      /// with respect to the object. See classes
+      /// \link hpp::manipulation::Handle Handle\endlink and
+      /// \link hpp::pinocchio::Gripper Gripper\endlink for details.
+      /// In this latter case,
+      /// \li state \b Grasp,
+      /// \li transition \b Transfer, and
+      /// \li transition <b>Release object</b>
+      ///
+      /// are all constrained in a foliated manifold parameterized by the
+      /// angle around z-axis of the gripper with respect to the object.
+      ///
+      /// Let us denote
+      /// \li \c grasp the numerical constraint defining state \b Grasp,
+      /// \li \c placement the numerical constraint defining state \b Placement,
+      /// \li \c grasp_comp the parameterized constraint defining a leaf
+      ///     of \c Transfer (the angle between the gripper and the
+      ///     object),
+      /// \li \c placement_comp the parameterized constraint defining a leaf
+      ///     of \b Placement (the position of the object on the contact
+      ///     surface).
+      ///
+      /// As explained in <a
+      /// href="https://hal.archives-ouvertes.fr/hal-01358767">this
+      /// paper </a>, we are in the crossed foliation case and manipulation RRT
+      /// will never be able to connect trees expanding in different leaves of
+      /// the foliation.
+      ///
+      /// This class solves this issue in the following way by creating an
+      /// instance of LevelSetEdge between \b Placement and \b Grasp.
+      ///
+      /// When extending a configuration \f$\mathbf{q}_{start}\f$ in state
+      /// \b Placement, this transition will produce a target configuration
+      /// (method \link LevelSetEdge::generateTargetConfig generateTargetConfig)
+      /// \endlink as follows.
+      ///
+      /// \li pick a random configuration \f$\mathbf{q}_rand\f$, in the edge
+      /// histogram (see method \link LevelSetEdge::histogram histogram\endlink)
+      /// \li compute right hand side of \c grasp_comp with
+      ///     \f$\mathbf{q}_{rand}\f$,
+      /// \li compute right hand side of \c placement_comp with
+      ///     \f$\mathbf{q}_{start}\f$,
+      /// \li solve (\c grasp, \c placement, \c placement_comp, \c grasp_comp)
+      ///     using input configuration \f$\mathbf{q}\f$. Note that the
+      /// parent method Edge::generateTargetConfig does the same without
+      /// adding \c grasp_comp.
+      ///
+      /// The constraints parameterizing the target state foliation
+      /// (\c graps_comp in our example) are passed to class instances
+      /// using method \link LevelSetEdge::insertParamConstraint
+      /// insertParamConstraint\endlink.
       class HPP_MANIPULATION_DLLAPI LevelSetEdge : public Edge
       {
         public:
@@ -443,18 +514,39 @@ namespace hpp {
           /// Build path and target state constraints
           virtual ConstraintSetPtr_t buildTargetConstraint();
 
+          /// Build the histogram
+          /// \sa LevelSetEdge::histogram.
           void buildHistogram ();
 
+          /// Return pointer on histogram of the edge
+          ///
+          /// The edge histogram is a container of configurations defined by
+          /// a set of constraints called the <b>condition constraints</b>
+          /// that a configuration should satisfy to be inserted in the
+          /// histogram.
+          ///
+          /// The histogram is passed to the Roadmap via the graph (method
+          /// Graph::insertHistogram). The roadmap then populates the histogram
+          /// with all new configurations satisfying the condition constraints.
+          ///
+          /// The condition constraints should therefore be the constraints of
+          /// the target state of the level set edge.
+          ///
+          /// \sa LevelSetEdge::insertConditionConstraint
           LeafHistogramPtr_t histogram () const;
 
           /// \name Foliation definition
           /// \{
 
-          /// Insert a numerical constraint that parametrizes the foliation
+          /// Insert a constraints parameterizing the target state foliation
+          /// \param nm the numerical constraint,
+          /// \param passiveDofs the passive degrees of freedom of the
+          ///        constraint.
           void insertParamConstraint (const ImplicitPtr_t& nm,
               const segments_t& passiveDofs = segments_t ());
 
-          /// Insert a numerical constraint that defines the foliation
+          /// Insert a condition constraint
+          /// \sa LevelSetEdge::histogram
           void insertConditionConstraint (const ImplicitPtr_t& nm,
               const segments_t& passiveDofs = segments_t ());
 
diff --git a/src/graph/edge.cc b/src/graph/edge.cc
index 6545f9941e891df1a3e3da3ae069f1d5e196da9b..d59e75beec7b5ce73284aefe3855f09e099cc858 100644
--- a/src/graph/edge.cc
+++ b/src/graph/edge.cc
@@ -203,7 +203,7 @@ namespace hpp {
         return targetConstraints_;
       }
 
-      // Merge constraints of several graph components into a config projectors
+      // Merge constraints of several graph components into a config projector
       // Replace constraints and complement by combination of both when
       // necessary.
       static void mergeConstraintsIntoConfigProjector
@@ -289,6 +289,11 @@ namespace hpp {
 	if (state () != stateTo ()) {
           components.push_back (state ());
 	}
+        // Copy constraints from
+        // - graph,
+        // - this edge,
+        // - the destination state,
+        // - the state in which the transition lies if different
         mergeConstraintsIntoConfigProjector (proj, components, parentGraph ());
 
         constraint->addConstraint (proj);
@@ -654,7 +659,10 @@ namespace hpp {
         const ConfigProjectorPtr_t cp = cs->configProjector ();
         assert (cp);
 
+        // Set right hand side of edge constraints with qStart
 	cp->rightHandSideFromConfig (qStart);
+        // Set right hand side of constraints parameterizing the target state
+        // foliation with qLeaf.
 	for (NumericalConstraints_t::const_iterator it =
 	       paramNumericalConstraints_.begin ();
 	     it != paramNumericalConstraints_.end (); ++it) {
@@ -778,6 +786,13 @@ namespace hpp {
 
         ConfigProjectorPtr_t proj = ConfigProjector::create(g->robot(), "proj_" + n, g->errorThreshold(), g->maxIterations());
 
+        // Copy constraints from
+        // - graph,
+        // - param numerical constraints
+        // - this edge,
+        // - the destination state,
+        // - the state in which the transition lies if different
+
         g->insertNumericalConstraints (proj);
         IntervalsContainer_t::const_iterator itpdof = paramPassiveDofs_.begin ();
         for (NumericalConstraints_t::const_iterator it = paramNumericalConstraints_.begin ();