Unverified Commit 460162f6 authored by Justin Carpentier's avatar Justin Carpentier Committed by GitHub
Browse files

Merge pull request #1301 from jcarpent/topic/devel

Fix pickling of std::{vector,map} and add testing
parents 3e036c78 867dc26a
Pipeline #11259 passed with stage
in 108 minutes and 14 seconds
......@@ -186,11 +186,11 @@ namespace pinocchio
typedef PINOCCHIO_ALIGNED_STD_VECTOR(Vector3) StdVec_Vector3;
typedef PINOCCHIO_ALIGNED_STD_VECTOR(Matrix6x) StdVec_Matrix6x;
StdAlignedVectorPythonVisitor<Vector3,false>::expose("StdVec_vec3d")
StdAlignedVectorPythonVisitor<Vector3,false>::expose("StdVec_Vector3")
.def(details::overload_base_get_item_for_std_vector<StdVec_Vector3>());
StdAlignedVectorPythonVisitor<Matrix6x,false>::expose("StdVec_Matrix6x")
.def(details::overload_base_get_item_for_std_vector<StdVec_Matrix6x>());
StdVectorPythonVisitor<int>::expose("StdVec_int");
StdVectorPythonVisitor<int>::expose("StdVec_Int");
}
};
......
......@@ -315,8 +315,8 @@ namespace pinocchio
StdVectorPythonVisitor<IndexVector>::expose("StdVec_IndexVector");
StdVectorPythonVisitor<std::string>::expose("StdVec_StdString");
StdVectorPythonVisitor<bool>::expose("StdVec_Bool");
StdVectorPythonVisitor<Scalar>::expose("StdVec_double");
bp::class_<typename Model::ConfigVectorMap>("StdMap_String_EigenVectorXd")
StdVectorPythonVisitor<Scalar>::expose("StdVec_Double");
bp::class_<typename Model::ConfigVectorMap>("StdMap_String_VectorXd")
.def(map_indexing_suite())
.def_pickle(PickleMap<typename Model::ConfigVectorMap>())
.def(details::overload_base_get_item_for_std_map<typename Model::ConfigVectorMap>());
......
//
// Copyright (c) 2016-2019 CNRS INRIA
// Copyright (c) 2016-2020 CNRS INRIA
//
#ifndef __pinocchio_python_parser_python_hpp__
......@@ -29,15 +29,24 @@ namespace pinocchio
///
/// \input filename The full path to the model file.
/// \input var_name Name of the Python variable which contains the model in the script.
/// \input verbose Verbosity mode.
///
/// \returns The model constructed by the Python script.
///
// TODO: look inside the context of Python and find an occurence of object Model
PINOCCHIO_PYWRAP_DLLAPI
Model buildModel(const std::string & filename,
const std::string & var_name = "model",
bool verbose = false);
const std::string & var_name = "model");
///
/// \copydoc pinocchio::python::buildModel(const std::string &, const std::string &)
///
PINOCCHIO_DEPRECATED
Model buildModel(const std::string & filename,
const std::string & var_name,
const bool /*verbose*/)
{
return buildModel(filename,var_name);
}
} // namespace python
......
//
// Copyright (c) 2016,2018 CNRS
// Copyright (c) 2016-2020 CNRS INRIA
//
#include "pinocchio/parsers/python.hpp"
......@@ -21,7 +21,7 @@ namespace pinocchio
{
namespace bp = boost::python;
Model buildModel(const std::string & filename, const std::string & model_name, bool verbose)
Model buildModel(const std::string & filename, const std::string & model_name)
{
Py_Initialize();
......@@ -63,11 +63,6 @@ namespace pinocchio
{
PyErr_PrintEx(0);
}
if (verbose)
{
std::cout << "Your model has been built. It has " << model.nv;
std::cout << " degrees of freedom." << std::endl;
}
// close the interpreter
// cf. https://github.com/numpy/numpy/issues/8097
......
......@@ -74,7 +74,7 @@ namespace pinocchio
bp::def("buildSampleModelHumanoidRandom",
static_cast <Model (*) (bool)> (pinocchio::python::buildSampleModelHumanoidRandom),
bp::args("bool (usingFreeFlyer)"),
bp::args("using_free_flyer"),
"Generate a (hard-coded) model of a humanoid robot with 6-DOF limbs and random joint placements.\nOnly meant for unit tests."
);
......@@ -86,7 +86,7 @@ namespace pinocchio
#ifdef PINOCCHIO_WITH_HPP_FCL
bp::def("buildSampleGeometryModelManipulator",
static_cast <GeometryModel (*) (const Model&)> (pinocchio::python::buildSampleGeometryModelManipulator),
bp::args("Model (model)"),
bp::args("model"),
"Generate a (hard-coded) geometry model of a simple manipulator."
);
#endif
......@@ -98,14 +98,14 @@ namespace pinocchio
bp::def("buildSampleModelHumanoid",
static_cast <Model (*) (bool)> (pinocchio::python::buildSampleModelHumanoid),
bp::args("bool (usingFreeFlyer)"),
bp::args("using_free_flyer"),
"Generate a (hard-coded) model of a simple humanoid."
);
#ifdef PINOCCHIO_WITH_HPP_FCL
bp::def("buildSampleGeometryModelHumanoid",
static_cast <GeometryModel (*) (const Model&)> (pinocchio::python::buildSampleGeometryModelHumanoid),
bp::args("Model (model)"),
bp::args("model"),
"Generate a (hard-coded) geometry model of a simple humanoid."
);
#endif
......
//
// Copyright (c) 2019 CNRS
// Copyright (c) 2019-2020 CNRS INRIA
//
#ifndef __pinocchio_python_utils_pickle_map_hpp__
#define __pinocchio_python_utils_pickle_map_hpp__
#include "pinocchio/bindings/python/utils/pickle-vector.hpp"
#include <boost/python.hpp>
#include <boost/python/tuple.hpp>
namespace pinocchio
{
......@@ -15,18 +16,56 @@ namespace pinocchio
///
/// \brief Create a pickle interface for the std::map and aligned map
///
/// \tparam VecType Map Type to pickle
/// \tparam MapType Map Type to pickle
///
/// \sa Pickle
/// \sa PickleVector
///
template<typename VecType>
struct PickleMap : public PickleVector<VecType>
{
template<typename MapType>
struct PickleMap : boost::python::pickle_suite
{
static boost::python::tuple getinitargs(const MapType&)
{
return boost::python::make_tuple();
}
static boost::python::tuple getstate(boost::python::object op)
{
boost::python::extract<const MapType&> get_map(op);
if(get_map.check())
{
const MapType & map = get_map();
boost::python::list list;
for(typename MapType::const_iterator it = map.begin();
it != map.end();
++it)
{
list.append(boost::python::make_tuple(it->first,it->second));
}
return boost::python::make_tuple(list);
}
return boost::python::make_tuple();
}
static void setstate(bp::object op, bp::tuple tup)
{
VecType& o = bp::extract<VecType&>(op)();
bp::stl_input_iterator<typename VecType::value_type> begin(tup[0]), end;
o.insert(begin,end);
typedef typename MapType::key_type key_type;
typedef typename MapType::mapped_type mapped_type;
if(bp::len(tup) > 0)
{
bp::extract<MapType&> get_map(op);
if(get_map.check())
{
MapType & map = get_map();
boost::python::list list = bp::extract<boost::python::list>(tup[0])();
for(boost::python::ssize_t k = 0; k < boost::python::len(list); ++k)
{
boost::python::tuple entry = bp::extract<boost::python::tuple>(list[k])();
key_type key = bp::extract<key_type>(entry[0])();
map[key] = bp::extract<mapped_type>(entry[1])();
}
}
}
}
};
}
......
......@@ -18,8 +18,6 @@ namespace pinocchio
///
/// \tparam VecType Vector Type to pickle
///
/// \sa Pickle
///
template<typename VecType>
struct PickleVector : boost::python::pickle_suite
{
......@@ -33,9 +31,12 @@ namespace pinocchio
static void setstate(boost::python::object op, boost::python::tuple tup)
{
VecType & o = boost::python::extract<VecType&>(op)();
boost::python::stl_input_iterator<typename VecType::value_type> begin(tup[0]), end;
o.insert(o.begin(),begin,end);
if(boost::python::len(tup) > 0)
{
VecType & o = boost::python::extract<VecType&>(op)();
boost::python::stl_input_iterator<typename VecType::value_type> begin(tup[0]), end;
o.insert(o.begin(),begin,end);
}
}
};
}
......
......@@ -370,6 +370,18 @@ BOOST_AUTO_TEST_CASE(test_buildReducedModel)
}
}
BOOST_AUTO_TEST_CASE(test_aligned_vector_of_model)
{
typedef PINOCCHIO_ALIGNED_STD_VECTOR(Model) VectorOfModels;
VectorOfModels models;
for(size_t k = 0; k < 100; ++k)
{
models.push_back(Model());
buildModels::humanoidRandom(models[k]);
}
}
#ifdef PINOCCHIO_WITH_HPP_FCL
BOOST_AUTO_TEST_CASE(test_buildReducedModel_with_geom)
{
......
......@@ -39,9 +39,15 @@ SET(${PROJECT_NAME}_PYTHON_TESTS
bindings_centroidal_dynamics_derivatives
bindings_com_velocity_derivatives
# Parsers
bindings_sample_models
# Others
utils
serialization
version
bindings_std_vector
bindings_std_map
)
IF(hpp-fcl_FOUND)
......@@ -57,13 +63,13 @@ IF(hpp-fcl_FOUND)
ENDIF(BUILD_WITH_HPP_FCL_PYTHON_BINDINGS)
ENDIF(hpp-fcl_FOUND)
IF(URDFDOM_FOUND)
IF(urdfdom_FOUND)
SET(${PROJECT_NAME}_PYTHON_TESTS
${${PROJECT_NAME}_PYTHON_TESTS}
bindings_urdf
bindings_geometry_model_urdf
)
ENDIF(URDFDOM_FOUND)
ENDIF(urdfdom_FOUND)
FOREACH(TEST ${${PROJECT_NAME}_PYTHON_TESTS})
ADD_PYTHON_UNIT_TEST("test-py-${TEST}" "unittest/python/${TEST}.py" "bindings/python")
......
......@@ -21,7 +21,7 @@ class TestGeometryObjectUrdfBindings(unittest.TestCase):
collision_model = pin.buildGeomFromUrdf(model, self.model_path, pin.GeometryType.COLLISION, hint_list)
col = collision_model.geometryObjects[1]
self.assertEqual(col.meshPath, expected_mesh_path)
self.assertEqual(os.path.normpath(col.meshPath), os.path.normpath(expected_mesh_path))
def test_self_load(self):
hint_list = [self.model_dir]
......@@ -54,35 +54,35 @@ class TestGeometryObjectUrdfBindings(unittest.TestCase):
collision_model = pin.buildGeomFromUrdf(model, self.model_path, pin.GeometryType.COLLISION, hint_list)
col = collision_model.geometryObjects[1]
self.assertEqual(col.meshPath, expected_collision_path)
self.assertEqual(os.path.normpath(col.meshPath), os.path.normpath(expected_collision_path))
visual_model = pin.buildGeomFromUrdf(model, self.model_path, pin.GeometryType.VISUAL, hint_list)
vis = visual_model.geometryObjects[1]
self.assertEqual(vis.meshPath, expected_visual_path)
self.assertEqual(os.path.normpath(vis.meshPath), os.path.normpath(expected_visual_path))
model_2, collision_model_2, visual_model_2 = pin.buildModelsFromUrdf(self.model_path, hint_list, pin.JointModelFreeFlyer())
self.assertEqual(model,model_2)
col_2 = collision_model_2.geometryObjects[1]
self.assertEqual(col_2.meshPath, expected_collision_path)
self.assertEqual(os.path.normpath(col_2.meshPath), os.path.normpath(expected_collision_path))
vis_2 = visual_model_2.geometryObjects[1]
self.assertEqual(vis_2.meshPath, expected_visual_path)
self.assertEqual(os.path.normpath(vis_2.meshPath), os.path.normpath(expected_visual_path))
model_c, collision_model_c = pin.buildModelsFromUrdf(self.model_path, hint_list, pin.JointModelFreeFlyer(), geometry_types=pin.GeometryType.COLLISION)
self.assertEqual(model,model_c)
col_c = collision_model_c.geometryObjects[1]
self.assertEqual(col_c.meshPath, expected_collision_path)
self.assertEqual(os.path.normpath(col_c.meshPath), os.path.normpath(expected_collision_path))
model_v, visual_model_v = pin.buildModelsFromUrdf(self.model_path, hint_list, pin.JointModelFreeFlyer(), geometry_types=pin.GeometryType.VISUAL)
self.assertEqual(model,model_v)
vis_v = visual_model_v.geometryObjects[1]
self.assertEqual(vis_v.meshPath, expected_visual_path)
self.assertEqual(os.path.normpath(vis_v.meshPath), os.path.normpath(expected_visual_path))
def test_deprecated_signatures(self):
model = pin.buildModelFromUrdf(self.model_path, pin.JointModelFreeFlyer())
......
import unittest
from test_case import PinocchioTestCase as TestCase
import pinocchio as pin
class TestSampleModels(TestCase):
def setUp(self):
pass
def test_all_sampled_models(self):
huamnoid_1 = pin.buildSampleModelHumanoidRandom()
huamnoid_2 = pin.buildSampleModelHumanoidRandom(True)
huamnoid_3 = pin.buildSampleModelHumanoidRandom(False)
self.assertTrue(huamnoid_1 != huamnoid_2)
self.assertTrue(huamnoid_1 != huamnoid_3)
manipulator_1 = pin.buildSampleModelManipulator()
if pin.WITH_HPP_FCL:
geometry_manipulator_1 = pin.buildSampleGeometryModelManipulator(manipulator_1)
humanoid_4 = pin.buildSampleModelHumanoid()
humanoid_5 = pin.buildSampleModelHumanoid(True)
humanoid_6 = pin.buildSampleModelHumanoid(False)
self.assertTrue(humanoid_4 == humanoid_5)
self.assertTrue(humanoid_4 != humanoid_6)
if pin.WITH_HPP_FCL:
geometry_humanoid_2 = pin.buildSampleGeometryModelHumanoid(humanoid_4)
if __name__ == '__main__':
unittest.main()
import unittest
from test_case import PinocchioTestCase as TestCase
import pinocchio as pin
import numpy as np
import pickle
class TestStdMap(TestCase):
def setUp(self):
pass
def test_pickle(self):
map = pin.StdMap_String_VectorXd()
keys = []
for k in range(100):
key_name = 'key_' + str(k+1)
keys.append(key_name)
map[key_name] = np.random.rand((10))
pickle.dump( map, open( "save_std_map.p", "wb" ) )
map_loaded = pickle.load( open( "save_std_map.p", "rb" ) )
for key in keys:
self.assertApprox(map[key],map_loaded[key])
if __name__ == '__main__':
unittest.main()
import unittest
from test_case import PinocchioTestCase as TestCase
import pinocchio as pin
import numpy as np
import pickle
class TestStdMap(TestCase):
def setUp(self):
pass
def test_pickle(self):
vec = pin.StdVec_Vector3()
for k in range(100):
vec.append(np.random.rand((3)))
pickle.dump( vec, open( "save_std_vec.p", "wb" ) )
vec_loaded = pickle.load( open( "save_std_vec.p", "rb" ) )
for k in range(len(vec)):
self.assertApprox(vec[k],vec_loaded[k])
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment