diff --git a/gtsam/base/serialization.h b/gtsam/base/serialization.h index 8089de814..a41182f47 100644 --- a/gtsam/base/serialization.h +++ b/gtsam/base/serialization.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include // includes for standard serialization types @@ -57,6 +58,28 @@ void deserialize(const std::string& serialized, T& output) { in_archive >> output; } +template +bool serializeToFile(const T& input, const std::string& filename) { + std::ofstream out_archive_stream(filename.c_str()); + if (!out_archive_stream.is_open()) + return false; + boost::archive::text_oarchive out_archive(out_archive_stream); + out_archive << input; + out_archive_stream.close(); + return true; +} + +template +bool deserializeFromFile(const std::string& filename, T& output) { + std::ifstream in_archive_stream(filename.c_str()); + if (!in_archive_stream.is_open()) + return false; + boost::archive::text_iarchive in_archive(in_archive_stream); + in_archive >> output; + in_archive_stream.close(); + return true; +} + // Serialization to XML format with named structures template std::string serializeXML(const T& input, const std::string& name="data") { @@ -73,6 +96,28 @@ void deserializeXML(const std::string& serialized, T& output, const std::string& in_archive >> boost::serialization::make_nvp(name.c_str(), output); } +template +bool serializeToXMLFile(const T& input, const std::string& filename, const std::string& name="data") { + std::ofstream out_archive_stream(filename.c_str()); + if (!out_archive_stream.is_open()) + return false; + boost::archive::xml_oarchive out_archive(out_archive_stream); + out_archive << boost::serialization::make_nvp(name.c_str(), input);; + out_archive_stream.close(); + return true; +} + +template +bool deserializeFromXMLFile(const std::string& filename, T& output, const std::string& name="data") { + std::ifstream in_archive_stream(filename.c_str()); + if (!in_archive_stream.is_open()) + return false; + boost::archive::xml_iarchive in_archive(in_archive_stream); + in_archive >> boost::serialization::make_nvp(name.c_str(), output); + in_archive_stream.close(); + return true; +} + // Serialization to binary format with named structures template std::string serializeBinary(const T& input, const std::string& name="data") { @@ -89,4 +134,26 @@ void deserializeBinary(const std::string& serialized, T& output, const std::stri in_archive >> boost::serialization::make_nvp(name.c_str(), output); } +template +bool deserializeToBinaryFile(const T& input, const std::string& filename, const std::string& name="data") { + std::ofstream out_archive_stream(filename.c_str()); + if (!out_archive_stream.is_open()) + return false; + boost::archive::binary_oarchive out_archive(out_archive_stream); + out_archive << boost::serialization::make_nvp(name.c_str(), input);; + out_archive_stream.close(); + return true; +} + +template +bool deserializeFromBinaryFile(const std::string& filename, T& output, const std::string& name="data") { + std::ifstream in_archive_stream(filename.c_str()); + if (!in_archive_stream.is_open()) + return false; + boost::archive::binary_iarchive in_archive(in_archive_stream); + in_archive >> boost::serialization::make_nvp(name.c_str(), output); + in_archive_stream.close(); + return true; +} + } // \namespace gtsam diff --git a/gtsam/slam/serialization.cpp b/gtsam/slam/serialization.cpp index d8a1cce06..e601a5e81 100644 --- a/gtsam/slam/serialization.cpp +++ b/gtsam/slam/serialization.cpp @@ -253,5 +253,61 @@ Values::shared_ptr gtsam::deserializeValuesXML(const std::string& serialized_val } /* ************************************************************************* */ +bool gtsam::serializeGraphToFile(const NonlinearFactorGraph& graph, const std::string& fname) { + return serializeToFile(graph, fname); +} + +/* ************************************************************************* */ +bool gtsam::serializeGraphToXMLFile(const NonlinearFactorGraph& graph, + const std::string& fname, const std::string& name) { + return serializeToXMLFile(graph, fname, name); +} + +/* ************************************************************************* */ +bool gtsam::serializeValuesToFile(const Values& values, const std::string& fname) { + return serializeToFile(values, fname); +} + +/* ************************************************************************* */ +bool gtsam::serializeValuesToXMLFile(const Values& values, + const std::string& fname, const std::string& name) { + return serializeToXMLFile(values, fname, name); +} + +/* ************************************************************************* */ +NonlinearFactorGraph::shared_ptr gtsam::deserializeGraphToFile(const std::string& fname) { + NonlinearFactorGraph::shared_ptr result(new NonlinearFactorGraph()); + if (!deserializeFromFile(fname, *result)) + throw std::invalid_argument("Failed to open file" + fname); + return result; +} + +/* ************************************************************************* */ +NonlinearFactorGraph::shared_ptr gtsam::deserializeGraphToXMLFile(const std::string& fname, + const std::string& name) { + NonlinearFactorGraph::shared_ptr result(new NonlinearFactorGraph()); + if (!deserializeFromXMLFile(fname, *result, name)) + throw std::invalid_argument("Failed to open file" + fname); + return result; +} + +/* ************************************************************************* */ +Values::shared_ptr gtsam::deserializeValuesToFile(const std::string& fname) { + Values::shared_ptr result(new Values()); + if (!deserializeFromFile(fname, *result)) + throw std::invalid_argument("Failed to open file" + fname); + return result; +} + +/* ************************************************************************* */ +Values::shared_ptr gtsam::deserializeValuesToXMLFile(const std::string& fname, + const std::string& name) { + Values::shared_ptr result(new Values()); + if (!deserializeFromXMLFile(fname, *result, name)) + throw std::invalid_argument("Failed to open file" + fname); + return result; +} + +/* ************************************************************************* */ diff --git a/gtsam/slam/serialization.h b/gtsam/slam/serialization.h index 0dde72a8c..5d75f160c 100644 --- a/gtsam/slam/serialization.h +++ b/gtsam/slam/serialization.h @@ -35,6 +35,28 @@ std::string serializeValuesXML(const Values& values, const std::string& name = " Values::shared_ptr deserializeValuesXML(const std::string& serialized_values, const std::string& name = "values"); +// Serialize to/from files +// serialize functions return true if successful +// Filename arguments include path + +// Serialize +bool serializeGraphToFile(const NonlinearFactorGraph& graph, const std::string& fname); +bool serializeGraphToXMLFile(const NonlinearFactorGraph& graph, + const std::string& fname, const std::string& name = "graph"); + +bool serializeValuesToFile(const Values& values, const std::string& fname); +bool serializeValuesToXMLFile(const Values& values, + const std::string& fname, const std::string& name = "values"); + +// Deserialize +NonlinearFactorGraph::shared_ptr deserializeGraphToFile(const std::string& fname); +NonlinearFactorGraph::shared_ptr deserializeGraphToXMLFile(const std::string& fname, + const std::string& name = "graph"); + +Values::shared_ptr deserializeValuesToFile(const std::string& fname); +Values::shared_ptr deserializeValuesToXMLFile(const std::string& fname, + const std::string& name = "values"); + } // \namespace gtsam diff --git a/gtsam/slam/tests/testSerialization.cpp b/gtsam/slam/tests/testSerialization.cpp index 91b938ad0..aad89d4a0 100644 --- a/gtsam/slam/tests/testSerialization.cpp +++ b/gtsam/slam/tests/testSerialization.cpp @@ -16,9 +16,23 @@ #include #include +#include + +#include +#include +#include +#include +#include using namespace std; using namespace gtsam; +using namespace boost::assign; +namespace fs = boost::filesystem; +#ifdef TOPSRCDIR +static string topdir = TOPSRCDIR; +#else +static string topdir = "TOPSRCDIR_NOT_CONFIGURED"; // If TOPSRCDIR is not defined, we error +#endif Values exampleValues() { Values result; @@ -35,6 +49,7 @@ NonlinearFactorGraph exampleGraph() { NonlinearFactorGraph graph; graph.add(PriorFactor(234, Pose2(1.0, 2.0, 0.3), noiseModel::Diagonal::Sigmas(ones(3)))); graph.add(BetweenFactor(234, 567, Pose2(1.0, 2.0, 0.3), noiseModel::Diagonal::Sigmas(ones(3)))); + graph.add(BearingRangeFactor(234, 567, Rot2::fromAngle(0.3), 2.0, noiseModel::Diagonal::Sigmas(ones(2)))); return graph; } @@ -70,6 +85,38 @@ TEST( testSerialization, xml_values_serialization ) { EXPECT(assert_equal(values, actValues, 1e-5)); } +/* ************************************************************************* */ +TEST( testSerialization, serialization_file ) { + // Create files in folder in build folder + fs::remove_all("actual"); + fs::create_directory("actual"); + string path = "actual/"; + + NonlinearFactorGraph graph = exampleGraph(); + Values values = exampleValues(); + + // Serialize objects using each configuration + EXPECT(serializeGraphToFile(graph, path + "graph.dat")); + EXPECT(serializeGraphToXMLFile(graph, path + "graph.xml", "graph1")); + + EXPECT(serializeValuesToFile(values, path + "values.dat")); + EXPECT(serializeValuesToXMLFile(values, path + "values.xml", "values1")); + + // Deserialize + NonlinearFactorGraph actGraph = *deserializeGraphToFile(path + "graph.dat"); + NonlinearFactorGraph actGraphXML = *deserializeGraphToXMLFile(path + "graph.xml", "graph1"); + + Values actValues = *deserializeValuesToFile(path + "values.dat"); + Values actValuesXML = *deserializeValuesToXMLFile(path + "values.xml", "values1"); + + // Verify + EXPECT(assert_equal(graph, actGraph)); + EXPECT(assert_equal(graph, actGraphXML)); + + EXPECT(assert_equal(values, actValues)); + EXPECT(assert_equal(values, actValuesXML)); +} + /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr); } /* ************************************************************************* */