Skip to content
Snippets Groups Projects
Commit ee5f5558 authored by Jeremie Deray's avatar Jeremie Deray
Browse files

partial eigen type serialization (bin only)

parent 4eb3bdf5
No related branches found
No related tags found
1 merge request!141Serialization
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(HDRS_SERIALIZATION ${HDRS_SERIALIZATION}
${CMAKE_CURRENT_SOURCE_DIR}/serialization_eigen_core.h
${CMAKE_CURRENT_SOURCE_DIR}/serialization_eigen_geometry.h
${CMAKE_CURRENT_SOURCE_DIR}/serialization_eigen_sparse.h
${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_base.h
${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_homogeneous.h
${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_quaternion.h
......
#ifndef _WOLF_IO_CEREAL_EIGEN_H_
#define _WOLF_IO_CEREAL_EIGEN_H_
// Wolf includes
#include <Eigen/Dense>
#include <cereal/cereal.hpp>
namespace cereal {
/**
* @brief Save Eigen::Matrix<...> to text based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<!traits::is_output_serializable<BinaryData<_Scalar>, Archive>::value,
void>::type save(Archive& ar,
const Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows = mat.rows();
decltype(mat.cols()) cols = mat.cols();
ar(cereal::make_nvp("rows", rows));
ar(cereal::make_nvp("cols", cols));
/// @todo find out something
std::cerr << "Saving Eigen type to text-based archive is NOT supported !\n";
}
/**
* @brief Save Eigen::Matrix<...> to binary based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<traits::is_output_serializable<BinaryData<_Scalar>, Archive>::value,
void>::type save(Archive& ar,
const Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows = mat.rows();
decltype(mat.cols()) cols = mat.cols();
ar(rows);
ar(cols);
ar(binary_data(mat.data(), static_cast<std::size_t>(rows * cols * sizeof(_Scalar))));
}
/**
* @brief Load compile-time sized Eigen::Matrix from text based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<!traits::is_input_serializable<BinaryData<_Scalar>, Archive>::value and
_Rows != Eigen::Dynamic and _Cols != Eigen::Dynamic,
void>::type load(Archive& ar,
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows;
decltype(mat.cols()) cols;
ar(cereal::make_nvp("rows", rows));
ar(cereal::make_nvp("cols", cols));
/// @todo find out something
std::cerr << "Saving Eigen type to text-based archive is NOT supported !\n";
}
/**
* @brief Load dynamic sized Eigen::Matrix from text based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<!traits::is_input_serializable<BinaryData<_Scalar>, Archive>::value and
(_Rows == Eigen::Dynamic or _Cols == Eigen::Dynamic),
void>::type load(Archive& ar,
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows;
decltype(mat.cols()) cols;
ar(cereal::make_nvp("rows", rows));
ar(cereal::make_nvp("cols", cols));
/// @todo find out something
std::cerr << "Saving Eigen type to text-based archive is NOT supported !\n";
//mat.resize(rows, cols);
}
/**
* @brief Load compile-time sized Eigen::Matrix from binary based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<traits::is_input_serializable<BinaryData<_Scalar>, Archive>::value and
_Rows != Eigen::Dynamic and _Cols != Eigen::Dynamic,
void>::type load(Archive& ar,
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows;
decltype(mat.cols()) cols;
ar(rows);
ar(cols);
ar(binary_data(mat.data(), static_cast<std::size_t>(rows * cols * sizeof(_Scalar))));
}
/**
* @brief Load dynamic sized Eigen::Matrix from binary based archives
*/
template<class Archive, typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline typename std::enable_if<traits::is_input_serializable<BinaryData<_Scalar>, Archive>::value and
(_Rows == Eigen::Dynamic or _Cols == Eigen::Dynamic),
void>::type load(Archive& ar,
Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& mat)
{
decltype(mat.rows()) rows;
decltype(mat.cols()) cols;
ar(rows);
ar(cols);
mat.resize(rows, cols);
ar(binary_data(mat.data(), static_cast<std::size_t>(rows * cols * sizeof(_Scalar))));
}
} // namespace cereal
#endif /* _WOLF_IO_CEREAL_EIGEN_H_ */
#ifndef _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_
#define _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_
// Wolf includes
#include <Eigen/Geometry>
#include "serialization_eigen_core.h"
namespace cereal {
template<class Archive, typename _Scalar, int _Dim, int _Mode, int _Options>
inline void save(Archive& ar,
const Eigen::Transform<_Scalar, _Dim, _Mode, _Options>& t)
{
save(ar, t.matrix());
}
template<class Archive, typename _Scalar, int _Dim, int _Mode, int _Options>
inline void load(Archive& ar,
Eigen::Transform<_Scalar, _Dim, _Mode, _Options>& t)
{
load(ar, t.matrix());
}
template<class Archive, typename _Scalar>
void serialize(Archive & ar,
Eigen::Quaternion<_Scalar>& q,
const std::uint32_t /*version*/)
{
ar(cereal::make_nvp("w", q.w()));
ar(cereal::make_nvp("x", q.x()));
ar(cereal::make_nvp("y", q.y()));
ar(cereal::make_nvp("z", q.z()));
}
} // namespace cereal
#endif /* _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_ */
#ifndef _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_
#define _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_
// Wolf includes
#include <Eigen/Sparse>
#include "serialization_eigen_core.h"
#include <cereal/types/vector.hpp>
namespace cereal {
template<class Archive, typename Scalar, typename Index>
inline void save(Archive& ar,
const Eigen::Triplet<Scalar, Index>& t)
{
ar(cereal::make_nvp("row", t.row()));
ar(cereal::make_nvp("col", t.col()));
ar(cereal::make_nvp("value", t.value()));
}
template<class Archive, typename Scalar, typename Index>
inline void load(Archive& ar,
Eigen::Triplet<Scalar, Index>& t)
{
Index row, col;
Scalar value;
ar(cereal::make_nvp("row", row));
ar(cereal::make_nvp("col", col));
ar(cereal::make_nvp("value", value));
t = Eigen::Triplet<Scalar, Index>(row, col, value);
}
template <class Archive, typename _Scalar, int _Options, typename _Index>
void save(Archive& ar,
const Eigen::SparseMatrix<_Scalar, _Options, _Index>& m)
{
_Index inner_size = m.innerSize();
_Index outer_size = m.outerSize();
using Triplet = Eigen::Triplet<_Scalar>;
std::vector<Triplet> triplets;
for (_Index i=0; i < outer_size; ++i)
for (typename Eigen::SparseMatrix<_Scalar, _Options, _Index>::InnerIterator it(m,i); it; ++it)
triplets.emplace_back( it.row(), it.col(), it.value() );
ar(cereal::make_nvp("inner_size", inner_size));
ar(cereal::make_nvp("outer_size", outer_size));
ar(cereal::make_nvp("triplets", triplets));
}
template <class Archive, typename _Scalar, int _Options, typename _Index>
void load(Archive& ar,
Eigen::SparseMatrix<_Scalar, _Options, _Index>& m)
{
_Index inner_size;
_Index outer_size;
ar(cereal::make_nvp("inner_size", inner_size));
ar(cereal::make_nvp("outer_size", outer_size));
_Index rows = (m.IsRowMajor)? outer_size : inner_size;
_Index cols = (m.IsRowMajor)? inner_size : outer_size;
m.resize(rows, cols);
using Triplet = Eigen::Triplet<_Scalar>;
std::vector<Triplet> triplets;
ar(cereal::make_nvp("triplets", triplets));
m.setFromTriplets(triplets.begin(), triplets.end());
}
} // namespace cereal
#endif /* _WOLF_IO_CEREAL_EIGEN_GEOMETRY_H_ */
......@@ -29,3 +29,15 @@ target_link_libraries(gtest_cereal_serialization_processor_odom2d_params ${PROJE
wolf_add_gtest(gtest_cereal_serialization_time_stamp
gtest_serialization_time_stamp.cpp)
target_link_libraries(gtest_cereal_serialization_time_stamp ${PROJECT_NAME})
wolf_add_gtest(gtest_cereal_serialization_eigen_core
gtest_serialization_eigen_core.cpp)
target_link_libraries(gtest_cereal_serialization_eigen_core ${PROJECT_NAME})
wolf_add_gtest(gtest_cereal_serialization_eigen_geometry
gtest_serialization_eigen_geometry.cpp)
target_link_libraries(gtest_cereal_serialization_eigen_geometry ${PROJECT_NAME})
wolf_add_gtest(gtest_cereal_serialization_eigen_sparse
gtest_serialization_eigen_sparse.cpp)
target_link_libraries(gtest_cereal_serialization_eigen_sparse ${PROJECT_NAME})
/*
* gtest_intrinsics_odom2d_serialization.cpp
*
* Created on: Jul 16, 2017
* Author: Jeremie Deray
*/
#include "../../utils_gtest.h"
#include "../../../serialization/cereal/serialization_eigen_core.h"
#include "../../../serialization/cereal/io.h"
#include <cereal/types/memory.hpp>
#include <fstream>
class WolfTestCerealSerializationEigen : public testing::Test
{
public:
WolfTestCerealSerializationEigen()
{
nb_ = f_mat_t::Random();
dnb_ = d_mat_t::Random(10, 10);
}
const std::string path_to_io = "/tmp/";
const std::string filename = "serialization_eigen";
const std::vector<std::string> exts = {".bin"/*, ".xml", ".json"*/};
using f_mat_t = Eigen::Matrix<double, 5, 5>;
using d_mat_t = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
f_mat_t nb_;
d_mat_t dnb_;
};
TEST_F(WolfTestCerealSerializationEigen,
CerealSerializationEigenFixedMat)
{
for (const auto ext : exts)
{
const std::string full_path = path_to_io + filename + ext;
ASSERT_NO_THROW( wolf::save( full_path, nb_ ) )
<< "Failed on saving " << full_path;
WolfTestCerealSerializationEigen::f_mat_t nb_load;
ASSERT_NO_THROW( wolf::load( full_path, nb_load ) )
<< "Failed on loading " << full_path;
EXPECT_EQ(nb_load, nb_) << full_path;
}
PRINTF("All good at "
"WolfTestCerealSerializationEigen::"
"CerealSerializationEigenFixedMat !\n");
}
TEST_F(WolfTestCerealSerializationEigen,
CerealSerializationEigenDynamicMat)
{
for (const auto ext : exts)
{
const std::string full_path = path_to_io + filename + ext;
ASSERT_NO_THROW( wolf::save( full_path, dnb_ ) )
<< "Failed on saving " << full_path;
WolfTestCerealSerializationEigen::d_mat_t dnb_load;
ASSERT_NO_THROW( wolf::load( full_path, dnb_load ) )
<< "Failed on loading " << full_path;
EXPECT_EQ(dnb_load, dnb_) << full_path;
}
PRINTF("All good at "
"WolfTestCerealSerializationEigen::"
"CerealSerializationEigenDynamicMat !\n");
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
/*
* gtest_intrinsics_odom2d_serialization.cpp
*
* Created on: Jul 16, 2017
* Author: Jeremie Deray
*/
#include "../../../wolf.h"
#include "../../utils_gtest.h"
#include "../../../serialization/cereal/serialization_eigen_geometry.h"
#include "../../../serialization/cereal/io.h"
#include <cereal/types/memory.hpp>
#include <fstream>
class WolfTestCerealSerializationEigenGeo : public testing::Test
{
public:
WolfTestCerealSerializationEigenGeo()
{
iso_2d_ = Eigen::Isometry2d(Eigen::Rotation2Dd(0.17));
iso_2d_.translation() << 0.5, 1.8;
q_d_ = Eigen::Vector4d().setRandom().normalized();
iso_3d_ = Eigen::Isometry3d(q_d_);
iso_3d_.translation() << -7.245, +3.88, 0.0001;
}
const std::string path_to_io = "/tmp/";
const std::string filename = "serialization_eigen_geo";
const std::vector<std::string> exts = {".bin"/*, ".xml", ".json"*/};
Eigen::Isometry2d iso_2d_;
Eigen::Isometry3d iso_3d_;
Eigen::Quaterniond q_d_;
};
TEST_F(WolfTestCerealSerializationEigenGeo,
CerealSerializationEigenIso2d)
{
for (const auto ext : exts)
{
const std::string full_path = path_to_io + filename + ext;
ASSERT_NO_THROW( wolf::save( full_path, iso_2d_, iso_3d_, q_d_) )
<< "Failed on saving " << full_path;
Eigen::Isometry2d iso_2d_loaded;
Eigen::Isometry3d iso_3d_loaded;
Eigen::Quaterniond q_d_loaded;
ASSERT_NO_THROW( wolf::load( full_path, iso_2d_loaded, iso_3d_loaded, q_d_loaded) )
<< "Failed on loading " << full_path;
ASSERT_MATRIX_APPROX(iso_2d_.matrix(), iso_2d_loaded.matrix(), wolf::Constants::EPS);
ASSERT_MATRIX_APPROX(iso_3d_.matrix(), iso_3d_loaded.matrix(), wolf::Constants::EPS);
ASSERT_MATRIX_APPROX(q_d_.coeffs(), q_d_loaded.coeffs(), wolf::Constants::EPS);
}
PRINT_TEST_FINISHED;
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
/*
* gtest_intrinsics_odom2d_serialization.cpp
*
* Created on: Jul 16, 2017
* Author: Jeremie Deray
*/
#include "../../../wolf.h"
#include "../../utils_gtest.h"
#include "../../../serialization/cereal/serialization_eigen_sparse.h"
#include "../../../serialization/cereal/io.h"
#include <cereal/types/memory.hpp>
#include <fstream>
class WolfTestCerealSerializationEigenSparse : public testing::Test
{
public:
using triplet_t = Eigen::Triplet<double>;
using sparse_mat_t = Eigen::SparseMatrix<double>;
WolfTestCerealSerializationEigenSparse()
{
triplet_list_.reserve(10);
for(int i=0; i<10; ++i)
triplet_list_.emplace_back(i,i,i*5);
m_.resize(10, 10);
m_.setFromTriplets(triplet_list_.begin(), triplet_list_.end());
}
const std::string path_to_io = "/tmp/";
const std::string filename_t = "serialization_eigen_triplet";
const std::string filename_m = "serialization_eigen_sparse";
const std::vector<std::string> exts = {".bin", ".xml", ".json"};
triplet_t t_ = Eigen::Triplet<double>(1, 2, 5.5);
std::vector<triplet_t> triplet_list_;
Eigen::SparseMatrix<double> m_;
};
TEST_F(WolfTestCerealSerializationEigenSparse,
CerealSerializationEigenTriplet)
{
for (const auto ext : exts)
{
const std::string full_path = path_to_io + filename_t + ext;
ASSERT_NO_THROW( wolf::save( full_path, t_) )
<< "Failed on saving " << full_path;
triplet_t t;
ASSERT_NO_THROW( wolf::load( full_path, t) )
<< "Failed on loading " << full_path;
ASSERT_EQ(t_.row(), t.row());
ASSERT_EQ(t_.col(), t.col());
ASSERT_EQ(t_.value(), t.value());
}
PRINT_TEST_FINISHED;
}
TEST_F(WolfTestCerealSerializationEigenSparse,
CerealSerializationEigenSparseMatrix)
{
for (const auto ext : exts)
{
const std::string full_path = path_to_io + filename_m + ext;
ASSERT_NO_THROW( wolf::save( full_path, m_) )
<< "Failed on saving " << full_path;
sparse_mat_t m;
ASSERT_NO_THROW( wolf::load( full_path, m) )
<< "Failed on loading " << full_path;
ASSERT_EQ(m_.rows(), m.rows());
ASSERT_EQ(m_.cols(), m.cols());
std::vector<triplet_t> triplet_list;
triplet_list.reserve(10);
for (int k=0; k<m.outerSize(); ++k)
for (sparse_mat_t::InnerIterator it(m, k); it; ++it)
{
triplet_list.emplace_back(it.row(), it.col(), it.value());
}
ASSERT_EQ(triplet_list_.size(), triplet_list.size());
for (int i=0; i<triplet_list_.size(); ++i)
{
ASSERT_EQ(triplet_list_[i].row(), triplet_list[i].row());
ASSERT_EQ(triplet_list_[i].col(), triplet_list[i].col());
ASSERT_EQ(triplet_list_[i].value(), triplet_list[i].value());
}
}
PRINT_TEST_FINISHED;
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment