diff --git a/CMakeLists.txt b/CMakeLists.txt index b23425c17395281887538fc309aebe885367bd71..e4a67b1bb2ab83919808446a47eab3863bf7fe50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,8 @@ SET (${PROJECT_NAME}_HEADERS include/hpp/manipulation/path-optimization/random-shortcut.hh include/hpp/manipulation/path-optimization/spline-gradient-based.hh + include/hpp/manipulation/path-planner/end-effector-trajectory.hh + include/hpp/manipulation/problem-target/state.hh include/hpp/manipulation/steering-method/cross-state-optimization.hh diff --git a/include/hpp/manipulation/path-planner/end-effector-trajectory.hh b/include/hpp/manipulation/path-planner/end-effector-trajectory.hh new file mode 100644 index 0000000000000000000000000000000000000000..e39dd0f5cbf1a851a24d0891a12f28877c8d9646 --- /dev/null +++ b/include/hpp/manipulation/path-planner/end-effector-trajectory.hh @@ -0,0 +1,137 @@ +// Copyright (c) 2019 CNRS +// Authors: Joseph Mirabel +// +// 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_PATH_PLANNER_END_EFFECTOR_TRAJECTORY_HH +# define HPP_MANIPULATION_PATH_PLANNER_END_EFFECTOR_TRAJECTORY_HH + +# include <hpp/manipulation/config.hh> +# include <hpp/manipulation/fwd.hh> + +# include <pinocchio/spatial/se3.hpp> + +# include <hpp/pinocchio/frame.hh> +# include <hpp/core/path-planner.hh> + +namespace hpp { + namespace manipulation { + namespace pathPlanner { + class HPP_MANIPULATION_DLLAPI IkSolverInitialization + { + public: + typedef std::vector<Configuration_t> Configurations_t; + + Configurations_t solve (vectorIn_t target) + { + return impl_solve (target); + } + + protected: + virtual Configurations_t impl_solve (vectorIn_t target) = 0; + }; + typedef boost::shared_ptr<IkSolverInitialization> IkSolverInitializationPtr_t; + + HPP_PREDEF_CLASS (EndEffectorTrajectory); + typedef boost::shared_ptr<EndEffectorTrajectory> EndEffectorTrajectoryPtr_t; + + class HPP_MANIPULATION_DLLAPI EndEffectorTrajectory : public core::PathPlanner + { + public: + /// Return shared pointer to new instance + /// \param problem the path planning problem + static EndEffectorTrajectoryPtr_t create (const core::Problem& problem); + /// Return shared pointer to new instance + /// \param problem the path planning problem + /// \param roadmap previously built roadmap + static EndEffectorTrajectoryPtr_t createWithRoadmap + (const core::Problem& problem, const core::RoadmapPtr_t& roadmap); + + /// Initialize the problem resolution + /// \li call parent implementation + /// \li get number nodes in problem parameter map + virtual void startSolve (); + + /// One step of the algorithm + virtual void oneStep (); + + /// Get the number of random configurations shoot (after using init + /// config) in order to generate the initial config of the final path. + int nRandomConfig () const + { return nRandomConfig_; } + + void nRandomConfig (int n) + { + assert (n >= 0); + nRandomConfig_ = n; + } + + /// Number of steps to generate goal config (successive projections). + int nDiscreteSteps () const + { return nDiscreteSteps_; } + + void nDiscreteSteps (int n) + { + assert (n > 0); + nDiscreteSteps_ = n; + } + + /// If enabled, only add one solution to the roadmap. + /// Otherwise add all solution. + void checkFeasibilityOnly (bool enable); + + bool checkFeasibilityOnly () const + { + return feasibilityOnly_; + } + + void ikSolverInitialization (IkSolverInitializationPtr_t solver) + { + ikSolverInit_ = solver; + } + + void tryConnectInitAndGoals (); + + protected: + /// Protected constructor + /// \param problem the path planning problem + EndEffectorTrajectory (const core::Problem& problem); + /// Protected constructor + /// \param problem the path planning problem + /// \param roadmap previously built roadmap + EndEffectorTrajectory (const core::Problem& problem, const core::RoadmapPtr_t& roadmap); + /// Store weak pointer to itself + void init (const EndEffectorTrajectoryWkPtr_t& weak); + + private: + std::vector<core::Configuration_t> configurations(const core::Configuration_t& q_init); + + /// Weak pointer to itself + EndEffectorTrajectoryWkPtr_t weak_; + /// Number of random config. + int nRandomConfig_; + /// Number of steps to generate goal config. + int nDiscreteSteps_; + /// Ik solver initialization. An external Ik solver can be plugged here. + IkSolverInitializationPtr_t ikSolverInit_; + /// Feasibility + bool feasibilityOnly_; + }; // class EndEffectorTrajectory + } // namespace pathPlanner + } // namespace manipulation +} // namespace hpp + +#endif // HPP_MANIPULATION_PATH_PLANNER_END_EFFECTOR_TRAJECTORY_HH diff --git a/include/hpp/manipulation/steering-method/end-effector-trajectory.hh b/include/hpp/manipulation/steering-method/end-effector-trajectory.hh index 7c8feee3c521b363160f2eacf33502318201ae47..dd04146f80940f589327abcbdc0ba30117a28d59 100644 --- a/include/hpp/manipulation/steering-method/end-effector-trajectory.hh +++ b/include/hpp/manipulation/steering-method/end-effector-trajectory.hh @@ -46,6 +46,13 @@ namespace hpp { return ptr; } + /// Build a trajectory in SE(3). + /// \param points a Nx7 matrix whose rows corresponds to a pose. + /// \param weights a 6D vector, weights to be applied when computing + /// the distance between two SE3 points. + static PathPtr_t makePiecewiseLinearTrajectory (matrixIn_t points, + vectorIn_t weights); + /// Set the constraint whose right hand side will vary. void trajectoryConstraint (const constraints::ImplicitPtr_t& ic); @@ -81,6 +88,12 @@ namespace hpp { return ptr; } + /// Computes an core::InterpolatedPath from the provided interpolation + /// points. + /// \param times the time of each configuration + /// \param configs each column correspond to a configuration + PathPtr_t projectedPath (vectorIn_t times, matrixIn_t configs) const; + protected: EndEffectorTrajectory (const core::Problem& problem) : core::SteeringMethod (problem) @@ -96,6 +109,8 @@ namespace hpp { PathPtr_t impl_compute (ConfigurationIn_t q1, ConfigurationIn_t q2) const; private: + core::ConstraintSetPtr_t getUpdatedConstraints () const; + DifferentiableFunctionPtr_t eeTraj_; interval_t timeRange_; constraints::ImplicitPtr_t constraint_; diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 7a0c682fe4842063f7cdaa4f4e70db18c4163c12..77bbad0a5bba1c79631719a4122f665f8621cc51 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -20,3 +20,8 @@ HPP_ADD_PLUGIN(manipulation-spline-gradient-based SOURCES spline-gradient-based.cc LINK_DEPENDENCIES ${PROJECT_NAME} ${PROJECT_NAME}-gpl hpp-core-gpl PKG_CONFIG_DEPENDENCIES hpp-core) + +HPP_ADD_PLUGIN(end-effector-trajectory + SOURCES end-effector-trajectory.cc + LINK_DEPENDENCIES ${PROJECT_NAME} + PKG_CONFIG_DEPENDENCIES hpp-core) diff --git a/plugins/end-effector-trajectory.cc b/plugins/end-effector-trajectory.cc new file mode 100644 index 0000000000000000000000000000000000000000..f2baee78989510cc0245526e5e03a4d7a3c794a4 --- /dev/null +++ b/plugins/end-effector-trajectory.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2019, Joseph Mirabel +// 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/core/plugin.hh> +#include <hpp/core/problem-solver.hh> + +#include <hpp/manipulation/steering-method/end-effector-trajectory.hh> +#include <hpp/manipulation/path-planner/end-effector-trajectory.hh> + +namespace hpp { + namespace manipulation { + class EndEffectorTrajectoryPlugin : public core::ProblemSolverPlugin + { + public: + EndEffectorTrajectoryPlugin () + : ProblemSolverPlugin ("EndEffectorTrajectoryPlugin", "0.0") + {} + + protected: + virtual bool impl_initialize (core::ProblemSolverPtr_t ps) + { + ps->pathPlanners.add ("EndEffectorTrajectory", + pathPlanner::EndEffectorTrajectory::createWithRoadmap); + ps->steeringMethods.add ("EndEffectorTrajectory", + steeringMethod::EndEffectorTrajectory::create); + return true; + } + }; + } // namespace manipulation +} // namespace hpp + +HPP_CORE_DEFINE_PLUGIN(hpp::manipulation::EndEffectorTrajectoryPlugin) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ae2c0ecb6b5ff76d5a8902ebd461fa6a955c59d..19c8702c7a5ffe6f9b887ceb0f7d50b8ce02a0ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,6 +49,8 @@ SET(SOURCES path-optimization/random-shortcut.cc path-optimization/enforce-transition-semantic.cc + path-planner/end-effector-trajectory.cc + problem-target/state.cc steering-method/end-effector-trajectory.cc diff --git a/src/path-planner/end-effector-trajectory.cc b/src/path-planner/end-effector-trajectory.cc new file mode 100644 index 0000000000000000000000000000000000000000..13df4ba0410713bb94b28a84ee4f2bbcedb246c0 --- /dev/null +++ b/src/path-planner/end-effector-trajectory.cc @@ -0,0 +1,257 @@ +// Copyright (c) 2019 CNRS +// Authors: Joseph Mirabel +// +// 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-planner/end-effector-trajectory.hh> + +# include <pinocchio/multibody/data.hpp> + +# include <hpp/util/exception-factory.hh> +# include <hpp/pinocchio/util.hh> +# include <hpp/pinocchio/device-sync.hh> +# include <hpp/pinocchio/liegroup-element.hh> + +# include <hpp/constraints/differentiable-function.hh> +# include <hpp/constraints/implicit.hh> + +# include <hpp/core/config-projector.hh> +# include <hpp/core/config-validations.hh> +# include <hpp/core/configuration-shooter.hh> +# include <hpp/core/path-validation.hh> +# include <hpp/core/problem.hh> +# include <hpp/core/roadmap.hh> +# include <hpp/manipulation/steering-method/end-effector-trajectory.hh> + +namespace hpp { + namespace manipulation { + namespace pathPlanner { + typedef manipulation::steeringMethod::EndEffectorTrajectory SM_t; + typedef manipulation::steeringMethod::EndEffectorTrajectoryPtr_t SMPtr_t; + + EndEffectorTrajectoryPtr_t EndEffectorTrajectory::create (const core::Problem& problem) + { + EndEffectorTrajectoryPtr_t ptr (new EndEffectorTrajectory(problem)); + ptr->init(ptr); + return ptr; + } + + EndEffectorTrajectoryPtr_t EndEffectorTrajectory::createWithRoadmap ( + const core::Problem& problem, const core::RoadmapPtr_t& roadmap) + { + EndEffectorTrajectoryPtr_t ptr (new EndEffectorTrajectory(problem, roadmap)); + ptr->init(ptr); + return ptr; + } + + void EndEffectorTrajectory::tryConnectInitAndGoals () + {} + + void EndEffectorTrajectory::startSolve () + { + //core::PathPlanner::startSolve(); + //problem().checkProblem (); + if (!problem().robot ()) { + std::string msg ("No device in problem."); + hppDout (error, msg); + throw std::runtime_error (msg); + } + + if (!problem().initConfig ()) { + std::string msg ("No init config in problem."); + hppDout (error, msg); + throw std::runtime_error (msg); + } + + // Tag init and goal configurations in the roadmap + roadmap()->resetGoalNodes (); + + SMPtr_t sm (HPP_DYNAMIC_PTR_CAST (SM_t, problem().steeringMethod())); + if (!sm) + throw std::invalid_argument ("Steering method must be of type hpp::manipulation::steeringMethod::EndEffectorTrajectory"); + + if (!sm->constraints() || !sm->constraints()->configProjector()) + throw std::invalid_argument ("Steering method constraint has no ConfigProjector."); + core::ConfigProjectorPtr_t constraints (sm->constraints()->configProjector()); + + const constraints::ImplicitPtr_t& trajConstraint = sm->trajectoryConstraint (); + if (!trajConstraint) + throw std::invalid_argument ("EndEffectorTrajectory has no trajectory constraint."); + if (!sm->trajectory()) + throw std::invalid_argument ("EndEffectorTrajectory has no trajectory."); + + const core::NumericalConstraints_t& ncs = constraints->numericalConstraints(); + bool ok = false; + for (std::size_t i = 0; i < ncs.size(); ++i) { + if (ncs[i] == trajConstraint) { + ok = true; + break; // Same pointer + } + // Here, we do not check the right hand side on purpose. + // if (*ncs[i] == *trajConstraint) { + if (ncs[i]->functionPtr() == trajConstraint->functionPtr() + && ncs[i]->comparisonType() == trajConstraint->comparisonType()) { + ok = true; + // TODO We should only modify the path constraint. + // However, only the pointers to implicit constraints are copied + // while we would like the implicit constraints to be copied as well. + ncs[i]->rightHandSideFunction (sm->trajectory()); + break; // logically identical + } + } + if (!ok) { + HPP_THROW (std::logic_error, "EndEffectorTrajectory could not find " + "constraint " << trajConstraint->function()); + } + } + + void EndEffectorTrajectory::oneStep () + { + SMPtr_t sm (HPP_DYNAMIC_PTR_CAST (SM_t, problem().steeringMethod())); + if (!sm) + throw std::invalid_argument ("Steering method must be of type hpp::manipulation::steeringMethod::EndEffectorTrajectory"); + if (!sm->trajectoryConstraint ()) + throw std::invalid_argument ("EndEffectorTrajectory has no trajectory constraint."); + if (!sm->trajectory()) + throw std::invalid_argument ("EndEffectorTrajectory has no trajectory."); + + if (!sm->constraints() || !sm->constraints()->configProjector()) + throw std::invalid_argument ("Steering method constraint has no ConfigProjector."); + core::ConfigProjectorPtr_t constraints (sm->constraints()->configProjector()); + + core::ConfigValidationPtr_t cfgValidation (problem().configValidations()); + core:: PathValidationPtr_t pathValidation (problem().pathValidation()); + core:: ValidationReportPtr_t cfgReport; + core::PathValidationReportPtr_t pathReport; + + core::interval_t timeRange (sm->timeRange()); + + std::vector<core::Configuration_t> qs (configurations(*problem().initConfig())); + if (qs.empty()) { + hppDout (info, "Failed to generate initial configs."); + return; + } + + // Generate a valid initial configuration. + bool success = false; + bool resetRightHandSide = true; + std::size_t i; + + vector_t times (nDiscreteSteps_+1); + matrix_t steps (problem().robot()->configSize(), nDiscreteSteps_+1); + + times[0] = timeRange.first; + for (int j = 1; j < nDiscreteSteps_; ++j) + times[j] = timeRange.first + j * (timeRange.second - timeRange.first) / nDiscreteSteps_; + times[nDiscreteSteps_] = timeRange.second; + + for (i = 0; i < qs.size(); ++i) + { + if (resetRightHandSide) { + constraints->rightHandSideAt (times[0]); + resetRightHandSide = false; + } + Configuration_t& q (qs[i]); + if (!constraints->apply (q)) continue; + if (!cfgValidation->validate (q, cfgReport)) continue; + resetRightHandSide = true; + + steps.col(0) = q; + success = true; + for (int j = 1; j <= nDiscreteSteps_; ++j) { + constraints->rightHandSideAt (times[j]); + hppDout (info, "RHS: " << setpyformat << constraints->rightHandSide().transpose()); + steps.col(j) = steps.col(j-1); + if (!constraints->apply (steps.col(j))) { + hppDout (info, "Failed to generate destination config.\n" << setpyformat + << *constraints + << "\nq=" << one_line (q)); + success = false; + break; + } + } + if (!success) continue; + success = false; + + if (!cfgValidation->validate (steps.col(nDiscreteSteps_), cfgReport)) { + hppDout (info, "Destination config is in collision."); + continue; + } + + core::PathPtr_t path = sm->projectedPath(times, steps); + if (!path) { + hppDout (info, "Steering method failed.\n" << setpyformat + << "times: " << one_line(times) << '\n' + << "configs:\n" << condensed(steps.transpose()) << '\n' + ); + continue; + } + + core::PathPtr_t validPart; + if (!pathValidation->validate (path, false, validPart, pathReport)) { + hppDout (info, "Path is in collision."); + continue; + } + + roadmap()->initNode (boost::make_shared<Configuration_t>(steps.col(0))); + core::NodePtr_t init = roadmap()-> initNode (); + core::NodePtr_t goal = roadmap()->addGoalNode ( + boost::make_shared<Configuration_t>(steps.col(nDiscreteSteps_))); + roadmap()->addEdge (init, goal, path); + success = true; + if (feasibilityOnly_) break; + } + } + + std::vector<core::Configuration_t> EndEffectorTrajectory::configurations(const core::Configuration_t& q_init) + { + if (!ikSolverInit_) { + std::vector<core::Configuration_t> configs(nRandomConfig_ + 1); + configs[0] = q_init; + for (int i = 1; i < nRandomConfig_ + 1; ++i) + problem().configurationShooter()->shoot(configs[i]); + return configs; + } + + // TODO Compute the target and call ikSolverInit_ + // See https://gepgitlab.laas.fr/airbus-xtct/hpp_airbus_xtct for an + // example using IKFast. + throw std::runtime_error ("Using an IkSolverInitialization is not implemented yet"); + } + + EndEffectorTrajectory::EndEffectorTrajectory (const core::Problem& problem) + : core::PathPlanner (problem) + {} + + EndEffectorTrajectory::EndEffectorTrajectory (const core::Problem& problem, const core::RoadmapPtr_t& roadmap) + : core::PathPlanner (problem, roadmap) + {} + + void EndEffectorTrajectory::checkFeasibilityOnly (bool enable) + { + feasibilityOnly_ = enable; + } + + void EndEffectorTrajectory::init (const EndEffectorTrajectoryWkPtr_t& weak) + { + core::PathPlanner::init (weak); + weak_ = weak; + nRandomConfig_ = 10; + nDiscreteSteps_ = 1; + feasibilityOnly_ = true; + } + } // namespace pathPlanner + } // namespace manipulation +} // namespace hpp diff --git a/src/problem-solver.cc b/src/problem-solver.cc index a75cd757a8eb622b65eb626ab7fcdf6c5ef6e948..92eede11847f4842373c0a733e8c1eac6fa38b7f 100644 --- a/src/problem-solver.cc +++ b/src/problem-solver.cc @@ -57,6 +57,7 @@ #include "hpp/manipulation/graph-node-optimizer.hh" #include "hpp/manipulation/path-optimization/random-shortcut.hh" #include "hpp/manipulation/path-optimization/enforce-transition-semantic.hh" +#include "hpp/manipulation/path-planner/end-effector-trajectory.hh" #include "hpp/manipulation/problem-target/state.hh" #include "hpp/manipulation/steering-method/cross-state-optimization.hh" #include "hpp/manipulation/steering-method/graph.hh" @@ -121,6 +122,7 @@ namespace hpp { robotType ("hpp::manipulation::Device"); pathPlanners.add ("M-RRT", ManipulationPlanner::create); + pathPlanners.add ("EndEffectorTrajectory", pathPlanner::EndEffectorTrajectory::createWithRoadmap); pathValidations.add ("Graph-Discretized" , createDiscretizedCollisionGraphPathValidation); pathValidations.add ("Graph-DiscretizedCollision" , createDiscretizedCollisionGraphPathValidation); diff --git a/src/steering-method/end-effector-trajectory.cc b/src/steering-method/end-effector-trajectory.cc index 776f0d68d1b5c1ea1bafd5308c1d8531c88a8e97..3825b02534d06ee3f8fcd50f88a91cece5a17e9d 100644 --- a/src/steering-method/end-effector-trajectory.cc +++ b/src/steering-method/end-effector-trajectory.cc @@ -26,7 +26,9 @@ #include <hpp/constraints/implicit.hh> #include <hpp/core/config-projector.hh> +#include <hpp/core/interpolated-path.hh> #include <hpp/core/path.hh> +#include <hpp/core/path-vector.hh> #include <hpp/core/problem.hh> #include <hpp/core/straight-path.hh> @@ -80,6 +82,34 @@ namespace hpp { }; } + PathPtr_t EndEffectorTrajectory::makePiecewiseLinearTrajectory ( + matrixIn_t points, + vectorIn_t weights) + { + if (points.cols() != 7) + throw std::invalid_argument("The input matrix should have 7 columns"); + if (weights.size() != 6) + throw std::invalid_argument("The weights vector should have 6 elements"); + LiegroupSpacePtr_t se3 = LiegroupSpace::SE3(); + core::PathVectorPtr_t path = core::PathVector::create(7, 6); + if (points.rows() == 1) + path->appendPath (core::StraightPath::create (se3, + points.row(0), + points.row(0), interval_t(0,0))); + else + for (size_type i = 1; i < points.rows(); ++i) { + value_type d = + ( se3->elementConstRef(points.row(i)) + - se3->elementConstRef(points.row(i-1)) + ).cwiseProduct(weights).norm(); + path->appendPath (core::StraightPath::create (se3, + points.row(i-1), + points.row(i), + interval_t(0, d))); + } + return path; + } + void EndEffectorTrajectory::trajectoryConstraint (const constraints::ImplicitPtr_t& ic) { constraint_ = ic; @@ -112,7 +142,48 @@ namespace hpp { ConfigurationIn_t q2) const { try { + core::ConstraintSetPtr_t c (getUpdatedConstraints()); + + return core::StraightPath::create (problem().robot(), q1, q2, timeRange_, c); + } catch (const std::exception& e) { + std::cout << timeRange_.first << ", " << timeRange_.second << '\n'; + if (eeTraj_) + std::cout << (*eeTraj_) (vector_t::Constant(1,timeRange_.first )) << '\n' + << (*eeTraj_) (vector_t::Constant(1,timeRange_.second)) << std::endl; + std::cout << *constraints() << std::endl; + std::cout << e.what() << std::endl; + throw; + } + } + + PathPtr_t EndEffectorTrajectory::projectedPath (vectorIn_t times, + matrixIn_t configs) const + { + core::ConstraintSetPtr_t c (getUpdatedConstraints()); + + size_type N = configs.cols(); + if (timeRange_.first != times[0] || timeRange_.second != times[N-1]) { + HPP_THROW (std::logic_error, "Time range (" << timeRange_.first << + ", " << timeRange_.second << ") does not match configuration " + "times (" << times[0] << ", " << times[N-1]); + } + + using core::InterpolatedPath; + using core::InterpolatedPathPtr_t; + + InterpolatedPathPtr_t path = InterpolatedPath::create( + problem().robot(), configs.col(0), configs.col(N-1), timeRange_, c); + + for (size_type i = 1; i < configs.cols()-1; ++i) + path->insert(times[i], configs.col(i)); + + return path; + } + + core::ConstraintSetPtr_t EndEffectorTrajectory::getUpdatedConstraints () const + { if (!eeTraj_) throw std::logic_error ("EndEffectorTrajectory not initialized."); + // Update (or check) the constraints core::ConstraintSetPtr_t c (constraints()); if (!c || !c->configProjector()) { @@ -144,18 +215,8 @@ namespace hpp { HPP_THROW (std::logic_error, "EndEffectorTrajectory could not find " "constraint " << constraint_->function()); } - - return core::StraightPath::create (problem().robot(), q1, q2, timeRange_, c); - } catch (const std::exception& e) { - std::cout << timeRange_.first << ", " << timeRange_.second << '\n'; - if (eeTraj_) - std::cout << (*eeTraj_) (vector_t::Constant(1,timeRange_.first )) << '\n' - << (*eeTraj_) (vector_t::Constant(1,timeRange_.second)) << std::endl; - std::cout << *constraints() << std::endl; - std::cout << e.what() << std::endl; - throw; + return c; } - } } // namespace steeringMethod } // namespace manipulation } // namespace hpp