Added direct saving to/from files for graph/values serialization
							parent
							
								
									527ea5e511
								
							
						
					
					
						commit
						e1fc90ad14
					
				|  | @ -20,6 +20,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <sstream> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| 
 | ||||
| // includes for standard serialization types
 | ||||
|  | @ -57,6 +58,28 @@ void deserialize(const std::string& serialized, T& output) { | |||
|   in_archive >> output; | ||||
| } | ||||
| 
 | ||||
| template<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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<class T> | ||||
| 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
 | ||||
|  |  | |||
|  | @ -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<NonlinearFactorGraph>(graph, fname); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| bool gtsam::serializeGraphToXMLFile(const NonlinearFactorGraph& graph, | ||||
|     const std::string& fname, const std::string& name) { | ||||
|   return serializeToXMLFile<NonlinearFactorGraph>(graph, fname, name); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| bool gtsam::serializeValuesToFile(const Values& values, const std::string& fname) { | ||||
|   return serializeToFile<Values>(values, fname); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| bool gtsam::serializeValuesToXMLFile(const Values& values, | ||||
|     const std::string& fname, const std::string& name) { | ||||
|   return serializeToXMLFile<Values>(values, fname, name); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| NonlinearFactorGraph::shared_ptr gtsam::deserializeGraphToFile(const std::string& fname) { | ||||
|   NonlinearFactorGraph::shared_ptr result(new NonlinearFactorGraph()); | ||||
|   if (!deserializeFromFile<NonlinearFactorGraph>(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<NonlinearFactorGraph>(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<Values>(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<Values>(fname, *result, name)) | ||||
|     throw std::invalid_argument("Failed to open file" + fname); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,9 +16,23 @@ | |||
| 
 | ||||
| #include <gtsam/slam/PriorFactor.h> | ||||
| #include <gtsam/slam/BetweenFactor.h> | ||||
| #include <gtsam/slam/BearingRangeFactor.h> | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <boost/assign/std/vector.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| 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<Pose2>(234, Pose2(1.0, 2.0, 0.3), noiseModel::Diagonal::Sigmas(ones(3)))); | ||||
|   graph.add(BetweenFactor<Pose2>(234, 567, Pose2(1.0, 2.0, 0.3), noiseModel::Diagonal::Sigmas(ones(3)))); | ||||
|   graph.add(BearingRangeFactor<Pose2,Point2>(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); } | ||||
| /* ************************************************************************* */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue