3939#include < fuse_core/fuse_macros.h>
4040#include < fuse_core/local_parameterization.h>
4141#include < fuse_core/manifold.h>
42+ #include < fuse_core/manifold_adapter.h>
4243#include < fuse_core/serialization.h>
4344#include < fuse_core/variable.h>
4445
4849#include < boost/serialization/base_object.hpp>
4950#include < boost/serialization/export.hpp>
5051#include < boost/serialization/shared_ptr.hpp>
52+ #include < boost/serialization/unique_ptr.hpp>
5153#include < boost/serialization/vector.hpp>
5254#include < boost/tuple/tuple.hpp>
5355#include < ceres/cost_function.h>
5456
5557#include < algorithm>
5658#include < cassert>
59+ #include < functional>
60+ #include < iterator>
5761#include < ostream>
62+ #include < stdexcept>
5863#include < string>
64+ #include < utility>
5965#include < vector>
6066
6167namespace fuse_constraints
@@ -131,7 +137,7 @@ class MarginalConstraint : public fuse_core::Constraint
131137 }
132138#else
133139 /* *
134- * @brief Read-only access to the variable local parameterizations
140+ * @brief Read-only access to the variable manifolds
135141 */
136142 const std::vector<fuse_core::Manifold::SharedPtr>& manifolds () const { return manifolds_; }
137143#endif
@@ -171,22 +177,72 @@ class MarginalConstraint : public fuse_core::Constraint
171177 /* *
172178 * @brief The Boost Serialize method that serializes all of the data members in to/out of the archive
173179 *
174- * @param[in/ out] archive - The archive object that holds the serialized class members
175- * @param[in] version - The version of the archive being read/ written. Generally unused .
180+ * @param[out] archive - The archive object into which class members will be serialized
181+ * @param[in] version - The version of the archive being written.
176182 */
177- template <class Archive >
178- void serialize (Archive& archive, const unsigned int /* version */ )
183+ template <class Archive >
184+ void save (Archive& archive, const unsigned int version) const
179185 {
180- archive& boost::serialization::base_object<fuse_core::Constraint>(*this );
181- archive& A_;
182- archive& b_;
186+ archive << boost::serialization::base_object<fuse_core::Constraint>(*this );
187+ archive << A_;
188+ archive << b_;
183189#if !CERES_SUPPORTS_MANIFOLDS
184- archive& local_parameterizations_;
190+ archive << local_parameterizations_;
185191#else
186- archive& manifolds_;
192+ archive << manifolds_;
187193#endif
188- archive& x_bar_;
194+ archive << x_bar_;
189195 }
196+
197+ /* *
198+ * @brief The Boost Serialize method that serializes all of the data members in to/out of the archive
199+ *
200+ * @param[in] archive - The archive object that holds the serialized class members
201+ * @param[in] version - The version of the archive being read.
202+ */
203+ template <class Archive >
204+ void load (Archive& archive, const unsigned int version)
205+ {
206+ archive >> boost::serialization::base_object<fuse_core::Constraint>(*this );
207+ archive >> A_;
208+ archive >> b_;
209+ if (version == 0 )
210+ {
211+ // Version 0 serialization files will contain a std::vector of LocalParameterization shared pointers.
212+ // If the current version of Ceres Solver does not support Manifolds, then the serialized LocalParameterization
213+ // pointers can be deserialized directly into the class member.
214+ // But if the current version of Ceres Solver supports manifolds, then the serialized LocalParameterization
215+ // pointers must be wrapped in a Manifold adapter first.
216+ #if !CERES_SUPPORTS_MANIFOLDS
217+ archive >> local_parameterizations_;
218+ #else
219+ auto local_parameterizations = std::vector<fuse_core::LocalParameterization::SharedPtr>();
220+ archive >> local_parameterizations;
221+ std::transform (
222+ std::make_move_iterator (local_parameterizations.begin ()),
223+ std::make_move_iterator (local_parameterizations.end ()),
224+ std::back_inserter (manifolds_),
225+ [](fuse_core::LocalParameterization::SharedPtr local_parameterization)
226+ { return fuse_core::ManifoldAdapter::make_shared (std::move (local_parameterization)); });
227+ #endif
228+ }
229+ else // (version >= 1)
230+ {
231+ // Version 1 serialization files will contain a std::vector of Manifold shared pointers. If the current version
232+ // of Ceres Solver does not support Manifolds, then there is no way to deserialize the requested data.
233+ // But if the current version of Ceres Solver does support manifolds, then the serialized Manifold pointers
234+ // can be deserialized directly into the class member.
235+ #if !CERES_SUPPORTS_MANIFOLDS
236+ throw std::runtime_error (" Attempting to deserialize an archive saved in Version " + std::to_string (version) +
237+ " format. However, the current version of Ceres Solver (" + CERES_VERSION_STRING + " ) does not support"
238+ " manifolds. Ceres Solver version 2.1.0 or later is required to load this file." );
239+ #else
240+ archive >> manifolds_;
241+ #endif
242+ }
243+ archive >> x_bar_;
244+ }
245+ BOOST_SERIALIZATION_SPLIT_MEMBER ();
190246};
191247
192248namespace detail
@@ -211,7 +267,7 @@ inline const fuse_core::VectorXd getCurrentValue(const fuse_core::Variable& vari
211267/* *
212268 * @brief Return the local parameterization of the provided variable
213269 */
214- inline fuse_core::LocalParameterization::SharedPtr const getLocalParameterization (const fuse_core::Variable& variable)
270+ inline fuse_core::LocalParameterization::SharedPtr getLocalParameterization (const fuse_core::Variable& variable)
215271{
216272 return fuse_core::LocalParameterization::SharedPtr (variable.localParameterization ());
217273}
@@ -220,7 +276,7 @@ inline fuse_core::LocalParameterization::SharedPtr const getLocalParameterizatio
220276/* *
221277 * @brief Return the manifold of the provided variable
222278 */
223- inline fuse_core::Manifold::SharedPtr const getManifold (const fuse_core::Variable& variable)
279+ inline fuse_core::Manifold::SharedPtr getManifold (const fuse_core::Variable& variable)
224280{
225281 return fuse_core::Manifold::SharedPtr (variable.manifold ());
226282}
@@ -275,5 +331,12 @@ MarginalConstraint::MarginalConstraint(
275331} // namespace fuse_constraints
276332
277333BOOST_CLASS_EXPORT_KEY (fuse_constraints::MarginalConstraint);
334+ // Since the contents of the serialized file will change depending on the CeresSolver version, also set the
335+ // Boost Serialization version to allow code reading serialized file to know what data to expect.
336+ #if !CERES_SUPPORTS_MANIFOLDS
337+ BOOST_CLASS_VERSION (fuse_constraints::MarginalConstraint, 0 );
338+ #else
339+ BOOST_CLASS_VERSION (fuse_constraints::MarginalConstraint, 1 );
340+ #endif
278341
279342#endif // FUSE_CONSTRAINTS_MARGINAL_CONSTRAINT_H
0 commit comments