From a03dc7d3ee15c64e10416a0c7d2ec0e54b8b5e01 Mon Sep 17 00:00:00 2001
From: Joseph Mirabel <jmirabel@laas.fr>
Date: Wed, 26 Jul 2017 18:51:50 +0200
Subject: [PATCH] Fix SplineGradientBased

---
 .../spline-gradient-based.cc                  | 91 ++++++++++++++++---
 1 file changed, 76 insertions(+), 15 deletions(-)

diff --git a/src/path-optimization/spline-gradient-based.cc b/src/path-optimization/spline-gradient-based.cc
index e2ae9236..6582424f 100644
--- a/src/path-optimization/spline-gradient-based.cc
+++ b/src/path-optimization/spline-gradient-based.cc
@@ -77,7 +77,7 @@ namespace hpp {
         bool zeroDerivative = this->problem().getParameter ("SplineGradientBased/zeroDerivativesAtStateIntersection", false);
 
         const std::size_t last = splines.size() - 1;
-        bool prevReversed = false;
+        graph::StatePtr_t stateOfStart;
         for (std::size_t i = 0; i < last; ++i) {
           core::PathPtr_t path = init->pathAtRank(i);
           ConstraintSetPtr_t set = HPP_STATIC_PTR_CAST (ConstraintSet, splines[i]->constraints ());
@@ -88,25 +88,81 @@ namespace hpp {
 
           this->addProblemConstraintOnPath (path, i, splines[i], lc, ss[i]);
 
-          bool reversed = transition->direction (path);
-
           // The path should always go through the start and end states of the
           // transition.
           // FIXME problem of waypoint edges...
           graph::WaypointEdgePtr_t we = HPP_DYNAMIC_PTR_CAST(graph::WaypointEdge, transition);
-          if (we) reversed = prevReversed;
           graph::StatePtr_t from = (we ? we->waypoint<graph::Edge>(we->nbWaypoints() - 1)->to() : transition->from());
-          if (reversed && transition->state() != from) {
-            // Do something different
-            constrainEndIntoState (path, i, splines[i], from, lc);
-          } else if (!reversed && transition->state() != transition->to()) {
-            // Do something different
-            constrainEndIntoState (path, i, splines[i], transition->to(), lc);
+          graph::StatePtr_t to = transition->to();
+          graph::StatePtr_t from2 = from, to2 = to;
+
+          Configuration_t q0 = path->initial (),
+                          q1 = path->end ();
+          const bool src_contains_q0 = from->contains (q0);
+          const bool dst_contains_q0 = to  ->contains (q0);
+          const bool src_contains_q1 = from->contains (q1);
+          const bool dst_contains_q1 = to  ->contains (q1);
+
+          bool use_direct  = src_contains_q0 && dst_contains_q1;
+          bool use_reverse = src_contains_q1 && dst_contains_q0;
+          if (use_direct && use_reverse) {
+            if (i == 0 || stateOfStart == from)
+              use_reverse = false;
+            else if (stateOfStart == to)
+              use_direct = false;
+            else if (stateOfStart) {
+              if (stateOfStart->contains(q0))
+                use_reverse = false;
+              else
+                use_direct = false; // assumes stateOfStart->contains(q0)
+            } else
+              use_reverse = false; // default if we don't know what to do...
           }
-          if (zeroDerivative && from != transition->to()) {
-            constraintDerivativesAtEndOfSpline (i, splines[i], lc);
+          if (use_direct) {
+            // Nominal case
+            if (transition->state() != to) {
+              constrainEndIntoState (path, i, splines[i], transition->to(), lc);
+            }
+            stateOfStart = to;
+          } else if (use_reverse) {
+            // Reversed nominal case
+            if (transition->state() != from) {
+              constrainEndIntoState (path, i, splines[i], from, lc);
+            }
+            stateOfStart = from;
+          } else {
+            if (src_contains_q0) { // q1 must stay in state
+              to2 = transition->state();
+              stateOfStart = to;
+            } else if (dst_contains_q0) { // q1 must stay in state
+              from2 = transition->state();
+              stateOfStart = from;
+            } else if (src_contains_q1) { // q1 must stay in src
+              to2 = transition->state();
+              stateOfStart = from;
+              if (transition->state() != from) {
+                constrainEndIntoState (path, i, splines[i], from, lc);
+              }
+            } else if (dst_contains_q1) { // q1 must stay in dst
+              from2 = transition->state();
+              stateOfStart = to;
+              if (transition->state() != to) {
+                constrainEndIntoState (path, i, splines[i], to, lc);
+              }
+            } else {
+              // q0 and q1 are in state. We add no constraint.
+              hppDout (warning, "Add no constraint for this path.");
+              from2 = transition->state();
+              to2 = transition->state();
+              stateOfStart.reset();
+            }
+          if (zeroDerivative) {
+            if (   !(use_reverse && src_contains_q0 && src_contains_q1)
+                && !(use_direct  && dst_contains_q0 && dst_contains_q1)
+                && from2 != to2                         ) {
+              constraintDerivativesAtEndOfSpline (i, splines[i], lc);
+            }
           }
-          prevReversed = reversed;
         }
         this->addProblemConstraintOnPath (init->pathAtRank(last), last, splines[last], lc, ss[last]);
       }
@@ -169,8 +225,13 @@ namespace hpp {
           lc.J.block  (row, col + k * rDof, nOutVar, rDof) = B1(k) * I;
         lc.b.segment(row, nOutVar).setZero();
 
-        assert ((lc.J.block(row, col, nOutVar, rDof * Spline::NbCoeffs) * spline->rowParameters())
-            .isApprox(lc.b.segment(row, nOutVar)));
+        if (!(lc.J.block(row, col, nOutVar, rDof * Spline::NbCoeffs) * spline->rowParameters())
+            .isApprox(lc.b.segment(row, nOutVar)))
+        {
+          hppDout (error, "The velocity should already be zero:\n"
+              << (lc.J.block(row, col, nOutVar, rDof * Spline::NbCoeffs) * spline->rowParameters()).transpose()
+              );
+        }
       }
 
       // ----------- Optimize ----------------------------------------------- //
-- 
GitLab