diff --git a/include/hpp/manipulation/graph/helper.hh b/include/hpp/manipulation/graph/helper.hh index c3b7b832f5eaa9b2ed3319d1e499e21011d8b28e..d806f00d8f3996a0858aeba418eff373364cacaa 100644 --- a/include/hpp/manipulation/graph/helper.hh +++ b/include/hpp/manipulation/graph/helper.hh @@ -80,9 +80,12 @@ namespace hpp { void addToEdge (EdgePtr_t comp) const; void specifyFoliation (LevelSetEdgePtr_t lse) const; - bool isFoliated () const { + bool foliated () const { return lj_fol.empty () && nc_fol.nc.empty (); } + bool empty () const { + return lj.empty () && nc.nc.empty (); + } }; typedef std::pair <EdgePtr_t, EdgePtr_t> EdgePair_t; diff --git a/src/graph/helper.cc b/src/graph/helper.cc index 0d982688f3edc51cdcdfded2c47e2cb233efeb05..4d5c3d19868acdc965c4418cd6796eab68687408 100644 --- a/src/graph/helper.cc +++ b/src/graph/helper.cc @@ -16,6 +16,8 @@ #include <hpp/manipulation/graph/helper.hh> +#include <boost/foreach.hpp> + #include <hpp/util/debug.hh> #include <hpp/model/gripper.hh> @@ -195,7 +197,7 @@ namespace hpp { weBack->setWaypoint (2, e21, n1); if (levelSetPlace) { - if (!place.isFoliated ()) { + if (!place.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for placement, " "but did not specify the target foliation. " "It will have no effect"); @@ -207,7 +209,7 @@ namespace hpp { submanifoldDef.addToEdge (e32_ls); } if (levelSetGrasp) { - if (!grasp.isFoliated ()) { + if (!grasp.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for grasping, " "but did not specify the target foliation. " "It will have no effect"); @@ -293,7 +295,7 @@ namespace hpp { weForw->setWaypoint (0, (levelSetGrasp)?e21_ls:e21, n1); if (levelSetPlace) { - if (!place.isFoliated ()) { + if (!place.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for placement, " "but did not specify the target foliation. " "It will have no effect"); @@ -305,7 +307,7 @@ namespace hpp { submanifoldDef.addToEdge (e21_ls); } if (levelSetGrasp) { - if (!grasp.isFoliated ()) { + if (!grasp.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for grasping, " "but did not specify the target foliation. " "It will have no effect"); @@ -385,7 +387,7 @@ namespace hpp { if (levelSetGrasp) { hppDout (error, "You specified a foliated grasp with no placement. " "This is currently unsupported."); - if (!grasp.isFoliated ()) { + if (!grasp.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for grasping, " "but did not specify the target foliation. " "It will have no effect"); @@ -425,7 +427,7 @@ namespace hpp { submanifoldDef.addToEdge (eBack); if (levelSetGrasp) { - if (!grasp.isFoliated ()) { + if (!grasp.foliated ()) { hppDout (warning, "You asked for a LevelSetEdge for grasping, " "but did not specify the target foliation. " "It will have no effect"); @@ -499,41 +501,198 @@ namespace hpp { preplace.nc_path.pdof.push_back (SizeIntervals_t()); } - typedef std::vector <std::size_t> IndexV_t; - typedef std::list <std::size_t> IndexL_t; - typedef std::pair <std::size_t, std::size_t> Grasp_t; - typedef std::vector <std::size_t, std::size_t> GraspV_t; + namespace { + typedef std::size_t index_t; + typedef std::vector <index_t> IndexV_t; + typedef std::list <index_t> IndexL_t; + typedef std::pair <index_t, index_t> Grasp_t; + typedef boost::tuple <NodePtr_t, + FoliatedManifold> + NodeAndManifold_t; + //typedef std::vector <index_t, index_t> GraspV_t; + /// GraspV_t corresponds to a unique ID of a permutation. + /// - its size is the number of grippers, + /// - the values correpond to the index of the handle (0..nbHandle-1), or + /// nbHandle to mean no handle. + typedef std::vector <index_t> GraspV_t; + + struct Result { + GraphPtr_t graph; + std::vector<NodeAndManifold_t> nodes; + index_t nG, nOH; + GraspV_t dims; + const Grippers_t& gs; + const Objects_t& ohs; + + Result (const Grippers_t& grippers, const Objects_t& objects, GraphPtr_t g) : + graph (g), nG (grippers.size ()), nOH (0), gs (grippers), ohs (objects) + { + BOOST_FOREACH (const Object_t& o, objects) { + nOH += o.get<1>().size(); + } + dims.resize (nG); + dims[0] = nOH + 1; + for (index_t i = 1; i < nG; ++i) + dims[i] = dims[i-1] * (nOH + 1); + nodes.resize (dims[nG-1] * (nOH + 1)); + } + + NodeAndManifold_t& operator() (const GraspV_t& iG) + { + index_t iGOH = 0; + for (index_t i = 1; i < nG; ++i) + iGOH += dims[i] * (iG[i]); + return nodes [iGOH]; + } + + const Object_t& object (const index_t& iOH) const { + index_t iH = iOH; + BOOST_FOREACH (const Object_t& o, ohs) { + if (iH < o.get<1>().size()) return o; + iH -= o.get<1>().size(); + } + throw std::out_of_range ("Handle index"); + } + + const HandlePtr_t& handle (const index_t& iOH) const { + index_t iH = iOH; + BOOST_FOREACH (const Object_t& o, ohs) { + if (iH < o.get<1>().size()) return o.get<1>()[iH]; + iH -= o.get<1>().size(); + } + throw std::out_of_range ("Handle index"); + } - void makeEdge (const Grippers_t& grippers, const IndexV_t& idx_g, - const Objects_t& objects, const IndexV_t& idx_oh, - const GraspV_t& grasps + std::string name (const GraspV_t& /*iG*/) const { + // TODO: define a more representative name + return "name"; + } + }; + + const NodeAndManifold_t& makeNode (Result& r, const GraspV_t& g) + { + NodeAndManifold_t& nam = r (g); + if (!nam.get<0>()) { + nam.get<0>() = r.graph->nodeSelector ()->createNode (r.name (g)); + // Loop over the grippers and create grasping constraints if required + FoliatedManifold unused; + std::set <index_t> idxsOH; + for (index_t i = 0; i < r.nG; ++i) { + if (g[i] < r.nOH) { + idxsOH.insert (g[i]); + graspManifold (r.gs[i], r.handle (g[i]), + nam.get<1>(), unused); + } + } + index_t iOH = 0; + BOOST_FOREACH (const Object_t& o, r.ohs) { + bool oIsGrasped = false; + // TODO: use the fact that the set is sorted. + // BOOST_FOREACH (const HandlePtr_t& h, o.get<1>()) { + for (index_t i = 0; i < o.get<1>().size(); ++i) { + if (idxsOH.erase (iOH) == 1) oIsGrasped = true; + ++iOH; + } + if (!oIsGrasped) + relaxedPlacementManifold (o.get<0>().get<0>(), + o.get<0>().get<1>(), + o.get<0>().get<2>(), + nam.get<1>(), unused); + } + nam.get<1>().addToNode (nam.get<0>()); + } + return nam; + } + + /// Arguments are such that + /// \li gTo[iG] != gFrom[iG] + /// \li for all i != iG, gTo[iG] == gFrom[iG] + void makeEdge (Result& r, + const GraspV_t& gFrom, const GraspV_t& gTo, + const index_t iG) + { + const NodeAndManifold_t& from = makeNode (r, gFrom), + to = makeNode (r, gTo); + FoliatedManifold grasp, pregrasp, place, preplace; + graspManifold (r.gs[iG], r.handle (gTo[iG]), + grasp, pregrasp); + const Object_t& o = r.object (gTo[iG]); + relaxedPlacementManifold (o.get<0>().get<0>(), + o.get<0>().get<1>(), + o.get<0>().get<2>(), + place, preplace); + if (pregrasp.empty ()) { + if (preplace.empty ()) + createEdges <GraspOnly | PlaceOnly> ( + "forwName" , "backName", + from.get<0> () , to.get<0>(), + 1 , 1, + grasp , pregrasp, + place , preplace, + grasp.foliated () , place.foliated(), + from.get<1> ()); + else + createEdges <GraspOnly | WithPrePlace> ( + "forwName" , "backName", + from.get<0> () , to.get<0>(), + 1 , 1, + grasp , pregrasp, + place , preplace, + grasp.foliated () , place.foliated(), + from.get<1> ()); + } else { + if (preplace.empty ()) + createEdges <WithPreGrasp | PlaceOnly> ( + "forwName" , "backName", + from.get<0> () , to.get<0>(), + 1 , 1, + grasp , pregrasp, + place , preplace, + grasp.foliated () , place.foliated(), + from.get<1> ()); + else + createEdges <WithPreGrasp | WithPrePlace> ( + "forwName" , "backName", + from.get<0> () , to.get<0>(), + 1 , 1, + grasp , pregrasp, + place , preplace, + grasp.foliated () , place.foliated(), + from.get<1> ()); + } + } /// idx are the available grippers - void recurseGrippers (const Grippers_t& grippers, const IndexV_t& idx_g, - const Objects_t& objects, const IndexV_t& idx_oh, + void recurseGrippers (Result& r, + const IndexV_t& idx_g, const IndexV_t& idx_oh, const GraspV_t& grasps) { + IndexV_t nIdx_g (idx_g.size() - 1); + IndexV_t nIdx_oh (idx_oh.size() - 1); for (IndexV_t::const_iterator itx_g = idx_g.begin (); itx_g != idx_g.end (); ++itx_g) { - IndexV_t nIdx_g (idx_g.size() - 1); // Copy all element except itx_g std::copy (boost::next (itx_g), idx_g.end (), std::copy (idx_g.begin (), itx_g, nIdx_g.begin ()) ); for (IndexV_t::const_iterator itx_oh = idx_oh.begin (); itx_oh != idx_oh.end (); ++itx_oh) { - IndexV_t nIdx_oh (idx_oh.size() - 1); // Copy all element except itx_oh std::copy (boost::next (itx_oh), idx_oh.end (), std::copy (idx_oh.begin (), itx_oh, nIdx_oh.begin ()) ); + + // Create the edge for the selected grasp GraspV_t nGrasps = grasps; - grasps.push_back (Grasp_t (*itx_g, *itx_oh)); - makeEdge (grippers, objects, grasps, nGrasps); - recurseGrippers (grippers, nIdx_oh, objects, nIdx_oh, nGrasps); + nGrasps [*itx_g] = *itx_oh; + makeEdge (r, grasps, nGrasps, *itx_g); + + // Do all the possible combination below this new grasp + recurseGrippers (r, nIdx_oh, nIdx_oh, nGrasps); } } } + } void graphBuilder ( const Objects_t& objects, @@ -544,15 +703,15 @@ namespace hpp { NodeSelectorPtr_t ns = graph->nodeSelector (); if (!ns) throw std::logic_error ("The graph does not have a NodeSelector"); - // Max number of handles that can be grasped - std::size_t nGrippers = grippers.size (); - for (Objects_t::const_iterator begin = objects.begin (); - begin != objects.end (); ++begin) { - for ( - } - for (Grippers_t::const_iterator begin = grippers.begin (); - begin != grippers.end (); ++begin) { - } + Result r (grippers, objects, graph); + + IndexV_t availG (r.nG), availOH (r.nOH); + for (index_t i = 0; i < r.nG; ++i) availG[i] = i; + for (index_t i = 0; i < r.nOH; ++i) availOH[i] = i; + + GraspV_t iG (r.nG, r.nOH); + + recurseGrippers (r, availG, availOH, iG); } } // namespace helper } // namespace graph