diff --git a/CMakeLists.txt b/CMakeLists.txt index fd5c5080ef87d472d14eb7af1a955b29dbb5e08b..134d7a5767981f34fabc72833a450dea4fae5211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ SET (${PROJECT_NAME}_HEADERS include/hpp/manipulation/manipulation-planner.hh include/hpp/manipulation/path-projector.hh include/hpp/manipulation/path-projector/dichotomy.hh + include/hpp/manipulation/path-projector/progressive.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/path-projector/progressive.hh b/include/hpp/manipulation/path-projector/progressive.hh new file mode 100644 index 0000000000000000000000000000000000000000..2598443df7a18fcbea5708ccc38e89b558d993a5 --- /dev/null +++ b/include/hpp/manipulation/path-projector/progressive.hh @@ -0,0 +1,40 @@ +// 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_PROGRESSIVE_HH +# define HPP_MANIPULATION_PATHPROJECTOR_PROGRESSIVE_HH + +# include "hpp/manipulation/path-projector.hh" + +namespace hpp { + namespace manipulation { + namespace pathProjector { + class HPP_MANIPULATION_DLLAPI Progressive : public PathProjector + { + public: + Progressive (const core::DistancePtr_t distance, value_type step); + + protected: + bool impl_apply (const StraightPathPtr_t path, PathPtr_t& projection) const; + + private: + value_type step_; + }; + } // namespace pathProjector + } // namespace manipulation +} // namespace hpp + +#endif // HPP_MANIPULATION_PATHPROJECTOR_PROGRESSIVE_HH diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23ca6b1c02b78f87b84f6e337da14145c4a6d667..8e101e59b28190f03bc424c9f465487c8a765bc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ ADD_LIBRARY(${LIBRARY_NAME} SHARED path-projector.cc path-projector/dichotomy.cc + path-projector/progressive.cc graph/node.cc graph/edge.cc diff --git a/src/path-projector/progressive.cc b/src/path-projector/progressive.cc new file mode 100644 index 0000000000000000000000000000000000000000..8d34fb9a04aa63b16fec6ac75cd6af52f2252be7 --- /dev/null +++ b/src/path-projector/progressive.cc @@ -0,0 +1,119 @@ +// 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/progressive.hh" + +#include <hpp/core/path-vector.hh> + +#include <limits> +#include <queue> +#include <stack> + +namespace hpp { + namespace manipulation { + namespace pathProjector { + Progressive::Progressive (const core::DistancePtr_t d, value_type step) : + PathProjector (d), step_ (step) + {} + + bool Progressive::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 = false; + std::queue <core::StraightPathPtr_t> paths; + StraightPathPtr_t toSplit = + core::StraightPath::create (sp.device (), q1, q2, d (q1, q2)); + Configuration_t qi (q1.size()); + value_type curStep, curLength; + while (true) { + const StraightPath& toSplitRef = *toSplit; + if (toSplitRef.length () < step_) { + paths.push (toSplit); + pathIsFullyProjected = true; + break; + } + timeRange = toSplitRef.timeRange (); + const Configuration_t& qb = toSplitRef (timeRange.first); + curStep = step_; + bool stop = false; + /// Find the good length. + /// Here, it would be good to have an upper bound of the Hessian + /// of the constraint. + do { + toSplitRef (qi, curStep); + if (!constraints->apply (qi)) { + stop = true; + break; + } + curLength = d (qb, qi); + if (curStep < 0.02) { + stop = true; + break; + } + curStep /= 2; + } while (curLength > step_); + if (stop) break; + StraightPathPtr_t part = + core::StraightPath::create (sp.device (), qb, qi, curLength); + paths.push (part); + toSplit = + core::StraightPath::create (sp.device (), qi, q2, d (qi, q2)); + } + switch (paths.size ()) { + case 0: + timeRange = sp.timeRange(); + projection = sp.extract (std::make_pair (timeRange.first, timeRange.first)); + return false; + break; + case 1: + projection = paths.front (); + projection->constraints (constraints); + break; + default: + core::PathVectorPtr_t pv = core::PathVector::create (sp.device ()->configSize ()); + qi = q1; + while (!paths.empty ()) { + assert ((qi - (*paths.front ())(paths.front ()->timeRange().first)).isZero ()); + assert (constraints->isSatisfied (qi)); + qi = (*paths.front ())(paths.front ()->timeRange().second); + assert (constraints->isSatisfied (qi)); + paths.front ()->constraints (constraints); + pv->appendPath (paths.front ()); + paths.pop (); + } + projection = pv; + break; + } + assert (((*projection)(projection->timeRange ().first) - (*path)(path->timeRange ().first)).isZero()); + assert (!pathIsFullyProjected || ((*projection)(projection->timeRange ().second) - (*path)(path->timeRange ().second)).isZero()); + return pathIsFullyProjected; + } + } // namespace pathProjector + } // namespace manipulation +} // namespace hpp