// // Copyright (c) 2019 INRIA // #include "pinocchio/algorithm/joint-configuration.hpp" #include "pinocchio/serialization/archive.hpp" #include "pinocchio/serialization/eigen.hpp" #include "pinocchio/serialization/spatial.hpp" #include "pinocchio/serialization/frame.hpp" #include "pinocchio/serialization/joints.hpp" #include "pinocchio/serialization/model.hpp" #include "pinocchio/parsers/sample-models.hpp" #include #include #include BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE) template struct call_equality_op { static bool run(const T1 & v1, const T2 & v2) { return v1 == v2; } }; template bool run_call_equality_op(const T & v1, const T & v2) { return call_equality_op::run(v1,v2); } // Bug fix in Eigen::Tensor #ifdef PINOCCHIO_WITH_EIGEN_TENSOR_MODULE template struct call_equality_op< pinocchio::Tensor > { typedef pinocchio::Tensor T; static bool run(const T & v1, const T & v2) { typedef Eigen::Matrix VectorXd; Eigen::Map map1(v1.data(),v1.size(),1); Eigen::Map map2(v2.data(),v2.size(),1); return map1 == map2; } }; #endif template void generic_test(const T & object, const std::string & filename, const std::string & tag_name) { using namespace pinocchio::serialization; // Load and save as TXT const std::string txt_filename = filename + ".txt"; saveToText(object,txt_filename); { T object_loaded; loadFromText(object_loaded,txt_filename); // Check BOOST_CHECK(run_call_equality_op(object_loaded,object)); } // Load and save as string stream std::stringstream ss_out; saveToStringStream(object,ss_out); { T object_loaded; std::istringstream is(ss_out.str()); loadFromStringStream(object_loaded,is); // Check BOOST_CHECK(run_call_equality_op(object_loaded,object)); } // Load and save as string std::string str_out = saveToString(object); { T object_loaded; std::string str_in(str_out); loadFromString(object_loaded,str_in); // Check BOOST_CHECK(run_call_equality_op(object_loaded,object)); } // Load and save as XML const std::string xml_filename = filename + ".xml"; saveToXML(object,xml_filename,tag_name); { T object_loaded; loadFromXML(object_loaded,xml_filename,tag_name); // Check BOOST_CHECK(run_call_equality_op(object_loaded,object)); } // Load and save as binary const std::string bin_filename = filename + ".bin"; saveToBinary(object,bin_filename); { T object_loaded; loadFromBinary(object_loaded,bin_filename); // Check BOOST_CHECK(run_call_equality_op(object_loaded,object)); } } BOOST_AUTO_TEST_CASE(test_eigen_serialization) { using namespace pinocchio; const Eigen::DenseIndex num_cols = 10; const Eigen::DenseIndex num_rows = 20; const Eigen::DenseIndex array_size = 3; Eigen::MatrixXd Mat = Eigen::MatrixXd::Random(num_rows,num_cols); generic_test(Mat,TEST_SERIALIZATION_FOLDER"/eigen_matrix","matrix"); Eigen::VectorXd Vec = Eigen::VectorXd::Random(num_rows*num_cols); generic_test(Vec,TEST_SERIALIZATION_FOLDER"/eigen_vector","vector"); Eigen::array array = { 1, 2, 3 }; generic_test(array,TEST_SERIALIZATION_FOLDER"/eigen_array","array"); const Eigen::DenseIndex tensor_size = 3; const Eigen::DenseIndex x_dim = 10, y_dim = 20, z_dim = 30; typedef pinocchio::Tensor Tensor3x; Tensor3x tensor(x_dim,y_dim,z_dim); Eigen::Map(tensor.data(),tensor.size(),1).setRandom(); generic_test(tensor,TEST_SERIALIZATION_FOLDER"/eigen_tensor","tensor"); } BOOST_AUTO_TEST_CASE(test_spatial_serialization) { using namespace pinocchio; SE3 M(SE3::Random()); generic_test(M,TEST_SERIALIZATION_FOLDER"/SE3","SE3"); Motion m(Motion::Random()); generic_test(m,TEST_SERIALIZATION_FOLDER"/Motion","Motion"); Force f(Force::Random()); generic_test(f,TEST_SERIALIZATION_FOLDER"/Force","Force"); Symmetric3 S(Symmetric3::Random()); generic_test(S,TEST_SERIALIZATION_FOLDER"/Symmetric3","Symmetric3"); Inertia I(Inertia::Random()); generic_test(I,TEST_SERIALIZATION_FOLDER"/Inertia","Inertia"); } BOOST_AUTO_TEST_CASE(test_multibody_serialization) { using namespace pinocchio; Frame frame("frame",0,0,SE3::Random(),SENSOR); generic_test(frame,TEST_SERIALIZATION_FOLDER"/Frame","Frame"); } template struct init; template struct init { static JointModel_ run() { JointModel_ jmodel; jmodel.setIndexes(0,0,0); return jmodel; } }; template struct init > { typedef pinocchio::JointModelRevoluteUnalignedTpl JointModel; static JointModel run() { typedef typename JointModel::Vector3 Vector3; JointModel jmodel(Vector3::Random().normalized()); jmodel.setIndexes(0,0,0); return jmodel; } }; template struct init > { typedef pinocchio::JointModelRevoluteUnboundedUnalignedTpl JointModel; static JointModel run() { typedef typename JointModel::Vector3 Vector3; JointModel jmodel(Vector3::Random().normalized()); jmodel.setIndexes(0,0,0); return jmodel; } }; template struct init > { typedef pinocchio::JointModelPrismaticUnalignedTpl JointModel; static JointModel run() { typedef typename JointModel::Vector3 Vector3; JointModel jmodel(Vector3::Random().normalized()); jmodel.setIndexes(0,0,0); return jmodel; } }; template class JointCollection> struct init > { typedef pinocchio::JointModelTpl JointModel; static JointModel run() { typedef pinocchio::JointModelRevoluteTpl JointModelRX; JointModel jmodel((JointModelRX())); jmodel.setIndexes(0,0,0); return jmodel; } }; template class JointCollection> struct init > { typedef pinocchio::JointModelCompositeTpl JointModel; static JointModel run() { typedef pinocchio::JointModelRevoluteTpl JointModelRX; typedef pinocchio::JointModelRevoluteTpl JointModelRY; JointModel jmodel((JointModelRX())); jmodel.addJoint(JointModelRY()); jmodel.setIndexes(0,0,0); return jmodel; } }; template struct init > { typedef pinocchio::JointModelMimic JointModel; static JointModel run() { JointModel_ jmodel_ref = init::run(); JointModel jmodel(jmodel_ref,1.,0.); return jmodel; } }; struct TestJointModel { template void operator()(const pinocchio::JointModelBase &) const { JointModel jmodel = init::run(); test(jmodel); } template static void test(JointType & jmodel) { generic_test(jmodel,TEST_SERIALIZATION_FOLDER"/Joint","jmodel"); } }; BOOST_AUTO_TEST_CASE(test_multibody_joints_model_serialization) { using namespace pinocchio; boost::mpl::for_each(TestJointModel()); } struct TestJointTransform { template void operator()(const pinocchio::JointModelBase &) const { typedef typename JointModel::JointDerived JointDerived; typedef typename pinocchio::traits::Transformation_t Transform; typedef typename pinocchio::traits::JointDataDerived JointData; typedef pinocchio::JointDataBase JointDataBase; JointModel jmodel = init::run(); JointData jdata = jmodel.createData(); JointDataBase & jdata_base = static_cast(jdata); typedef typename pinocchio::LieGroup::type LieGroupType; LieGroupType lg; Eigen::VectorXd lb(Eigen::VectorXd::Constant(jmodel.nq(),-1.)); Eigen::VectorXd ub(Eigen::VectorXd::Constant(jmodel.nq(), 1.)); Eigen::VectorXd q_random = lg.randomConfiguration(lb,ub); jmodel.calc(jdata,q_random); Transform & m = jdata_base.M(); test(m); } template class JointCollectionTpl> void operator()(const pinocchio::JointModelCompositeTpl &) { // Do nothing } template void operator()(const pinocchio::JointModelMimic &) { typedef pinocchio::JointModelMimic JointModelMimic; typedef typename JointModelMimic::JointDerived JointDerived; typedef typename pinocchio::traits::Transformation_t Transform; typedef typename pinocchio::traits::JointDataDerived JointDataMimic; typedef pinocchio::JointDataBase JointDataBase; JointModelMimic jmodel_mimic = init::run(); JointModel jmodel = init::run(); JointDataMimic jdata_mimic = jmodel_mimic.createData(); JointDataBase & jdata_mimic_base = static_cast(jdata_mimic); typedef typename pinocchio::LieGroup::type LieGroupType; LieGroupType lg; Eigen::VectorXd lb(Eigen::VectorXd::Constant(jmodel.nq(),-1.)); Eigen::VectorXd ub(Eigen::VectorXd::Constant(jmodel.nq(), 1.)); Eigen::VectorXd q_random = lg.randomConfiguration(lb,ub); jmodel_mimic.calc(jdata_mimic,q_random); Transform & m = jdata_mimic_base.M(); test(m); } template static void test(Transform & m) { generic_test(m,TEST_SERIALIZATION_FOLDER"/JointTransform","transform"); } }; BOOST_AUTO_TEST_CASE(test_multibody_joints_transform_serialization) { using namespace pinocchio; boost::mpl::for_each(TestJointTransform()); } struct TestJointMotion { template void operator()(const pinocchio::JointModelBase &) const { typedef typename JointModel::JointDerived JointDerived; typedef typename pinocchio::traits::Motion_t Motion; typedef typename pinocchio::traits::Bias_t Bias; typedef typename pinocchio::traits::JointDataDerived JointData; typedef pinocchio::JointDataBase JointDataBase; JointModel jmodel = init::run(); JointData jdata = jmodel.createData(); JointDataBase & jdata_base = static_cast(jdata); typedef typename pinocchio::LieGroup::type LieGroupType; LieGroupType lg; Eigen::VectorXd lb(Eigen::VectorXd::Constant(jmodel.nq(),-1.)); Eigen::VectorXd ub(Eigen::VectorXd::Constant(jmodel.nq(), 1.)); Eigen::VectorXd q_random = lg.randomConfiguration(lb,ub); Eigen::VectorXd v_random = Eigen::VectorXd::Random(jmodel.nv()); jmodel.calc(jdata,q_random,v_random); Motion & m = jdata_base.v(); test(m); Bias & b = jdata_base.c(); test(b); } template class JointCollectionTpl> void operator()(const pinocchio::JointModelCompositeTpl &) { // Do nothing } template void operator()(const pinocchio::JointModelMimic &) { typedef pinocchio::JointModelMimic JointModelMimic; typedef typename JointModelMimic::JointDerived JointDerived; typedef typename pinocchio::traits::Motion_t Motion; typedef typename pinocchio::traits::Bias_t Bias; typedef typename pinocchio::traits::JointDataDerived JointDataMimic; typedef pinocchio::JointDataBase JointDataBase; JointModelMimic jmodel_mimic = init::run(); JointModel jmodel = init::run(); JointDataMimic jdata_mimic = jmodel_mimic.createData(); JointDataBase & jdata_mimic_base = static_cast(jdata_mimic); typedef typename pinocchio::LieGroup::type LieGroupType; LieGroupType lg; Eigen::VectorXd lb(Eigen::VectorXd::Constant(jmodel.nq(),-1.)); Eigen::VectorXd ub(Eigen::VectorXd::Constant(jmodel.nq(), 1.)); Eigen::VectorXd q_random = lg.randomConfiguration(lb,ub); Eigen::VectorXd v_random = Eigen::VectorXd::Random(jmodel.nv()); jmodel_mimic.calc(jdata_mimic,q_random,v_random); Motion & m = jdata_mimic_base.v(); test(m); Bias & b = jdata_mimic_base.c(); test(b); } template static void test(Motion & m) { generic_test(m,TEST_SERIALIZATION_FOLDER"/JointMotion","motion"); } }; BOOST_AUTO_TEST_CASE(test_multibody_joints_motion_serialization) { using namespace pinocchio; boost::mpl::for_each(TestJointMotion()); } BOOST_AUTO_TEST_CASE(test_model_serialization) { using namespace pinocchio; Model model; buildModels::humanoidRandom(model); generic_test(model,TEST_SERIALIZATION_FOLDER"/Model","Model"); } BOOST_AUTO_TEST_CASE(test_throw_extension) { using namespace pinocchio; Model model; buildModels::humanoidRandom(model); const std::string & fake_filename = "this_is_a_fake_filename"; { const std::string complete_filename = fake_filename + ".txt"; BOOST_REQUIRE_THROW(loadFromText(model,complete_filename), std::invalid_argument); } saveToText(model,TEST_SERIALIZATION_FOLDER"/model.txt"); saveToXML(model,TEST_SERIALIZATION_FOLDER"/model.xml","model"); saveToBinary(model,TEST_SERIALIZATION_FOLDER"/model.bin"); { const std::string complete_filename = fake_filename + ".txte"; BOOST_REQUIRE_THROW(loadFromText(model,complete_filename), std::invalid_argument); } { const std::string complete_filename = fake_filename + ".xmle"; BOOST_REQUIRE_THROW(loadFromXML(model,complete_filename,"model"), std::invalid_argument); } { const std::string complete_filename = fake_filename + ".bine"; BOOST_REQUIRE_THROW(loadFromBinary(model,complete_filename), std::invalid_argument); } } BOOST_AUTO_TEST_SUITE_END()