Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding serialization support to be used for GT-SFM #650

Merged
merged 10 commits into from
Jan 4, 2021
12 changes: 12 additions & 0 deletions gtsam/gtsam.i
Original file line number Diff line number Diff line change
Expand Up @@ -2768,6 +2768,12 @@ class SfmTrack {
pair<size_t, gtsam::Point2> measurement(size_t idx) const;
pair<size_t, size_t> siftIndex(size_t idx) const;
void add_measurement(size_t idx, const gtsam::Point2& m);

// enabling serialization functionality
void serialize() const;

// enabling function to compare objects
bool equals(const gtsam::SfmTrack& expected, double tol) const;
};

class SfmData {
Expand All @@ -2778,6 +2784,12 @@ class SfmData {
gtsam::SfmTrack track(size_t idx) const;
void add_track(const gtsam::SfmTrack& t) ;
void add_camera(const gtsam::SfmCamera& cam);

// enabling serialization functionality
void serialize() const;

// enabling function to compare objects
bool equals(const gtsam::SfmData& expected, double tol) const;
};

gtsam::SfmData readBal(string filename);
Expand Down
124 changes: 121 additions & 3 deletions gtsam/slam/dataset.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
#include <gtsam/nonlinear/Values.h>
#include <gtsam/linear/NoiseModel.h>
#include <gtsam/base/serialization.h>
#include <gtsam/base/Testable.h>
#include <gtsam/base/types.h>

#include <boost/smart_ptr/shared_ptr.hpp>
Expand Down Expand Up @@ -222,7 +224,7 @@ struct SfmTrack {
float r, g, b; ///< RGB color of the 3D point
std::vector<SfmMeasurement> measurements; ///< The 2D image projections (id,(u,v))
std::vector<SiftIndex> siftIndices;

/// Total number of measurements in this track
size_t number_measurements() const {
return measurements.size();
Expand All @@ -243,6 +245,73 @@ struct SfmTrack {
void add_measurement(size_t idx, const gtsam::Point2& m) {
measurements.emplace_back(idx, m);
}

/** Serialization function */
friend class boost::serialization::access;
template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
ar & BOOST_SERIALIZATION_NVP(p);
ar & BOOST_SERIALIZATION_NVP(r);
ar & BOOST_SERIALIZATION_NVP(g);
ar & BOOST_SERIALIZATION_NVP(b);
ar & BOOST_SERIALIZATION_NVP(measurements);
ar & BOOST_SERIALIZATION_NVP(siftIndices);
}

/// assert equality up to a tolerance
bool equals(const SfmTrack &sfmTrack, double tol = 1e-9) const {
// check the 3D point
if (!p.isApprox(sfmTrack.p)) {
return false;
}

// check the RGB values
if (r!=sfmTrack.r || g!=sfmTrack.g || b!=sfmTrack.b) {
return false;
}

// compare size of vectors for measurements and siftIndices
if (number_measurements() != sfmTrack.number_measurements() ||
siftIndices.size() != sfmTrack.siftIndices.size()) {
return false;
}

// compare measurements (order sensitive)
for (size_t idx = 0; idx < number_measurements(); ++idx) {
SfmMeasurement measurement = measurements[idx];
SfmMeasurement otherMeasurement = sfmTrack.measurements[idx];

if (measurement.first != otherMeasurement.first ||
!measurement.second.isApprox(otherMeasurement.second)) {
return false;
}
}

// compare sift indices (order sensitive)
for (size_t idx = 0; idx < siftIndices.size(); ++idx) {
SiftIndex index = siftIndices[idx];
SiftIndex otherIndex = sfmTrack.siftIndices[idx];

if (index.first != otherIndex.first ||
index.second != otherIndex.second) {
return false;
}
}

return true;
}

/// print
void print(const std::string& s = "") const {
cout << "Track with " << measurements.size();
cout << " measurements of point " << p << "\n";
}
};

/* ************************************************************************* */
/// traits
johnwlambert marked this conversation as resolved.
Show resolved Hide resolved
template<>
struct traits<SfmTrack> : public Testable<SfmTrack> {
};


Expand All @@ -269,13 +338,62 @@ struct SfmData {
return tracks[idx];
}
/// Add a track to SfmData
void add_track(const SfmTrack& t) {
void add_track(const SfmTrack& t) {
tracks.push_back(t);
}
/// Add a camera to SfmData
void add_camera(const SfmCamera& cam){
void add_camera(const SfmCamera& cam) {
cameras.push_back(cam);
}

/** Serialization function */
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/) {
ar & BOOST_SERIALIZATION_NVP(cameras);
ar & BOOST_SERIALIZATION_NVP(tracks);
}

/// @}
/// @name Testable
/// @{

/// assert equality up to a tolerance
bool equals(const SfmData &sfmData, double tol = 1e-9) const {
// check number of cameras and tracks
if (number_cameras() != sfmData.number_cameras() ||
number_tracks() != sfmData.number_tracks()) {
return false;
}

// check each camera
for (size_t i = 0; i < number_cameras(); ++i) {
if (!camera(i).equals(sfmData.camera(i), tol)) {
return false;
}
}

// check each track
for (size_t j = 0; j < number_tracks(); ++j) {
if (!track(j).equals(sfmData.track(j), tol)) {
return false;
}
}

return true;
}

/// print
void print(const std::string& s = "") const {
cout << "Number of cameras = " << number_cameras() << "\n";
cout << "Number of tracks = " << number_tracks() << "\n";
}
};

/* ************************************************************************* */
/// traits
template<>
struct traits<SfmData> : public Testable<SfmData> {
};

/**
Expand Down
58 changes: 58 additions & 0 deletions gtsam/slam/tests/testSerializationDataset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* ----------------------------------------------------------------------------

* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)

* See LICENSE for the license information

* -------------------------------------------------------------------------- */

/**
* @file testSerializationDataset.cpp
* @brief serialization tests for dataset.cpp
* @author Ayush Baid
* @date Jan 1, 2021
*/

#include <gtsam/slam/dataset.h>

#include <gtsam/base/serializationTestHelpers.h>
#include <CppUnitLite/TestHarness.h>

using namespace std;
using namespace gtsam;
using namespace gtsam::serializationTestHelpers;

/* ************************************************************************* */
TEST(dataSet, sfmDataSerialization) {
// Test the serialization of SfmData
const string filename = findExampleDataFile("dubrovnik-3-7-pre");
SfmData mydata;
CHECK(readBAL(filename, mydata));

// round-trip equality check on serialization and subsequent deserialization
EXPECT(equalsObj(mydata));
johnwlambert marked this conversation as resolved.
Show resolved Hide resolved
EXPECT(equalsXML(mydata));
EXPECT(equalsBinary(mydata));
}

/* ************************************************************************* */
TEST(dataSet, sfmTrackSerialization) {
// Test the serialization of SfmTrack
const string filename = findExampleDataFile("dubrovnik-3-7-pre");
SfmData mydata;
CHECK(readBAL(filename, mydata));

SfmTrack track = mydata.track(0);

// round-trip equality check on serialization and subsequent deserialization
EXPECT(equalsObj(track));
ayushbaid marked this conversation as resolved.
Show resolved Hide resolved
EXPECT(equalsXML(track));
EXPECT(equalsBinary(track));
}

/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */