Skip to content
Snippets Groups Projects
graph-path-validation.cc 4.28 KiB
Newer Older
// 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/graph-path-validation.hh"

namespace hpp {
  namespace manipulation {
    GraphPathValidationPtr_t GraphPathValidation::create (
        const PathValidationPtr_t& pathValidation, const GraphPtr_t& graph)
    {
      GraphPathValidation* p = new GraphPathValidation (pathValidation, graph);
      return GraphPathValidationPtr_t (p);
    }

    GraphPathValidation::GraphPathValidation (
        const PathValidationPtr_t& pathValidation, const GraphPtr_t& graph) :
      pathValidation_ (pathValidation), constraintGraph_ (graph)
    {}

    bool GraphPathValidation::validate (
          const PathPtr_t& path, bool reverse, PathPtr_t& validPart)
    {
      assert (path);
      PathPtr_t pathGraphValid;
      bool graphValid = impl_validate (path, reverse, pathGraphValid);
      bool collisionValid = pathValidation_->validate (pathGraphValid, reverse, validPart);
      return graphValid && collisionValid;
    }

    bool GraphPathValidation::impl_validate (
        const PathVectorPtr_t& path, bool reverse, PathPtr_t& validPart)
    {
      size_t start = 0,
             end = path->numberPaths ();
      int inc = 1;
      value_type timeOffset = path->timeRange().first;
      if (reverse) {
        std::swap (start, end);
        start--;end--;
        inc = -1;
        timeOffset = path->timeRange ().second;
      }
      PathPtr_t validSubPart;
      for (size_t index = start; index != end; index += inc) {
        // We should stop at the first non valid subpath.
        if (!impl_validate (path->pathAtRank (index), reverse, validSubPart)) {
          if (reverse)
            validPart = path->extract (
                std::make_pair (timeOffset - validSubPart->timeRange().second,
                                path->timeRange().second));
          else
            validPart = path->extract (
                std::make_pair (path->timeRange().first,
                                timeOffset + validSubPart->timeRange().second));
          return false;
        }
        timeOffset += inc * path->pathAtRank (index)->length();
      }
      // Here, every subpath is valid.
      validPart = path;
      return true;
    }

    bool GraphPathValidation::impl_validate (
        const PathPtr_t& path, bool reverse, PathPtr_t& validPart)
    {
      PathVectorPtr_t pathVector = HPP_DYNAMIC_PTR_CAST(PathVector, path);
      if (pathVector)
        return impl_validate (pathVector, reverse, validPart);

      value_type tmin = path->timeRange ().first;
      value_type tmax = path->timeRange ().second;
      if (reverse)
        std::swap (tmin, tmax);
      const Path& configAt (*path);
      graph::Nodes_t origNodes = constraintGraph_->getNode (configAt (tmin));
      graph::Nodes_t destNodes = constraintGraph_->getNode (configAt (tmax));
      std::vector <graph::Edges_t> possibleEdges (constraintGraph_->getEdge (origNodes, destNodes));
      // We check for all of them if both nodes are on the same leaf.
      ConstraintSetPtr_t constraints;
      while (!possibleEdges.empty ()) {
Joseph Mirabel's avatar
Joseph Mirabel committed
        constraints = constraintGraph_->pathConstraint (possibleEdges.back());
        constraints->offsetFromConfig(configAt (tmin));
        assert (constraints->isSatisfied (configAt (tmin)));
        if (constraints == path->constraints ()
            && constraints->isSatisfied (configAt (tmax))) {
          validPart = path;
          return true;
        }
        possibleEdges.pop_back();
      }
      return false;
    }
  } // namespace manipulation
} // namespace hpp