diff --git a/include/hpp/manipulation/axial-handle.hh b/include/hpp/manipulation/axial-handle.hh index 605f43688a7728de5cfb9a6e851835cbde0340b1..9ea966fd85ff41db76ae4a47a0a0ec56fcd7507c 100644 --- a/include/hpp/manipulation/axial-handle.hh +++ b/include/hpp/manipulation/axial-handle.hh @@ -64,13 +64,6 @@ namespace hpp { virtual NumericalConstraintPtr_t createGraspComplement (const GripperPtr_t& gripper, std::string name) const; - /// Create constraint composed of grasp constraint and its complement - /// \param gripper object containing the gripper information - /// \return the composition of grasp constraint and its complement. - /// \note the 6 degrees of freedom are constrained - virtual NumericalConstraintPtr_t createGraspAndComplement - (const GripperPtr_t& gripper, std::string name) const; - /// Create constraint corresponding to a pregrasping task. /// \param gripper object containing the gripper information /// \return the constraint of relative transformation between the handle and diff --git a/include/hpp/manipulation/fwd.hh b/include/hpp/manipulation/fwd.hh index c076ca844aeef8129d9cad97e29a963db246726a..2a80e4cd801dfdeb32d462d149861b084b6fb42a 100644 --- a/include/hpp/manipulation/fwd.hh +++ b/include/hpp/manipulation/fwd.hh @@ -100,10 +100,16 @@ namespace hpp { typedef std::vector <ObjectPtr_t> Objects_t; typedef core::Constraint Constraint; typedef core::ConstraintPtr_t ConstraintPtr_t; + typedef core::ExplicitNumericalConstraintPtr_t + ExplicitNumericalConstraintPtr_t; typedef core::LockedJoint LockedJoint; typedef core::LockedJointPtr_t LockedJointPtr_t; typedef core::NumericalConstraint NumericalConstraint; typedef core::NumericalConstraintPtr_t NumericalConstraintPtr_t; + typedef core::ComparisonTypesPtr_t ComparisonTypesPtr_t; + typedef core::EqualToZero EqualToZero; + typedef core::Equality Equality; + typedef core::ComparisonTypes ComparisonTypes; typedef core::ConfigProjector ConfigProjector; typedef core::ConfigProjectorPtr_t ConfigProjectorPtr_t; HPP_PREDEF_CLASS (ConstraintSet); diff --git a/include/hpp/manipulation/graph/graph.hh b/include/hpp/manipulation/graph/graph.hh index 56ba1109eeb24aae8c129f74320ae34e18783aa5..a7314ea42dad02b780e189f2476a0eb8ba3a85da 100644 --- a/include/hpp/manipulation/graph/graph.hh +++ b/include/hpp/manipulation/graph/graph.hh @@ -17,6 +17,7 @@ #ifndef HPP_MANIPULATION_GRAPH_GRAPH_HH # define HPP_MANIPULATION_GRAPH_GRAPH_HH +# include <boost/tuple/tuple.hpp> # include "hpp/manipulation/config.hh" # include "hpp/manipulation/fwd.hh" # include "hpp/manipulation/graph/fwd.hh" @@ -104,6 +105,38 @@ namespace hpp { /// Select randomly outgoing edge of the given node. EdgePtr_t chooseEdge(RoadmapNodePtr_t node) const; + /// Register a triple of constraints to be inserted in nodes and edges + /// \param constraint a constraint (grasp of placement) + /// \param complement the complement constraint + /// \param both combination of the constraint and its complement. Both + /// constraints together corresponds to a full relative + /// transformation constraint + /// When inserting constraints in transitions of the graph, + /// in many cases, a constraint is associated to a state and + /// the complement constraint is associated to the + /// transition itself. Registering those constraints + /// priorly to graph construction makes possible to replace + /// the constraint and its complement by the combination of + /// both that is an explicit constraint. + void registerConstraints (const NumericalConstraintPtr_t& constraint, + const NumericalConstraintPtr_t& complement, + const NumericalConstraintPtr_t& both); + + /// Test whether two constraints are complement of one another + /// + /// \param constraint, complement two constraints to test + /// \retval combinationOfBoth constraint corresponding to combining + /// constraint and complement if result is true, + /// unchanged otherwise. + /// \return whether complement is the complement of constraint. + /// Two constraints are complement of one another if and only if + /// combined they constitute a complement relative transformation + /// constraint. \sa Graph::registerConstraints + /// \warning argument order matters. + bool isComplement (const NumericalConstraintPtr_t& constraint, + const NumericalConstraintPtr_t& complement, + NumericalConstraintPtr_t& combinationOfBoth) const; + /// Constraint to project onto the Node. /// \param state the state on which to project. /// \return The initialized projector. @@ -265,6 +298,20 @@ namespace hpp { value_type errorThreshold_; size_type maxIterations_; + struct ConstraintAndComplement_t { + NumericalConstraintPtr_t constraint; + NumericalConstraintPtr_t complement; + NumericalConstraintPtr_t both; + ConstraintAndComplement_t (const NumericalConstraintPtr_t& constr, + const NumericalConstraintPtr_t& comp, + const NumericalConstraintPtr_t& b) : + constraint (constr), complement (comp), both (b) + { + } + }; + typedef std::vector <ConstraintAndComplement_t> + ConstraintsAndComplements_t; + ConstraintsAndComplements_t constraintsAndComplements_; friend class GraphComponent; }; // Class Graph diff --git a/src/graph/edge.cc b/src/graph/edge.cc index 8c7fdd8863c3d2366641cd996ffc95e834afe943..31ee35142167db40899715d5aaef75c8f42e3cb2 100644 --- a/src/graph/edge.cc +++ b/src/graph/edge.cc @@ -165,6 +165,62 @@ namespace hpp { return configConstraints_; } + // Merge constraints of several graph components into a config projectors + // Replace constraints and complement by combination of both when + // necessary. + static void mergeConstraintsIntoConfigProjector + (const ConfigProjectorPtr_t& proj, + const std::vector <GraphComponentPtr_t>& components, + const GraphPtr_t& graph) + { + NumericalConstraints_t nc; + std::vector <segments_t> pdof; + for (std::vector <GraphComponentPtr_t>::const_iterator it + (components.begin ()); it != components.end (); ++it) { + nc.insert (nc.end (), (*it)->numericalConstraints ().begin (), + (*it)->numericalConstraints ().end ()); + pdof.insert (pdof.end (), (*it)->passiveDofs ().begin (), + (*it)->passiveDofs ().end ()); + } + assert (nc.size () == pdof.size ()); + NumericalConstraints_t::iterator itnc1 (nc.begin ()); + std::vector <segments_t>::iterator itpdof1 (pdof.begin ()); + while (itnc1 != nc.end ()) { + NumericalConstraints_t::iterator itnc2 (nc.begin ()); + std::vector <segments_t>::iterator itpdof2 (pdof.begin ()); + while (itnc2 != nc.end ()) { + bool increment (true); + NumericalConstraintPtr_t combination; + // Do not check that a constraint is its own complement + if (itnc1 != itnc2) { + // Remove duplicate constraints + if (*itnc1 == *itnc2) { + nc.erase (itnc2); + pdof.erase (itpdof2); + increment = false; + } else if (graph->isComplement (*itnc1, *itnc2, combination)) { + // Replace constraint by combination of both and remove + // complement. + *itnc1 = combination; + if (itnc1 > itnc2) --itnc1; + nc.erase (itnc2); + pdof.erase (itpdof2); + break; + } + } + if (increment) ++itnc2; ++itpdof2; + } + ++itnc1; ++itpdof1; + } + assert (nc.size () == pdof.size ()); + NumericalConstraints_t::iterator itnc (nc.begin ()); + std::vector <segments_t>::iterator itpdof (pdof.begin ()); + while (itnc != nc.end ()) { + proj->add (*itnc, *itpdof); + ++itnc; ++itpdof; + } + } + ConstraintSetPtr_t Edge::buildConfigConstraint() { std::string n = "(" + name () + ")"; @@ -180,12 +236,14 @@ namespace hpp { state ()->insertLockedJoints (proj); } - g->insertNumericalConstraints (proj); - insertNumericalConstraints (proj); - to ()->insertNumericalConstraints (proj); + std::vector <GraphComponentPtr_t> components; + components.push_back (g); + components.push_back (wkPtr_.lock ()); + components.push_back (to ()); if (state () != to ()) { - state ()->insertNumericalConstraints (proj); + components.push_back (state ()); } + mergeConstraintsIntoConfigProjector (proj, components, parentGraph ()); constraint->addConstraint (proj); constraint->edge (wkPtr_.lock ()); @@ -210,9 +268,11 @@ namespace hpp { insertLockedJoints (proj); state ()->insertLockedJoints (proj); - g->insertNumericalConstraints (proj); - insertNumericalConstraints (proj); - state ()->insertNumericalConstraintsForPath (proj); + std::vector <GraphComponentPtr_t> components; + components.push_back (g); + components.push_back (wkPtr_.lock ()); + components.push_back (state ()); + mergeConstraintsIntoConfigProjector (proj, components, parentGraph ()); constraint->addConstraint (proj); constraint->edge (wkPtr_.lock ()); diff --git a/src/graph/graph.cc b/src/graph/graph.cc index c3812b75acc4ee07b9a5e4d41a8f20eb82ef7d9b..7d397a98e0dbb0495093f0ce5c9d2b61be1932a1 100644 --- a/src/graph/graph.cc +++ b/src/graph/graph.cc @@ -150,6 +150,32 @@ namespace hpp { return stateSelector_->chooseEdge (from); } + void Graph::registerConstraints + (const NumericalConstraintPtr_t& constraint, + const NumericalConstraintPtr_t& complement, + const NumericalConstraintPtr_t& both) + { + constraintsAndComplements_.push_back (ConstraintAndComplement_t + (constraint, complement, both)); + } + + bool Graph::isComplement (const NumericalConstraintPtr_t& constraint, + const NumericalConstraintPtr_t& complement, + NumericalConstraintPtr_t& combinationOfBoth) + const + { + for (ConstraintsAndComplements_t::const_iterator it = + constraintsAndComplements_.begin (); + it != constraintsAndComplements_.end (); ++it) { + if ((it->constraint->functionPtr () == constraint->functionPtr ()) && + (it->complement->functionPtr () == complement->functionPtr ())) { + combinationOfBoth = it->both; + return true; + } + } + return false; + } + ConstraintSetPtr_t Graph::configConstraint (const StatePtr_t& state) const { return state->configConstraint (); diff --git a/src/handle.cc b/src/handle.cc index 446fc9b920590a039c92670fbbfdaff158d0c374..797db73157630daeb80791c0819ec04bce607aaf 100644 --- a/src/handle.cc +++ b/src/handle.cc @@ -164,12 +164,25 @@ namespace hpp { if (n.empty()) { n = gripper->name() + "_holds_" + name(); } + // Create the comparison operator + assert (mask_.size () == 6); + ComparisonTypes_t comp (6); + for (std::size_t i=0; i<6;++i) { + if (mask_ [i]) { + comp [i] = constraints::EqualToZero; + } else { + comp [i] = constraints::Equality; + } + } // If handle is on a freeflying object, create an explicit constraint if (isHandleOnFreeflyer (*this)) { - return ExplicitRelativeTransformation::create - (n, gripper->joint ()->robot (), gripper->joint (), joint (), - gripper->objectPositionInJoint (), - localPosition())->createNumericalConstraint(); + ExplicitNumericalConstraintPtr_t enc + (ExplicitRelativeTransformation::create + (n, gripper->joint ()->robot (), gripper->joint (), joint (), + gripper->objectPositionInJoint (), + localPosition())->createNumericalConstraint()); + enc->comparisonType (comp); + return enc; } return NumericalConstraintPtr_t (NumericalConstraint::create (RelativeTransformation::create @@ -179,7 +192,7 @@ namespace hpp { gripper->objectPositionInJoint (), localPosition(), list_of (true)(true)(true)(true)(true) - (true)))); + (true)), comp)); } NumericalConstraintPtr_t Handle::createPreGrasp diff --git a/src/problem-solver.cc b/src/problem-solver.cc index 694ea363be0f880e561cfdc47d3e50288c8e579e..fd688e57a01d0f21a1502326c6cf723f349d4fe7 100644 --- a/src/problem-solver.cc +++ b/src/problem-solver.cc @@ -301,15 +301,22 @@ namespace hpp { (const std::string& name, const std::string& gripper, const std::string& handle) { + if (!constraintGraph ()) { + throw std::runtime_error ("The graph is not defined."); + } GripperPtr_t g = robot_->get <GripperPtr_t> (gripper); if (!g) throw std::runtime_error ("No gripper with name " + gripper + "."); HandlePtr_t h = robot_->get <HandlePtr_t> (handle); if (!h) throw std::runtime_error ("No handle with name " + handle + "."); const std::string cname = name + "/complement"; + const std::string bname = name + "/hold"; NumericalConstraintPtr_t constraint (h->createGrasp (g, name)); NumericalConstraintPtr_t complement (h->createGraspComplement (g, cname)); + NumericalConstraintPtr_t both (h->createGraspAndComplement (g, bname)); addNumericalConstraint ( name, constraint); addNumericalConstraint (cname, complement); + addNumericalConstraint (bname, both); + constraintGraph ()->registerConstraints (constraint, complement, both); } void ProblemSolver::createPreGraspConstraint