diff --git a/NEWS b/NEWS index 0c133eb5bbe48a3eb5fc2ec43c6e023977eecc5f..0a8dde97929b493080f0e8684e706d76b8e35e87 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,26 @@ -*- outline -*- +New in +* In graph::steeringMethod, if q1 == q2, the steering method calls the problem + inner steering method. This avoids a failure if no loop transition has been + set on the state containing q1. +* In class Edge, + - different security margins for different pairs of links can + be set for collision checking, + - rename some methods for homogeneity with python bindings + - applyConstraints -> generateTargetConfig + - configConstraint -> targetConstraint, + - from -> stateFrom, to -> stateTo. +* In class LevelSetEdge, + - write documentation, + - rename method applyConstraintsWithOffset into generateTargetConfigOnLeaf, + - add read access to condition and parameterization constraints. +* In class GraphComponent, + - add cost +* Add end-effector-tracjectory plugin. +* In class ManipulationPlanner, + - call the problem PathValidation instead of the edge one. + +New in 4.8.0 * Rewrite steering method CrossStateOptimization. * In graph component classes (State, Edge, Graph) locked joints are handled as other numerical constraints. - decouple waypoint computations. diff --git a/doc/Doxyfile.extra.in b/doc/Doxyfile.extra.in index 2d1578be3c59d3f9509f581df72d77001ef03c81..9ca64de3f434a2e125f080fe33b7d42657e5d5f8 100644 --- a/doc/Doxyfile.extra.in +++ b/doc/Doxyfile.extra.in @@ -1,6 +1,5 @@ INPUT = @CMAKE_SOURCE_DIR@/doc \ @CMAKE_SOURCE_DIR@/include \ - @CMAKE_SOURCE_DIR@/src/steering-method/cross-state-optimization/function.cc \ @CMAKE_BINARY_DIR@/doc HTML_EXTRA_FILES = @CMAKE_SOURCE_DIR@/doc/ObjectManipulation_MasterThesis_JosephMirabel.pdf 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 ac42495677b7d58acdf042e5877b782d092796bf..90d8cb135b3cd71c85f625e0723fb9434f753906 100644 --- a/include/hpp/manipulation/graph/edge.hh +++ b/include/hpp/manipulation/graph/edge.hh @@ -71,42 +71,59 @@ namespace hpp { const StateWkPtr_t& from, const StateWkPtr_t& to); - /// Apply edge constraint + /// Generate a reachable configuration in the target state /// - /// \param nnear node containing the configuration defining the right + /// \param nStart node containing the configuration defining the right /// hand side of the edge constraint, - /// \param[in,out] q configuration to which the edge constraint is - /// applied. + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear + /// \deprecated Use generateTargetConfig instead. + virtual bool applyConstraints (core::NodePtr_t nStart, + ConfigurationOut_t q) const + HPP_MANIPULATION_DEPRECATED; + + /// Generate a reachable configuration in the target state /// - /// \sa hpp::core::ConfigProjector::rightHandSideFromConfig - virtual bool applyConstraints (core::NodePtr_t nnear, ConfigurationOut_t q) const; - /// Apply edge constraint + /// \param qStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + /// \deprecated Use generateTargetConfig instead. + virtual bool applyConstraints (ConfigurationIn_t qStart, + ConfigurationOut_t q) const + HPP_MANIPULATION_DEPRECATED; + + /// Generate a reachable configuration in the target state /// - /// \param qoffset configuration defining the right hand side of the - /// edge constraint, - /// \param[in,out] q configuration to which the edge constraint is - /// applied. + /// \param nStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nStart. + virtual bool generateTargetConfig(core::NodePtr_t nStart, + ConfigurationOut_t q) const; + + /// Generate a reachable configuration in the target state /// - /// \sa hpp::core::ConfigProjector::rightHandSideFromConfig - virtual bool applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const; + /// \param qStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + virtual bool generateTargetConfig (ConfigurationIn_t qStart, + ConfigurationOut_t q) const; virtual bool canConnect (ConfigurationIn_t q1, ConfigurationIn_t q2) const; virtual bool build (core::PathPtr_t& path, ConfigurationIn_t q1, ConfigurationIn_t q2) const; - /// Get the destination - /// \deprecated from and to method are renamed stateFrom and stateTo. - /// method from cannot be binded in python since "from" - /// is a keyword in python. - StatePtr_t to () const HPP_MANIPULATION_DEPRECATED; - - /// Get the origin - /// \deprecated from and to method are renamed stateFrom and stateTo. - /// method from cannot be binded in python since "from" - /// is a keyword in python. - StatePtr_t from () const HPP_MANIPULATION_DEPRECATED; - /// Get the destination StatePtr_t stateTo () const; @@ -174,7 +191,12 @@ namespace hpp { virtual std::ostream& dotPrint (std::ostream& os, dot::DrawingAttributes da = dot::DrawingAttributes ()) const; /// Constraint of the destination state and of the path - ConstraintSetPtr_t configConstraint() const; + /// \deprecated Use targetConstraint instead + ConstraintSetPtr_t configConstraint() const + HPP_MANIPULATION_DEPRECATED; + + /// Constraint of the destination state and of the path + ConstraintSetPtr_t targetConstraint() const; void setShort (bool isShort) { isShort_ = isShort; @@ -195,8 +217,13 @@ namespace hpp { /// Constructor Edge (const std::string& name); - virtual ConstraintSetPtr_t buildConfigConstraint(); + virtual ConstraintSetPtr_t buildConfigConstraint() + HPP_MANIPULATION_DEPRECATED; + + /// Build path and target state constraint set. + virtual ConstraintSetPtr_t buildTargetConstraint(); + /// Build path constraints virtual ConstraintSetPtr_t buildPathConstraint(); virtual void initialize (); @@ -212,7 +239,7 @@ namespace hpp { /// Constraint ensuring that a q_proj will be in to_ and in the /// same leaf of to_ as the configuration used for initialization. - ConstraintSetPtr_t configConstraints_; + ConstraintSetPtr_t targetConstraints_; /// The two ends of the transition. StateWkPtr_t from_, to_; @@ -236,21 +263,34 @@ namespace hpp { friend class Graph; }; // class Edge - /// Edge with waypoint. - /// Waypoints are handled recursively, i.e.\ class WaypointEdge contains only a - /// State and an Edge, the second Edge being itself. - /// In this package, the State in a WaypointEdge is semantically different from other State - /// because it does not correspond to a state with different manipulation rules. It has - /// the same rules as another State (either Edge::from() or Edge::to()). + /// Edge with intermediate waypoint states. + /// + /// This class implements a transition from one state to another state + /// with intermediate states in-between. This feature is particularly + /// interesting when manipulating objects. Between a state where a gripper + /// does not grasp an object and a state where the same gripper grasps + /// the object, it is useful to add an intermediate state where the + /// gripper is close to the object. /// - /// Semantically, a waypoint State is fully part of the WaypointEdge. When a corresponding path - /// reaches it, no planning is required to know what to do next. To the contrary, when a path reaches - /// Edge::from() or Edge::to(), there may be several possibilities. + /// Waypoints are handled recursively, i.e.\ class WaypointEdge + /// contains only a State and an Edge, the second Edge being + /// itself. In this package, the State in a WaypointEdge is + /// semantically different from other State because it does not + /// correspond to a state with different manipulation rules. It + /// has the same rules as another State (either Edge::stateFrom() or + /// Edge::stateTo()). + /// + /// Semantically, a waypoint State is fully part of the WaypointEdge. + /// When a corresponding path reaches it, no planning is required to know + /// what to do next. To the contrary, when a path reaches + /// Edge::stateFrom() or Edge::stateTo(), there may be several + /// possibilities. /// /// \note - /// Implementation details: let's say, between the two states \f$N_f\f$ and \f$N_t\f$, - /// two waypoints are required: - /// \f$ N_f \xrightarrow{e_0} n_0 \xrightarrow{e_1} n_1 \xrightarrow{e_2} N_t\f$. + /// Implementation details: let's say, between the two states \f$N_f\f$ + /// and \f$N_t\f$, two waypoints are required: + /// \f$ N_f \xrightarrow{e_0} n_0 \xrightarrow{e_1} n_1 + /// \xrightarrow{e_2} N_t\f$. /// The WaypointEdge contains: /// \li from: \f$N_f\f$, /// \li to: \f$N_t\f$, @@ -270,7 +310,30 @@ namespace hpp { virtual bool build (core::PathPtr_t& path, ConfigurationIn_t q1, ConfigurationIn_t q2) const; - virtual bool applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const; + + /// Generate a reachable configuration in the target state + /// + /// \param qStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + /// deprecated Used generateTargetConfig instead. + virtual bool applyConstraints (ConfigurationIn_t qStart, + ConfigurationOut_t q) const + HPP_MANIPULATION_DEPRECATED; + + /// Generate a reachable configuration in the target state + /// + /// \param qStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + virtual bool generateTargetConfig (ConfigurationIn_t qStart, + ConfigurationOut_t q) const; /// Return the index-th edge. const EdgePtr_t& waypoint (const std::size_t index) const; @@ -313,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: @@ -325,27 +459,115 @@ namespace hpp { const GraphWkPtr_t& graph, const StateWkPtr_t& from, const StateWkPtr_t& to); - virtual bool applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const; - - virtual bool applyConstraints (core::NodePtr_t n_offset, ConfigurationOut_t q) const; - - virtual ConstraintSetPtr_t buildConfigConstraint(); - + /// Generate a reachable configuration in the target state + /// + /// \param nStart node containing the configuration defining the right + /// hand side of the edge constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear + /// \deprecated Use generateTargetConfig instead. + virtual bool applyConstraints (core::NodePtr_t nStart, + ConfigurationOut_t q) const + HPP_MANIPULATION_DEPRECATED; + + /// Generate a reachable configuration in the target state + /// + /// \param qStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + /// \deprecated Use generateTargetConfig instead. + virtual bool applyConstraints (ConfigurationIn_t qStart, + ConfigurationOut_t q) const + HPP_MANIPULATION_DEPRECATED; + + /// Generate a reachable configuration in the target state + /// + /// \param nStart node containing the configuration defining the right + /// hand side of the edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nStart. + virtual bool generateTargetConfig(core::NodePtr_t nStart, + ConfigurationOut_t q) const; + + /// Generate a reachable configuration in the target state + /// + /// \param qStart configuration defining the right hand side of the + /// edge path constraint, + /// \param[in,out] q input configuration used to initialize the + /// numerical solver and output configuration lying + /// in the target state and reachable along the edge + /// from nnear. + virtual bool generateTargetConfig (ConfigurationIn_t qStart, + ConfigurationOut_t q) const; + + /// Generate a reachable configuration in leaf of target state + /// \param qStart configuration defining the right hand side of the + /// edge path constraint, + /// \param qLeaf configuration used to set the right hand side of + /// the target state foliation. See method + /// \link LevelSetEdge::insertParamConstraint + /// insertParamConstraint\endlink. + bool generateTargetConfigOnLeaf(ConfigurationIn_t qStart, + ConfigurationIn_t qLeaf, + ConfigurationOut_t q) const; + + /// \deprecated Use buildTargetConstraint instead + virtual ConstraintSetPtr_t buildConfigConstraint() + HPP_MANIPULATION_DEPRECATED; + + /// 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::conditionConstraints + /// 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 + /// Get constraints parameterizing the target state foliation + const NumericalConstraints_t& paramConstraints() const; + + /// Insert a condition constraint + /// \sa LevelSetEdge::histogram void insertConditionConstraint (const ImplicitPtr_t& nm, const segments_t& passiveDofs = segments_t ()); + /// Get constraints parameterizing the target state foliation + /// \sa LevelSetEdge::histogram + const NumericalConstraints_t& conditionConstraints() const; /// \} /// Print the object in a stream. @@ -367,9 +589,6 @@ namespace hpp { virtual void initialize (); private: - bool applyConstraintsWithOffset (ConfigurationIn_t qoffset, - ConfigurationIn_t qlevelset, ConfigurationOut_t q) const; - // Parametrizer // NumericalConstraints_t NumericalConstraints_t paramNumericalConstraints_; diff --git a/include/hpp/manipulation/graph/graph.hh b/include/hpp/manipulation/graph/graph.hh index ff07201995951b2b16f7018bb2487f7af084d023..af5840675609ddf46ee14769a61c22ef944fd72f 100644 --- a/include/hpp/manipulation/graph/graph.hh +++ b/include/hpp/manipulation/graph/graph.hh @@ -122,10 +122,18 @@ namespace hpp { /// \return The initialized projector. ConstraintSetPtr_t configConstraint (const StatePtr_t& state) const; - /// Constraint to project onto the same leaf as config. - /// \param edges a list of edges defining the foliation. - /// \return The constraint. - ConstraintSetPtr_t configConstraint (const EdgePtr_t& edge) const; + /// Constraints of path and target state of an edge + /// \deprecated Use tagetConstraint instead. + ConstraintSetPtr_t configConstraint (const EdgePtr_t& edge) const + HPP_MANIPULATION_DEPRECATED; + + /// Constraints a configuration in target state should satisfy + /// \param edge a transition + /// \return The set of constraints a configuration lying in the + /// target state of the edge should satisfy. This set + /// includes the paths constraints of the edge. + /// \sa Edge::targetConstraint. + ConstraintSetPtr_t targetConstraint (const EdgePtr_t& edge) const; /// Get error of a config with respect to a state constraint /// diff --git a/src/graph/edge.cc b/src/graph/edge.cc index f08aa4bc8442e088fb8cd3f7ef285631bf65798b..412e82fa7df1c90de75dba8222c73b1e29966e29 100644 --- a/src/graph/edge.cc +++ b/src/graph/edge.cc @@ -41,7 +41,7 @@ namespace hpp { Edge::Edge (const std::string& name) : GraphComponent (name), isShort_ (false), pathConstraints_ (), - configConstraints_ (), + targetConstraints_ (), steeringMethod_ (), securityMargins_ (), pathValidation_ () @@ -50,16 +50,6 @@ namespace hpp { Edge::~Edge () {} - StatePtr_t Edge::to () const - { - return to_.lock(); - } - - StatePtr_t Edge::from () const - { - return from_.lock(); - } - StatePtr_t Edge::stateTo () const { return to_.lock(); @@ -94,7 +84,7 @@ namespace hpp { // 01 | ? | ? | 0 | 0 // 11 | ? | 1 | * | 0 // 10 | ? | 1 | 1 | 1 - // + // /// true if reverse if ( (!src_contains_q0 && !src_contains_q1) || (!dst_contains_q0 && !dst_contains_q1) @@ -133,7 +123,7 @@ namespace hpp { ConfigProjectorPtr_t proj) const { GraphPtr_t g = graph_.lock (); - + g->insertNumericalConstraints (proj); insertNumericalConstraints (proj); state ()->insertNumericalConstraints (proj); @@ -175,7 +165,7 @@ namespace hpp { void Edge::initialize () { - configConstraints_ = buildConfigConstraint (); + targetConstraints_ = buildTargetConstraint (); pathConstraints_ = buildPathConstraint (); isInit_ = true; } @@ -201,13 +191,19 @@ namespace hpp { return os; } + ConstraintSetPtr_t Edge::targetConstraint() const + { + throwIfNotInitialized (); + return targetConstraints_; + } + ConstraintSetPtr_t Edge::configConstraint() const { throwIfNotInitialized (); - return configConstraints_; + 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 @@ -274,6 +270,11 @@ namespace hpp { } ConstraintSetPtr_t Edge::buildConfigConstraint() + { + return buildTargetConstraint(); + } + + ConstraintSetPtr_t Edge::buildTargetConstraint() { std::string n = "(" + name () + ")"; GraphPtr_t g = graph_.lock (); @@ -288,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); @@ -381,18 +387,31 @@ namespace hpp { } } - bool Edge::applyConstraints (core::NodePtr_t nnear, ConfigurationOut_t q) const + bool Edge::applyConstraints (core::NodePtr_t nStart, + ConfigurationOut_t q) const { - return applyConstraints (*(nnear->configuration ()), q); + return generateTargetConfig (*(nStart->configuration ()), q); } bool Edge::applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const { - ConstraintSetPtr_t c = configConstraint (); + return generateTargetConfig(qoffset, q); + } + + bool Edge::generateTargetConfig (core::NodePtr_t nStart, + ConfigurationOut_t q) const + { + return generateTargetConfig (*(nStart->configuration ()), q); + } + + bool Edge::generateTargetConfig (ConfigurationIn_t qStart, + ConfigurationOut_t q) const + { + ConstraintSetPtr_t c = targetConstraint(); ConfigProjectorPtr_t proj = c->configProjector (); - proj->rightHandSideFromConfig (qoffset); - if (isShort_) q = qoffset; + proj->rightHandSideFromConfig (qStart); + if (isShort_) q = qStart; if (c->apply (q)) return true; const ::hpp::statistics::SuccessStatistics& ss = proj->statistics (); if (ss.nbFailure () > ss.nbSuccess ()) { @@ -441,7 +460,7 @@ namespace hpp { core::PathVectorPtr_t pv = core::PathVector::create (graph_.lock ()->robot ()->configSize (), graph_.lock ()->robot ()->numberDof ()); - // Many times, this will be called rigth after WaypointEdge::applyConstraints so config_ + // Many times, this will be called rigth after WaypointEdge::generateTargetConfig so config_ // already satisfies the constraints. size_type n = edges_.size(); assert (configs_.cols() == n + 1); @@ -453,17 +472,17 @@ namespace hpp { for (size_type i = 0; i < n; ++i) { if (i < (n-1) && !useCache) configs_.col (i+1) = q2; - if (i < (n-1) && !edges_[i]->applyConstraints (configs_.col(i), configs_.col (i+1))) { - hppDout (info, "Waypoint edge " << name() << ": applyConstraints failed at waypoint " << i << "." + if (i < (n-1) && !edges_[i]->generateTargetConfig (configs_.col(i), configs_.col (i+1))) { + hppDout (info, "Waypoint edge " << name() << ": generateTargetConfig failed at waypoint " << i << "." << "\nUse cache: " << useCache ); lastSucceeded_ = false; return false; } - assert (configConstraint ()); - assert (configConstraint ()->configProjector ()); + assert (targetConstraint()); + assert (targetConstraint()->configProjector ()); value_type eps - (configConstraint ()->configProjector ()->errorThreshold ()); + (targetConstraint()->configProjector ()->errorThreshold ()); if ((configs_.col(i) - configs_.col (i+1)).squaredNorm () > eps*eps) { if (!edges_[i]->build (p, configs_.col(i), configs_.col (i+1))) { hppDout (info, "Waypoint edge " << name() @@ -481,13 +500,20 @@ namespace hpp { return true; } - bool WaypointEdge::applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const + bool WaypointEdge::applyConstraints (ConfigurationIn_t qStart, + ConfigurationOut_t q) const + { + return generateTargetConfig(qStart,q); + } + + bool WaypointEdge::generateTargetConfig (ConfigurationIn_t qStart, + ConfigurationOut_t q) const { assert (configs_.cols() == size_type(edges_.size() + 1)); - configs_.col(0) = qoffset; + configs_.col(0) = qStart; for (std::size_t i = 0; i < edges_.size (); ++i) { configs_.col (i+1) = q; - if (!edges_[i]->applyConstraints (configs_.col(i), configs_.col (i+1))) { + if (!edges_[i]->generateTargetConfig (configs_.col(i), configs_.col (i+1))) { q = configs_.col(i+1); lastSucceeded_ = false; return false; @@ -523,7 +549,7 @@ namespace hpp { const EdgePtr_t& WaypointEdge::waypoint (const std::size_t index) const { - assert (index < edges_.size()); + assert (index < edges_.size()); return edges_[index]; } @@ -584,7 +610,14 @@ namespace hpp { } } - bool LevelSetEdge::applyConstraints (ConfigurationIn_t qoffset, ConfigurationOut_t q) const + bool LevelSetEdge::applyConstraints(ConfigurationIn_t qStart, + ConfigurationOut_t q) const + { + return generateTargetConfig(qStart, q); + } + + bool LevelSetEdge::generateTargetConfig(ConfigurationIn_t qStart, + ConfigurationOut_t q) const { // First, get an offset from the histogram statistics::DiscreteDistribution < RoadmapNodePtr_t > distrib = hist_->getDistrib (); @@ -592,42 +625,53 @@ namespace hpp { hppDout (warning, "Edge " << name() << ": Distrib is empty"); return false; } - const Configuration_t& qlevelset = *(distrib ()->configuration ()); + const Configuration_t& qLeaf = *(distrib ()->configuration ()); - return applyConstraintsWithOffset (qoffset, qlevelset, q); + return generateTargetConfigOnLeaf (qStart, qLeaf, q); + } + + bool LevelSetEdge::applyConstraints(core::NodePtr_t nStart, + ConfigurationOut_t q) const + { + return generateTargetConfig(nStart, q); } - bool LevelSetEdge::applyConstraints (core::NodePtr_t n_offset, ConfigurationOut_t q) const + bool LevelSetEdge::generateTargetConfig(core::NodePtr_t nStart, + ConfigurationOut_t q) const { - // First, get an offset from the histogram that is not in the same connected component. - statistics::DiscreteDistribution < RoadmapNodePtr_t > distrib = hist_->getDistribOutOfConnectedComponent (n_offset->connectedComponent ()); + // First, get an offset from the histogram that is not in the same connected component. + statistics::DiscreteDistribution < RoadmapNodePtr_t > distrib = hist_->getDistribOutOfConnectedComponent (nStart->connectedComponent ()); if (distrib.size () == 0) { hppDout (warning, "Edge " << name() << ": Distrib is empty"); return false; } - const Configuration_t& qlevelset = *(distrib ()->configuration ()), - qoffset = *(n_offset->configuration ()); + const Configuration_t& qLeaf = *(distrib ()->configuration ()), + qStart = *(nStart->configuration ()); - return applyConstraintsWithOffset (qoffset, qlevelset, q); + return generateTargetConfigOnLeaf (qStart, qLeaf, q); } - bool LevelSetEdge::applyConstraintsWithOffset (ConfigurationIn_t qoffset, - ConfigurationIn_t qlevelset, ConfigurationOut_t q) const + bool LevelSetEdge::generateTargetConfigOnLeaf(ConfigurationIn_t qStart, + ConfigurationIn_t qLeaf, + ConfigurationOut_t q) const { // First, set the offset. - ConstraintSetPtr_t cs = configConstraint (); + ConstraintSetPtr_t cs = targetConstraint(); const ConfigProjectorPtr_t cp = cs->configProjector (); assert (cp); - cp->rightHandSideFromConfig (qoffset); + // 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) { - cp->rightHandSideFromConfig (*it, qlevelset); + cp->rightHandSideFromConfig (*it, qLeaf); } // Eventually, do the projection. - if (isShort_) q = qoffset; + if (isShort_) q = qStart; if (cs->apply (q)) return true; ::hpp::statistics::SuccessStatistics& ss = cp->statistics (); if (ss.nbFailure () > ss.nbSuccess ()) { @@ -730,6 +774,11 @@ namespace hpp { } ConstraintSetPtr_t LevelSetEdge::buildConfigConstraint() + { + return buildTargetConstraint(); + } + + ConstraintSetPtr_t LevelSetEdge::buildTargetConstraint() { std::string n = "(" + name () + ")"; GraphPtr_t g = graph_.lock (); @@ -738,6 +787,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 (); @@ -767,6 +823,11 @@ namespace hpp { paramPassiveDofs_.push_back (passiveDofs); } + const NumericalConstraints_t& LevelSetEdge::paramConstraints() const + { + return paramNumericalConstraints_; + } + void LevelSetEdge::insertConditionConstraint (const constraints::ImplicitPtr_t& nm, const segments_t& passiveDofs) @@ -776,6 +837,11 @@ namespace hpp { condPassiveDofs_.push_back (passiveDofs); } + const NumericalConstraints_t& LevelSetEdge::conditionConstraints() const + { + return condNumericalConstraints_; + } + LevelSetEdge::LevelSetEdge (const std::string& name) : Edge (name) diff --git a/src/graph/graph.cc b/src/graph/graph.cc index 3d5ba3b7ccc858ce0d3afc3339d42b0116cb3360..3725672c605ce5b73b10b969a32dc5dd9d87ddf1 100644 --- a/src/graph/graph.cc +++ b/src/graph/graph.cc @@ -132,7 +132,7 @@ namespace hpp { Edges_t edges; for (Neighbors_t::const_iterator it = from->neighbors ().begin (); it != from->neighbors ().end (); ++it) { - if (it->second->to () == to) + if (it->second->stateTo () == to) edges.push_back (it->second); } return edges; @@ -205,7 +205,7 @@ namespace hpp { (ConfigurationIn_t leafConfig, ConfigurationIn_t config, const EdgePtr_t& edge, vector_t& error) const { - ConstraintSetPtr_t cs (configConstraint (edge)); + ConstraintSetPtr_t cs (targetConstraint (edge)); ConfigProjectorPtr_t cp (cs->configProjector ()); if (cp) cp->rightHandSideFromConfig (leafConfig); return cs->isSatisfied (config, error); @@ -223,7 +223,12 @@ namespace hpp { ConstraintSetPtr_t Graph::configConstraint (const EdgePtr_t& edge) const { - return edge->configConstraint (); + return edge->targetConstraint (); + } + + ConstraintSetPtr_t Graph::targetConstraint (const EdgePtr_t& edge) const + { + return edge->targetConstraint (); } ConstraintSetPtr_t Graph::pathConstraint (const EdgePtr_t& edge) const diff --git a/src/graph/guided-state-selector.cc b/src/graph/guided-state-selector.cc index 334504c95108c16a7ce974c880026344c96bfae7..1ccfec093f592717ec7a706f29a0e1b848eb2611 100644 --- a/src/graph/guided-state-selector.cc +++ b/src/graph/guided-state-selector.cc @@ -92,13 +92,13 @@ namespace hpp { const Neighbors_t& n = state->neighbors(); /// You stay in the same state for (Neighbors_t::const_iterator it = n.begin (); it != n.end (); ++it) - if (it->second->to () == state) + if (it->second->stateTo () == state) nn.insert (it->second, it->first); /// Go from state it1 to state // The path will be build from state. So we must find an edge from // state to it1, that will be reversely for (Neighbors_t::const_iterator it = n.begin (); it != n.end (); ++it) - if (it->second->to () == *it1) + if (it->second->stateTo () == *it1) nn.insert (it->second, it->first); } else { States_t::const_iterator it1 = stateList_.begin (); @@ -118,7 +118,8 @@ namespace hpp { for (Neighbors_t::const_iterator it = n.begin (); it != n.end (); ++it) /// You stay in the same state /// or go from state to state it1 - if (it->second->to () == state || it->second->to () == *it1) + if (it->second->stateTo () == state || + it->second->stateTo () == *it1) nn.insert (it->second, it->first); } if (nn.size () > 0 && nn.totalWeight() > 0) diff --git a/src/manipulation-planner.cc b/src/manipulation-planner.cc index d42f7cd5a36c8b07b82f318462e9ccdb3521b015..5950d3b2359cbd0c48e42301fd536237d4fcf421 100644 --- a/src/manipulation-planner.cc +++ b/src/manipulation-planner.cc @@ -55,7 +55,7 @@ namespace hpp { HPP_DEFINE_TIMECOUNTER(tryConnectToRoadmap); /// extend steps HPP_DEFINE_TIMECOUNTER(chooseEdge); - HPP_DEFINE_TIMECOUNTER(applyConstraints); + HPP_DEFINE_TIMECOUNTER(generateTargetConfig); HPP_DEFINE_TIMECOUNTER(buildPath); HPP_DEFINE_TIMECOUNTER(projectPath); HPP_DEFINE_TIMECOUNTER(validatePath); @@ -241,7 +241,7 @@ namespace hpp { HPP_DISPLAY_TIMECOUNTER(nearestNeighbor); HPP_DISPLAY_TIMECOUNTER(delayedEdges); HPP_DISPLAY_TIMECOUNTER(chooseEdge); - HPP_DISPLAY_TIMECOUNTER(applyConstraints); + HPP_DISPLAY_TIMECOUNTER(generateTargetConfig); HPP_DISPLAY_TIMECOUNTER(buildPath); HPP_DISPLAY_TIMECOUNTER(projectPath); HPP_DISPLAY_TIMECOUNTER(validatePath); @@ -265,10 +265,10 @@ namespace hpp { return false; } qProj_ = *q_rand; - HPP_START_TIMECOUNTER (applyConstraints); + HPP_START_TIMECOUNTER (generateTargetConfig); SuccessStatistics& es = edgeStat (edge); - if (!edge->applyConstraints (n_near, qProj_)) { - HPP_STOP_TIMECOUNTER (applyConstraints); + if (!edge->generateTargetConfig(n_near, qProj_)) { + HPP_STOP_TIMECOUNTER (generateTargetConfig); es.addFailure (reasons_[FAILURE]); es.addFailure (reasons_[PROJECTION]); return false; @@ -278,7 +278,7 @@ namespace hpp { es.addFailure (reasons_[PATH_PROJECTION_ZERO]); return false; } - HPP_STOP_TIMECOUNTER (applyConstraints); + HPP_STOP_TIMECOUNTER (generateTargetConfig); core::PathPtr_t path; HPP_START_TIMECOUNTER (buildPath); if (!edge->build (path, *q_near, qProj_)) { diff --git a/src/path-optimization/enforce-transition-semantic.cc b/src/path-optimization/enforce-transition-semantic.cc index 14221df930b6f0b5d9c75be71d69e7177f67d750..675298a93065868201fff1f85084697703a1dddd 100644 --- a/src/path-optimization/enforce-transition-semantic.cc +++ b/src/path-optimization/enforce-transition-semantic.cc @@ -40,12 +40,12 @@ namespace hpp { Edges_t edges; for (graph::Neighbors_t::const_iterator it = from->neighbors ().begin (); it != from->neighbors ().end (); ++it) { - if (it->second->to () == to) + if (it->second->stateTo () == to) edges.push_back (it->second); } for (Edges_t::const_iterator it = from->hiddenNeighbors ().begin (); it != from->hiddenNeighbors ().end (); ++it) { - if ((*it)->to () == to) + if ((*it)->stateTo () == to) edges.push_back (*it); } return edges; @@ -70,8 +70,8 @@ namespace hpp { } Configuration_t q0 = current->initial(); Configuration_t q1 = current->end (); - StatePtr_t src = c->edge()->from(); - StatePtr_t dst = c->edge()->to (); + StatePtr_t src = c->edge()->stateFrom(); + StatePtr_t dst = c->edge()->stateTo (); if (src == dst) continue; bool q0_in_src = src->contains(q0); diff --git a/src/path-optimization/spline-gradient-based.cc b/src/path-optimization/spline-gradient-based.cc index 50bfb16e6fae78011e2fa1ccea030c7bebb86581..0e6cf918bee25fa8722df59532dfdd0c7a68332b 100644 --- a/src/path-optimization/spline-gradient-based.cc +++ b/src/path-optimization/spline-gradient-based.cc @@ -91,8 +91,8 @@ namespace hpp { // The path should always go through the start and end states of the // transition. assert(!HPP_DYNAMIC_PTR_CAST(graph::WaypointEdge, transition)); - graph::StatePtr_t from = transition->from(); - graph::StatePtr_t to = transition->to(); + graph::StatePtr_t from = transition->stateFrom(); + graph::StatePtr_t to = transition->stateTo(); graph::StatePtr_t from2 = from, to2 = to; Configuration_t q0 = path->initial (), @@ -120,7 +120,8 @@ namespace hpp { if (use_direct) { // Nominal case if (transition->state() != to) { - constrainEndIntoState (path, i, splines[i], transition->to(), lc); + constrainEndIntoState (path, i, splines[i], transition->stateTo(), + lc); } stateOfStart = to; } else if (use_reverse) { diff --git a/src/steering-method/cross-state-optimization.cc b/src/steering-method/cross-state-optimization.cc index 4216f5edd3e2dd5824e448415985d5ec50d657e6..6e3afcfd10bd0eb68609d7dce677b02d0463e2db 100644 --- a/src/steering-method/cross-state-optimization.cc +++ b/src/steering-method/cross-state-optimization.cc @@ -91,7 +91,7 @@ namespace hpp { std::size_t i; // index in parent state_with_depths_t inline state_with_depth () : s(), e(), l(0), i (0) {} inline state_with_depth (EdgePtr_t _e, std::size_t _l, std::size_t _i) - : s(_e->from()), e(_e), l(_l), i (_i) {} + : s(_e->stateFrom()), e(_e), l(_l), i (_i) {} }; typedef std::vector<state_with_depth> state_with_depths_t; typedef std::map<StatePtr_t,state_with_depths_t> StateMap_t; @@ -131,7 +131,7 @@ namespace hpp { // Insert state to if necessary StateMap_t::iterator next = parent1.insert ( StateMap_t::value_type( - transition->to(), state_with_depths_t () + transition->stateTo(), state_with_depths_t () )).first; next->second.push_back ( @@ -233,7 +233,7 @@ namespace hpp { d.addParent (_state, transition) ); - done = done || (transition->to() == d.s2); + done = done || (transition->stateTo() == d.s2); } if (done) break; } @@ -475,7 +475,7 @@ namespace hpp { graph::GraphPtr_t cg (problem_.constraintGraph ()); // Fill solvers with graph, node and edge constraints for (std::size_t j = 0; j < d.N; ++j) { - graph::StatePtr_t state (transitions [(std::size_t)j]->to ()); + graph::StatePtr_t state (transitions [(std::size_t)j]->stateTo ()); // initialize solver with state constraints d.solvers [(std::size_t)j] = state->configConstraint ()-> configProjector ()->solver ();