From 01f26776f86d469c8c2c264ce3b1e06af3c8e908 Mon Sep 17 00:00:00 2001 From: Paul Sardin Date: Wed, 24 Sep 2025 11:36:26 +0200 Subject: [PATCH 1/4] Add grasp creation functions and grasp storage to manipulation graph --- .../manipulation/constraint_graph_factory.py | 24 +++----- src/pyhpp/manipulation/graph.cc | 55 ++++++++++++++++++- src/pyhpp/manipulation/graph.hh | 10 ++++ 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/src/pyhpp/manipulation/constraint_graph_factory.py b/src/pyhpp/manipulation/constraint_graph_factory.py index a9381415..ac24fd5d 100644 --- a/src/pyhpp/manipulation/constraint_graph_factory.py +++ b/src/pyhpp/manipulation/constraint_graph_factory.py @@ -708,20 +708,13 @@ def buildGrasp(self, g, h): if not graspAlreadyCreated: cname = n + "/complement" bname = n + "/hold" - gripper = self.graph.robot.grippers()[g] - handle = self.graph.robot.handles()[h] - constraint = handle.createGrasp(gripper, n) - complement = handle.createGraspComplement(gripper, cname) - both = handle.createGraspAndComplement(gripper, bname) - self.registerConstraint(constraint, n) - self.registerConstraint(complement, cname) - self.registerConstraint(both, bname) + constraints = self.graph.createGraspConstraint(n, g, h) + self.registerConstraint(constraints[0], n) + self.registerConstraint(constraints[1], cname) + self.registerConstraint(constraints[2], bname) if not pregraspAlreadyCreated: - gripper = self.graph.robot.grippers()[g] - handle = self.graph.robot.handles()[h] - c = handle.clearance + gripper.clearance - pregrasp = handle.createPreGrasp(gripper, c, pn) - self.registerConstraint(pregrasp, pn) + constraint = self.graph.createPreGraspConstraint(pn, g, h) + self.registerConstraint(constraint, pn) return dict( list( zip( @@ -1070,10 +1063,11 @@ def _createWaypointState(name, constraints): self.edge_objects[nf] = forward_trans self.edge_objects[nb] = backward_trans - nf_ls = nf - nb_ls = nb if crossedFoliation: + + nf_ls = nf + nb_ls = nb if i == 0: edgeName = nf_ls = nf + "_ls" containingState = ( diff --git a/src/pyhpp/manipulation/graph.cc b/src/pyhpp/manipulation/graph.cc index 2c467ce6..e15cb99a 100644 --- a/src/pyhpp/manipulation/graph.cc +++ b/src/pyhpp/manipulation/graph.cc @@ -42,6 +42,8 @@ #include #include #include +#include "hpp/manipulation/constraint-set.hh" + namespace { const char* DOC_CREATESTATE = @@ -662,7 +664,8 @@ void PyWGraph::registerConstraints(const ImplicitPtr_t& constraint, const ImplicitPtr_t& complement, const ImplicitPtr_t& both) { try { - obj->registerConstraints(constraint, complement, both); + constraintsAndComplements.push_back( + ConstraintAndComplement_t(constraint, complement, both)); } catch (const std::exception& exc) { throw std::logic_error(exc.what()); } @@ -975,6 +978,11 @@ void PyWGraph::display(const char* filename) { void PyWGraph::initialize() { try { + obj->clearConstraintsAndComplement(); + for (std::size_t i = 0; i < constraintsAndComplements.size(); ++i) { + const ConstraintAndComplement_t& c = constraintsAndComplements[i]; + obj->registerConstraints(c.constraint, c.complement, c.both); + } obj->initialize(); } catch (const std::exception& exc) { throw std::logic_error(exc.what()); @@ -1041,6 +1049,10 @@ boost::python::tuple PyWGraph::createPlacementConstraint( std::get<0>(constraints)->functionPtr())); contactFunction->setNormalMargin(margin); + constraintsAndComplements.push_back(ConstraintAndComplement_t( + std::get<0>(constraints), std::get<1>(constraints), + std::get<2>(constraints))); + return boost::python::make_tuple(std::get<0>(constraints), std::get<1>(constraints), std::get<2>(constraints)); @@ -1139,6 +1151,44 @@ ImplicitPtr_t PyWGraph::createPrePlacementConstraint2( return createPrePlacementConstraint(name, py_surface1, py_surface2, width); } +boost::python::list PyWGraph::createGraspConstraint(const std::string& name, + const std::string& gripper, + const std::string& handle) { + + boost::python::list result; + + GripperPtr_t g = robot->obj->grippers.get(gripper, GripperPtr_t()); + if (!g) throw std::runtime_error("No gripper with name " + gripper + "."); + HandlePtr_t h = robot->obj->handles.get(handle, HandlePtr_t()); + if (!h) throw std::runtime_error("No handle with name " + handle + "."); + const std::string cname = name + "/complement"; + const std::string bname = name + "/hold"; + ImplicitPtr_t constraint(h->createGrasp(g, name)); + ImplicitPtr_t complement(h->createGraspComplement(g, cname)); + ImplicitPtr_t both(h->createGraspAndComplement(g, bname)); + + result.append(constraint); + result.append(complement); + result.append(both); + + constraintsAndComplements.push_back( + ConstraintAndComplement_t(constraint, complement, both)); + + return result; +} + +ImplicitPtr_t PyWGraph::createPreGraspConstraint(const std::string& name, + const std::string& gripper, + const std::string& handle) { + GripperPtr_t g = robot->obj->grippers.get(gripper, GripperPtr_t()); + if (!g) throw std::runtime_error("No gripper with name " + gripper + "."); + HandlePtr_t h = robot->obj->handles.get(handle, HandlePtr_t()); + if (!h) throw std::runtime_error("No handle with name " + handle + "."); + + value_type c = h->clearance() + g->clearance(); + ImplicitPtr_t constraint = h->createPreGrasp(g, c, name); + return constraint; +} // ============================================================================= // Boost.Python bindings // ============================================================================= @@ -1222,7 +1272,8 @@ void exposeGraph() { .def("createPrePlacementConstraint", &PyWGraph::createPrePlacementConstraint2, DOC_CREATEPREPLACEMENTCONSTRAINT) - + .def("createGraspConstraint", &PyWGraph::createGraspConstraint) + .def("createPreGraspConstraint", &PyWGraph::createPreGraspConstraint) // Configuration error checking .PYHPP_DEFINE_METHOD1(PyWGraph, getConfigErrorForState, DOC_GETCONFIGERRORFORSTATE) diff --git a/src/pyhpp/manipulation/graph.hh b/src/pyhpp/manipulation/graph.hh index 0a49e4a5..4a272963 100644 --- a/src/pyhpp/manipulation/graph.hh +++ b/src/pyhpp/manipulation/graph.hh @@ -48,6 +48,8 @@ typedef hpp::manipulation::graph::EdgePtr_t EdgePtr_t; typedef hpp::manipulation::graph::State State; typedef hpp::manipulation::graph::StatePtr_t StatePtr_t; typedef hpp::manipulation::graph::GraphPtr_t GraphPtr_t; +typedef hpp::manipulation::ConstraintsAndComplements_t ConstraintsAndComplements_t; +typedef hpp::manipulation::ConstraintAndComplement_t ConstraintAndComplement_t; /// Result structure for constraint operations struct ConstraintResult { @@ -88,6 +90,8 @@ struct PyWGraph { PyWDevicePtr_t robot; PyWProblemPtr_t problem; + ConstraintsAndComplements_t constraintsAndComplements; + // Constructors PyWGraph(const GraphPtr_t& object); PyWGraph(const std::string& name, const PyWDevicePtr_t& d, @@ -174,6 +178,12 @@ struct PyWGraph { const std::string& name, const boost::python::list& py_surface1, const boost::python::list& py_surface2, const value_type& width); + boost::python::list createGraspConstraint(const std::string& name, + const std::string& gripper, + const std::string& handle); + ImplicitPtr_t createPreGraspConstraint(const std::string& name, + const std::string& gripper, + const std::string& handle); boost::python::list getNumericalConstraintsForState(PyWStatePtr_t component); boost::python::list getNumericalConstraintsForEdge(PyWEdgePtr_t component); boost::python::list getNumericalConstraintsForGraph(); From a93744b079ea761647484bb30ae3b454a4ce17f1 Mon Sep 17 00:00:00 2001 From: Paul Sardin Date: Thu, 25 Sep 2025 09:35:24 +0200 Subject: [PATCH 2/4] Fix getConfigError function --- src/pyhpp/manipulation/graph.cc | 34 +++++++++++++++++++-------------- src/pyhpp/manipulation/graph.hh | 16 ++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/pyhpp/manipulation/graph.cc b/src/pyhpp/manipulation/graph.cc index e15cb99a..1159fb3b 100644 --- a/src/pyhpp/manipulation/graph.cc +++ b/src/pyhpp/manipulation/graph.cc @@ -675,19 +675,19 @@ void PyWGraph::registerConstraints(const ImplicitPtr_t& constraint, // Configuration error checking // ============================================================================= -bool PyWGraph::getConfigErrorForState(PyWStatePtr_t component, - ConfigurationIn_t input, - hpp::core::vector_t& error) { +boost::python::tuple PyWGraph::getConfigErrorForState(PyWStatePtr_t component, + ConfigurationIn_t input) { try { - return obj->getConfigErrorForState(input, component->obj, error); + hpp::core::vector_t error; + bool res = obj->getConfigErrorForState(input, component->obj, error); + return boost::python::make_tuple(error, res); } catch (const std::exception& exc) { throw std::logic_error(exc.what()); } } -bool PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, - ConfigurationIn_t input, - hpp::core::vector_t& error) { +boost::python::tuple PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, + ConfigurationIn_t input) { try { // Check if steering method is properly initialized if (!edge->obj->parentGraph()->problem()->manipulationSteeringMethod() || @@ -697,22 +697,28 @@ bool PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, ->innerSteeringMethod()) { throw std::logic_error("Could not initialize the steering method."); } - return obj->getConfigErrorForEdge(input, edge->obj, error); + hpp::core::vector_t error; + bool res = obj->getConfigErrorForEdge(input, edge->obj, error); + return boost::python::make_tuple(error, res); } catch (const std::exception& exc) { throw std::logic_error(exc.what()); } } -bool PyWGraph::getConfigErrorForTransitionLeaf( +boost::python::tuple PyWGraph::getConfigErrorForTransitionLeaf( ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge, hpp::core::vector_t& error) const { - return obj->getConfigErrorForEdgeLeaf(leafConfig, config, edge->obj, error); + const PyWEdgePtr_t& edge) const { + hpp::core::vector_t error; + bool res = obj->getConfigErrorForEdgeLeaf(leafConfig, config, edge->obj, error); + return boost::python::make_tuple(error, res); } -bool PyWGraph::getConfigErrorForTransitionTarget( +boost::python::tuple PyWGraph::getConfigErrorForTransitionTarget( ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge, hpp::core::vector_t& error) const { - return obj->getConfigErrorForEdgeTarget(leafConfig, config, edge->obj, error); + const PyWEdgePtr_t& edge) const { + hpp::core::vector_t error; + bool res = obj->getConfigErrorForEdgeTarget(leafConfig, config, edge->obj, error); + return boost::python::make_tuple(error, res); } // ============================================================================= diff --git a/src/pyhpp/manipulation/graph.hh b/src/pyhpp/manipulation/graph.hh index 4a272963..4d9c4388 100644 --- a/src/pyhpp/manipulation/graph.hh +++ b/src/pyhpp/manipulation/graph.hh @@ -189,18 +189,14 @@ struct PyWGraph { boost::python::list getNumericalConstraintsForGraph(); // Configuration error checking - bool getConfigErrorForState(PyWStatePtr_t component, ConfigurationIn_t input, - hpp::core::vector_t& error); - bool getConfigErrorForTransition(PyWEdgePtr_t edge, ConfigurationIn_t input, - hpp::core::vector_t& error); - bool getConfigErrorForTransitionLeaf(ConfigurationIn_t leafConfig, + boost::python::tuple getConfigErrorForState(PyWStatePtr_t component, ConfigurationIn_t input); + boost::python::tuple getConfigErrorForTransition(PyWEdgePtr_t edge, ConfigurationIn_t input); + boost::python::tuple getConfigErrorForTransitionLeaf(ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge, - hpp::core::vector_t& error) const; - bool getConfigErrorForTransitionTarget(ConfigurationIn_t leafConfig, + const PyWEdgePtr_t& edge) const; + boost::python::tuple getConfigErrorForTransitionTarget(ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge, - hpp::core::vector_t& error) const; + const PyWEdgePtr_t& edge) const; // Constraint application ConstraintResult applyStateConstraints(PyWStatePtr_t state, From c9d42f88870d2df024954cd0b7b22a47226ba567 Mon Sep 17 00:00:00 2001 From: Paul Sardin Date: Thu, 25 Sep 2025 10:04:33 +0200 Subject: [PATCH 3/4] Change arguments order to unify configErr functions --- src/pyhpp/manipulation/graph.cc | 10 ++++------ src/pyhpp/manipulation/graph.hh | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pyhpp/manipulation/graph.cc b/src/pyhpp/manipulation/graph.cc index 1159fb3b..20dd4c67 100644 --- a/src/pyhpp/manipulation/graph.cc +++ b/src/pyhpp/manipulation/graph.cc @@ -705,17 +705,15 @@ boost::python::tuple PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, } } -boost::python::tuple PyWGraph::getConfigErrorForTransitionLeaf( - ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge) const { +boost::python::tuple PyWGraph::getConfigErrorForTransitionLeaf( const PyWEdgePtr_t& edge, + ConfigurationIn_t leafConfig, ConfigurationIn_t config) const { hpp::core::vector_t error; bool res = obj->getConfigErrorForEdgeLeaf(leafConfig, config, edge->obj, error); return boost::python::make_tuple(error, res); } -boost::python::tuple PyWGraph::getConfigErrorForTransitionTarget( - ConfigurationIn_t leafConfig, ConfigurationIn_t config, - const PyWEdgePtr_t& edge) const { +boost::python::tuple PyWGraph::getConfigErrorForTransitionTarget(const PyWEdgePtr_t& edge, + ConfigurationIn_t leafConfig, ConfigurationIn_t config) const { hpp::core::vector_t error; bool res = obj->getConfigErrorForEdgeTarget(leafConfig, config, edge->obj, error); return boost::python::make_tuple(error, res); diff --git a/src/pyhpp/manipulation/graph.hh b/src/pyhpp/manipulation/graph.hh index 4d9c4388..c5583643 100644 --- a/src/pyhpp/manipulation/graph.hh +++ b/src/pyhpp/manipulation/graph.hh @@ -191,12 +191,10 @@ struct PyWGraph { // Configuration error checking boost::python::tuple getConfigErrorForState(PyWStatePtr_t component, ConfigurationIn_t input); boost::python::tuple getConfigErrorForTransition(PyWEdgePtr_t edge, ConfigurationIn_t input); - boost::python::tuple getConfigErrorForTransitionLeaf(ConfigurationIn_t leafConfig, - ConfigurationIn_t config, - const PyWEdgePtr_t& edge) const; - boost::python::tuple getConfigErrorForTransitionTarget(ConfigurationIn_t leafConfig, - ConfigurationIn_t config, - const PyWEdgePtr_t& edge) const; + boost::python::tuple getConfigErrorForTransitionLeaf(const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const; + boost::python::tuple getConfigErrorForTransitionTarget(const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const; // Constraint application ConstraintResult applyStateConstraints(PyWStatePtr_t state, From 40f716fed9382434da4836b60f0c831c7787babd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 08:05:18 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../manipulation/constraint_graph_factory.py | 2 - src/pyhpp/manipulation/graph.cc | 40 ++++++++++--------- src/pyhpp/manipulation/graph.hh | 27 ++++++++----- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/pyhpp/manipulation/constraint_graph_factory.py b/src/pyhpp/manipulation/constraint_graph_factory.py index ac24fd5d..6847d779 100644 --- a/src/pyhpp/manipulation/constraint_graph_factory.py +++ b/src/pyhpp/manipulation/constraint_graph_factory.py @@ -1063,9 +1063,7 @@ def _createWaypointState(name, constraints): self.edge_objects[nf] = forward_trans self.edge_objects[nb] = backward_trans - if crossedFoliation: - nf_ls = nf nb_ls = nb if i == 0: diff --git a/src/pyhpp/manipulation/graph.cc b/src/pyhpp/manipulation/graph.cc index 20dd4c67..d1474af8 100644 --- a/src/pyhpp/manipulation/graph.cc +++ b/src/pyhpp/manipulation/graph.cc @@ -42,6 +42,7 @@ #include #include #include + #include "hpp/manipulation/constraint-set.hh" namespace { @@ -676,7 +677,7 @@ void PyWGraph::registerConstraints(const ImplicitPtr_t& constraint, // ============================================================================= boost::python::tuple PyWGraph::getConfigErrorForState(PyWStatePtr_t component, - ConfigurationIn_t input) { + ConfigurationIn_t input) { try { hpp::core::vector_t error; bool res = obj->getConfigErrorForState(input, component->obj, error); @@ -686,8 +687,8 @@ boost::python::tuple PyWGraph::getConfigErrorForState(PyWStatePtr_t component, } } -boost::python::tuple PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, - ConfigurationIn_t input) { +boost::python::tuple PyWGraph::getConfigErrorForTransition( + PyWEdgePtr_t edge, ConfigurationIn_t input) { try { // Check if steering method is properly initialized if (!edge->obj->parentGraph()->problem()->manipulationSteeringMethod() || @@ -705,17 +706,21 @@ boost::python::tuple PyWGraph::getConfigErrorForTransition(PyWEdgePtr_t edge, } } -boost::python::tuple PyWGraph::getConfigErrorForTransitionLeaf( const PyWEdgePtr_t& edge, - ConfigurationIn_t leafConfig, ConfigurationIn_t config) const { +boost::python::tuple PyWGraph::getConfigErrorForTransitionLeaf( + const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const { hpp::core::vector_t error; - bool res = obj->getConfigErrorForEdgeLeaf(leafConfig, config, edge->obj, error); + bool res = + obj->getConfigErrorForEdgeLeaf(leafConfig, config, edge->obj, error); return boost::python::make_tuple(error, res); } -boost::python::tuple PyWGraph::getConfigErrorForTransitionTarget(const PyWEdgePtr_t& edge, - ConfigurationIn_t leafConfig, ConfigurationIn_t config) const { +boost::python::tuple PyWGraph::getConfigErrorForTransitionTarget( + const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const { hpp::core::vector_t error; - bool res = obj->getConfigErrorForEdgeTarget(leafConfig, config, edge->obj, error); + bool res = + obj->getConfigErrorForEdgeTarget(leafConfig, config, edge->obj, error); return boost::python::make_tuple(error, res); } @@ -1054,8 +1059,8 @@ boost::python::tuple PyWGraph::createPlacementConstraint( contactFunction->setNormalMargin(margin); constraintsAndComplements.push_back(ConstraintAndComplement_t( - std::get<0>(constraints), std::get<1>(constraints), - std::get<2>(constraints))); + std::get<0>(constraints), std::get<1>(constraints), + std::get<2>(constraints))); return boost::python::make_tuple(std::get<0>(constraints), std::get<1>(constraints), @@ -1156,9 +1161,8 @@ ImplicitPtr_t PyWGraph::createPrePlacementConstraint2( } boost::python::list PyWGraph::createGraspConstraint(const std::string& name, - const std::string& gripper, - const std::string& handle) { - + const std::string& gripper, + const std::string& handle) { boost::python::list result; GripperPtr_t g = robot->obj->grippers.get(gripper, GripperPtr_t()); @@ -1170,20 +1174,20 @@ boost::python::list PyWGraph::createGraspConstraint(const std::string& name, ImplicitPtr_t constraint(h->createGrasp(g, name)); ImplicitPtr_t complement(h->createGraspComplement(g, cname)); ImplicitPtr_t both(h->createGraspAndComplement(g, bname)); - + result.append(constraint); result.append(complement); result.append(both); constraintsAndComplements.push_back( ConstraintAndComplement_t(constraint, complement, both)); - + return result; } ImplicitPtr_t PyWGraph::createPreGraspConstraint(const std::string& name, - const std::string& gripper, - const std::string& handle) { + const std::string& gripper, + const std::string& handle) { GripperPtr_t g = robot->obj->grippers.get(gripper, GripperPtr_t()); if (!g) throw std::runtime_error("No gripper with name " + gripper + "."); HandlePtr_t h = robot->obj->handles.get(handle, HandlePtr_t()); diff --git a/src/pyhpp/manipulation/graph.hh b/src/pyhpp/manipulation/graph.hh index c5583643..baa42be8 100644 --- a/src/pyhpp/manipulation/graph.hh +++ b/src/pyhpp/manipulation/graph.hh @@ -48,7 +48,8 @@ typedef hpp::manipulation::graph::EdgePtr_t EdgePtr_t; typedef hpp::manipulation::graph::State State; typedef hpp::manipulation::graph::StatePtr_t StatePtr_t; typedef hpp::manipulation::graph::GraphPtr_t GraphPtr_t; -typedef hpp::manipulation::ConstraintsAndComplements_t ConstraintsAndComplements_t; +typedef hpp::manipulation::ConstraintsAndComplements_t + ConstraintsAndComplements_t; typedef hpp::manipulation::ConstraintAndComplement_t ConstraintAndComplement_t; /// Result structure for constraint operations @@ -179,22 +180,26 @@ struct PyWGraph { const boost::python::list& py_surface2, const value_type& width); boost::python::list createGraspConstraint(const std::string& name, - const std::string& gripper, - const std::string& handle); + const std::string& gripper, + const std::string& handle); ImplicitPtr_t createPreGraspConstraint(const std::string& name, - const std::string& gripper, - const std::string& handle); + const std::string& gripper, + const std::string& handle); boost::python::list getNumericalConstraintsForState(PyWStatePtr_t component); boost::python::list getNumericalConstraintsForEdge(PyWEdgePtr_t component); boost::python::list getNumericalConstraintsForGraph(); // Configuration error checking - boost::python::tuple getConfigErrorForState(PyWStatePtr_t component, ConfigurationIn_t input); - boost::python::tuple getConfigErrorForTransition(PyWEdgePtr_t edge, ConfigurationIn_t input); - boost::python::tuple getConfigErrorForTransitionLeaf(const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, - ConfigurationIn_t config) const; - boost::python::tuple getConfigErrorForTransitionTarget(const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, - ConfigurationIn_t config) const; + boost::python::tuple getConfigErrorForState(PyWStatePtr_t component, + ConfigurationIn_t input); + boost::python::tuple getConfigErrorForTransition(PyWEdgePtr_t edge, + ConfigurationIn_t input); + boost::python::tuple getConfigErrorForTransitionLeaf( + const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const; + boost::python::tuple getConfigErrorForTransitionTarget( + const PyWEdgePtr_t& edge, ConfigurationIn_t leafConfig, + ConfigurationIn_t config) const; // Constraint application ConstraintResult applyStateConstraints(PyWStatePtr_t state,