Created
October 6, 2020 06:50
-
-
Save jlblancoc/cddd4a431ba676f2dfe09cb9d13b25a0 to your computer and use it in GitHub Desktop.
GTSAM factor graph serialization example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/archive/binary_iarchive.hpp> | |
#include <boost/archive/binary_oarchive.hpp> | |
#include <boost/archive/text_iarchive.hpp> | |
#include <boost/archive/text_oarchive.hpp> | |
#include <fstream> | |
#include <gtsam/base/serialization.h> | |
// ... Includes for your values and factors: | |
#include <gtsam/base/GenericValue.h> // GTSAM_VALUE_EXPORT | |
#include <gtsam/geometry/Pose2.h> | |
#include <gtsam/geometry/Pose3.h> | |
#include <gtsam/linear/NoiseModel.h> | |
#include <gtsam/nonlinear/ExpressionFactor.h> | |
#include <gtsam/nonlinear/NonlinearFactorGraph.h> | |
#include <gtsam/nonlinear/expressions.h> | |
#include <gtsam/slam/BetweenFactor.h> | |
#include <gtsam/slam/expressions.h> | |
// ... | |
// Define the Boost export macros: | |
#include <boost/serialization/export.hpp> // BOOST_CLASS_EXPORT_GUID | |
#include <boost/serialization/serialization.hpp> | |
#include <gtsam/base/GenericValue.h> // GTSAM_VALUE_EXPORT | |
namespace boost { | |
namespace serialization { | |
template <class Archive, typename Derived> | |
void serialize(Archive &ar, Eigen::EigenBase<Derived> &g, | |
const unsigned int version) { | |
ar &boost::serialization::make_array(g.derived().data(), g.size()); | |
} | |
} // namespace serialization | |
} // namespace boost | |
/* Create GUIDs for Noisemodels */ | |
/* ************************************************************************* */ | |
// clang-format off | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Constrained, "gtsam_noiseModel_Constrained"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Diagonal, "gtsam_noiseModel_Diagonal"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Gaussian, "gtsam_noiseModel_Gaussian"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Unit, "gtsam_noiseModel_Unit"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Isotropic,"gtsam_noiseModel_Isotropic"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::Robust, "gtsam_noiseModel_Robust"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::mEstimator::Base, "gtsam_noiseModel_mEstimator_Base"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::mEstimator::Null,"gtsam_noiseModel_mEstimator_Null"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::mEstimator::Fair, "gtsam_noiseModel_mEstimator_Fair"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::mEstimator::Huber,"gtsam_noiseModel_mEstimator_Huber"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::noiseModel::mEstimator::Tukey, "gtsam_noiseModel_mEstimator_Tukey"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::SharedNoiseModel, "gtsam_SharedNoiseModel"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::SharedDiagonal, "gtsam_SharedDiagonal"); | |
// clang-format on | |
/* Create GUIDs for geometry */ | |
/* ************************************************************************* */ | |
GTSAM_VALUE_EXPORT(gtsam::Point2); | |
GTSAM_VALUE_EXPORT(gtsam::Point3); | |
GTSAM_VALUE_EXPORT(gtsam::Rot2); | |
GTSAM_VALUE_EXPORT(gtsam::Rot3); | |
GTSAM_VALUE_EXPORT(gtsam::Pose2); | |
GTSAM_VALUE_EXPORT(gtsam::Pose3); | |
/* Create GUIDs for factors */ | |
/* ************************************************************************* */ | |
// clang-format off | |
BOOST_CLASS_EXPORT_GUID(gtsam::JacobianFactor, "gtsam::JacobianFactor"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::ExpressionFactor<gtsam::Point3>, "gtsam::ExpressionFactor<gtsam::Point3>"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::ExpressionFactor<gtsam::Rot3>, "gtsam::ExpressionFactor<gtsam::Rot3>"); | |
// Add your custom factors, if any. | |
BOOST_CLASS_EXPORT_GUID(gtsam::BetweenFactor<gtsam::Point3>, "gtsam::BetweenFactor<gtsam::Point3>"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::BetweenFactor<gtsam::Rot3>, "gtsam::BetweenFactor<gtsam::Rot3>"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::PriorFactor<gtsam::Point3>, "gtsam::PriorFactor<gtsam::Point3>"); | |
BOOST_CLASS_EXPORT_GUID(gtsam::PriorFactor<gtsam::Rot3>, "gtsam::PriorFactor<gtsam::Rot3>"); | |
void saveBinary(const std::string &outFileName, const gtsam::NonlinearFactorGraph &f, const gtsam::Values &v) | |
{ | |
std::ofstream ofs(outFileName); | |
boost::archive::binary_oarchive oa(ofs); | |
oa << f << v; | |
} | |
void loadBinary(const std::string &inFileName, gtsam::NonlinearFactorGraph &f, gtsam::Values &v) | |
{ | |
std::ifstream ifs(inFileName); | |
if (!ifs.is_open()) | |
throw std::runtime_error("Error opening file"); | |
boost::archive::binary_iarchive ia(ifs); | |
ia >> f >> v; | |
} |
You need to add an additional line for each factor type, e.g.
BOOST_CLASS_EXPORT_GUID(gtsam::PriorFactor<gtsam::Pose3>, "gtsam::PriorFactor<gtsam::Pose3>");
// ...
You might be also interested in giving a try to this alternative project to serialize GTSAM graphs.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I just tested this code but it doesn't work for me. It exits with the error:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): unregistered class - derived class not registered or exported
GDB trace seems to imply there is a problem with gtsam::NonlinearFactor class derivates:
boost::archive::detail::save_pointer_type<boost::archive::binary_oarchive>::polymorphic::save<gtsam::NonlinearFactor> (ar=..., t=...) at /usr/include/boost/serialization/singleton.hpp:195
The problem arises just as I try to save a NonlinearFactorGraph with Values, which only contain an initial gtsam::PriorFactor<gtsam::Pose3> and the corresponding initial value.
I am using GTSAM v4.0.0 and have zero experience with BOOST serialization, so any ideas on how I could fix this bug are welcome.