From 69226edd81d576b4e6d2d9904d76c299e653fd31 Mon Sep 17 00:00:00 2001 From: Gerry Chen Date: Wed, 4 Jan 2023 22:49:57 -0500 Subject: [PATCH] Move `X1-6` aliases into `NoiseModelFactorN` and un-deprecate --- gtsam/nonlinear/NonlinearFactor.h | 362 +++++++----------------------- tests/testNonlinearFactor.cpp | 20 +- 2 files changed, 89 insertions(+), 293 deletions(-) diff --git a/gtsam/nonlinear/NonlinearFactor.h b/gtsam/nonlinear/NonlinearFactor.h index c58179db3..2f718be27 100644 --- a/gtsam/nonlinear/NonlinearFactor.h +++ b/gtsam/nonlinear/NonlinearFactor.h @@ -272,6 +272,64 @@ public: }; // \class NoiseModelFactor +/* ************************************************************************* */ +namespace detail { +/** Convenience base class to add aliases `X1`, `X2`, ..., `X6` -> ValueType. + * Usage example: + * ``` + * class MyFactor : public NoiseModelFactorN, + * public NoiseModelFactorAliases { + * // class implementation ... + * }; + * + * // MyFactor::X1 == Pose3 + * // MyFactor::X2 == Point3 + * ``` + */ +template +struct NoiseModelFactorAliases {}; +template +struct NoiseModelFactorAliases { + using X = T1; + using X1 = T1; +}; +template +struct NoiseModelFactorAliases { + using X1 = T1; + using X2 = T2; +}; +template +struct NoiseModelFactorAliases { + using X1 = T1; + using X2 = T2; + using X3 = T3; +}; +template +struct NoiseModelFactorAliases { + using X1 = T1; + using X2 = T2; + using X3 = T3; + using X4 = T4; +}; +template +struct NoiseModelFactorAliases { + using X1 = T1; + using X2 = T2; + using X3 = T3; + using X4 = T4; + using X5 = T5; +}; +template +struct NoiseModelFactorAliases { + using X1 = T1; + using X2 = T2; + using X3 = T3; + using X4 = T4; + using X5 = T5; + using X6 = T6; +}; +} // namespace detail /* ************************************************************************* */ /** @@ -327,7 +385,9 @@ public: * objects in non-linear manifolds (Lie groups). */ template -class NoiseModelFactorN : public NoiseModelFactor { +class NoiseModelFactorN + : public NoiseModelFactor, + public detail::NoiseModelFactorAliases { public: /// N is the number of variables (N-way factor) enum { N = sizeof...(ValueTypes) }; @@ -377,6 +437,14 @@ class NoiseModelFactorN : public NoiseModelFactor { * // Factor::ValueType<0> // ERROR! Will not compile. * // Factor::ValueType<3> // ERROR! Will not compile. * ``` + * + * You can also use the shortcuts `X1`, ..., `X6` which are the same as + * `ValueType<1>`, ..., `ValueType<6>` respectively (see + * detail::NoiseModelFactorAliases). + * + * Note that, if your class is templated AND you want to use `ValueType<1>` + * inside your class, due to dependent types you need the `template` keyword: + * `typename MyFactor::template ValueType<1>`. */ template > using ValueType = @@ -431,6 +499,10 @@ class NoiseModelFactorN : public NoiseModelFactor { * // key<0>() // ERROR! Will not compile * // key<3>() // ERROR! Will not compile * ``` + * + * Note that, if your class is templated AND you are trying to call `key<1>` + * inside your class, due to dependent types you need the `template` keyword: + * `this->template key<1>()`. */ template inline Key key() const { @@ -555,37 +627,34 @@ class NoiseModelFactorN : public NoiseModelFactor { } public: - /// @name Deprecated methods. Use `key<1>()`, `key<2>()`, ... instead of old - /// `key1()`, `key2()`, ... - /// If your class is templated AND you are trying to call `key<1>` inside your - /// class, due to dependent types you need to do `this->template key<1>()`. + /// @name Shortcut functions `key1()` -> `key<1>()` /// @{ - inline Key GTSAM_DEPRECATED key1() const { + inline Key key1() const { return key<1>(); } template - inline Key GTSAM_DEPRECATED key2() const { + inline Key key2() const { static_assert(I <= N, "Index out of bounds"); return key<2>(); } template - inline Key GTSAM_DEPRECATED key3() const { + inline Key key3() const { static_assert(I <= N, "Index out of bounds"); return key<3>(); } template - inline Key GTSAM_DEPRECATED key4() const { + inline Key key4() const { static_assert(I <= N, "Index out of bounds"); return key<4>(); } template - inline Key GTSAM_DEPRECATED key5() const { + inline Key key5() const { static_assert(I <= N, "Index out of bounds"); return key<5>(); } template - inline Key GTSAM_DEPRECATED key6() const { + inline Key key6() const { static_assert(I <= N, "Index out of bounds"); return key<6>(); } @@ -594,268 +663,11 @@ class NoiseModelFactorN : public NoiseModelFactor { }; // \class NoiseModelFactorN -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 1 variable. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor1 : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys, for backwards compatibility. - * Note: in your code you can probably just do: - * `using X = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X = typename NoiseModelFactor1::template ValueType<1>; +#define NoiseModelFactor1 NoiseModelFactorN +#define NoiseModelFactor2 NoiseModelFactorN +#define NoiseModelFactor3 NoiseModelFactorN +#define NoiseModelFactor4 NoiseModelFactorN +#define NoiseModelFactor5 NoiseModelFactorN +#define NoiseModelFactor6 NoiseModelFactorN - protected: - using Base = NoiseModelFactor; // grandparent, for backwards compatibility - using This = NoiseModelFactor1; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor1() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor1 - -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 2 variables. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor2 - : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys. - * Note: in your code you can probably just do: - * `using X1 = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X1 = typename NoiseModelFactor2::template ValueType<1>; - using X2 = typename NoiseModelFactor2::template ValueType<2>; - - protected: - using Base = NoiseModelFactor; - using This = NoiseModelFactor2; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor2() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor2 - -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 3 variables. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor3 - : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys. - * Note: in your code you can probably just do: - * `using X1 = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X1 = typename NoiseModelFactor3::template ValueType<1>; - using X2 = typename NoiseModelFactor3::template ValueType<2>; - using X3 = typename NoiseModelFactor3::template ValueType<3>; - - protected: - using Base = NoiseModelFactor; - using This = NoiseModelFactor3; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor3() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor3 - -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 4 variables. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor4 - : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys. - * Note: in your code you can probably just do: - * `using X1 = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X1 = typename NoiseModelFactor4::template ValueType<1>; - using X2 = typename NoiseModelFactor4::template ValueType<2>; - using X3 = typename NoiseModelFactor4::template ValueType<3>; - using X4 = typename NoiseModelFactor4::template ValueType<4>; - - protected: - using Base = NoiseModelFactor; - using This = NoiseModelFactor4; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor4() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor4 - -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 5 variables. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor5 - : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys. - * Note: in your code you can probably just do: - * `using X1 = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X1 = typename NoiseModelFactor5::template ValueType<1>; - using X2 = typename NoiseModelFactor5::template ValueType<2>; - using X3 = typename NoiseModelFactor5::template ValueType<3>; - using X4 = typename NoiseModelFactor5::template ValueType<4>; - using X5 = typename NoiseModelFactor5::template ValueType<5>; - - protected: - using Base = NoiseModelFactor; - using This = NoiseModelFactor5; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor5() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor5 - -/* ************************************************************************* */ -/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1>() and X1 - * with ValueType<1>. - * If your class is templated AND you are trying to call `.key<1>()` or - * `ValueType<1>` inside your class, due to dependent types you need to do - * `this->template key<1>()` or `This::template ValueType<1>`. - * ~~~ - * A convenient base class for creating your own NoiseModelFactor - * with 6 variables. To derive from this class, implement evaluateError(). - */ -template -class GTSAM_DEPRECATED NoiseModelFactor6 - : public NoiseModelFactorN { - public: - /** Aliases for value types pulled from keys. - * Note: in your code you can probably just do: - * `using X1 = ValueType<1>;` - * but this class is uglier due to dependent types. - * See e.g. testNonlinearFactor.cpp:TestFactorN. - */ - using X1 = typename NoiseModelFactor6::template ValueType<1>; - using X2 = typename NoiseModelFactor6::template ValueType<2>; - using X3 = typename NoiseModelFactor6::template ValueType<3>; - using X4 = typename NoiseModelFactor6::template ValueType<4>; - using X5 = typename NoiseModelFactor6::template ValueType<5>; - using X6 = typename NoiseModelFactor6::template ValueType<6>; - - protected: - using Base = NoiseModelFactor; - using This = - NoiseModelFactor6; - - public: - // inherit NoiseModelFactorN's constructors - using NoiseModelFactorN::NoiseModelFactorN; - ~NoiseModelFactor6() override {} - - private: - /** Serialization function */ - friend class boost::serialization::access; - template - void serialize(ARCHIVE& ar, const unsigned int /*version*/) { - ar& boost::serialization::make_nvp( - "NoiseModelFactor", boost::serialization::base_object(*this)); - } -}; // \class NoiseModelFactor6 - -} // \namespace gtsam +} // namespace gtsam diff --git a/tests/testNonlinearFactor.cpp b/tests/testNonlinearFactor.cpp index c536a48c3..c82361450 100644 --- a/tests/testNonlinearFactor.cpp +++ b/tests/testNonlinearFactor.cpp @@ -330,13 +330,6 @@ TEST( NonlinearFactor, cloneWithNewNoiseModel ) } /* ************************************************************************* */ -// Suppress deprecation warnings while we are testing backwards compatibility -#define IGNORE_DEPRECATED_PUSH \ - CLANG_DIAGNOSTIC_PUSH_IGNORE("-Wdeprecated-declarations") \ - GCC_DIAGNOSTIC_PUSH_IGNORE("-Wdeprecated-declarations") \ - MSVC_DIAGNOSTIC_PUSH_IGNORE(4996) -/* ************************************************************************* */ -IGNORE_DEPRECATED_PUSH class TestFactor1 : public NoiseModelFactor1 { static_assert(std::is_same::value, "Base type wrong"); static_assert(std::is_same>::value, @@ -358,7 +351,6 @@ class TestFactor1 : public NoiseModelFactor1 { gtsam::NonlinearFactor::shared_ptr(new TestFactor1(*this))); } }; -DIAGNOSTIC_POP() /* ************************************ */ TEST(NonlinearFactor, NoiseModelFactor1) { @@ -388,7 +380,6 @@ TEST(NonlinearFactor, NoiseModelFactor1) { } /* ************************************************************************* */ -IGNORE_DEPRECATED_PUSH class TestFactor4 : public NoiseModelFactor4 { static_assert(std::is_same::value, "Base type wrong"); static_assert( @@ -420,7 +411,6 @@ class TestFactor4 : public NoiseModelFactor4 { return boost::static_pointer_cast( gtsam::NonlinearFactor::shared_ptr(new TestFactor4(*this))); } }; -DIAGNOSTIC_POP() /* ************************************ */ TEST(NonlinearFactor, NoiseModelFactor4) { @@ -444,7 +434,6 @@ TEST(NonlinearFactor, NoiseModelFactor4) { EXPECT(assert_equal((Vector)(Vector(1) << 0.5 * -30.).finished(), jf.getb())); // Test all functions/types for backwards compatibility - IGNORE_DEPRECATED_PUSH static_assert(std::is_same::value, "X1 type incorrect"); static_assert(std::is_same::value, @@ -463,7 +452,6 @@ TEST(NonlinearFactor, NoiseModelFactor4) { EXPECT(assert_equal((Matrix)(Matrix(1, 1) << 2.).finished(), H.at(1))); EXPECT(assert_equal((Matrix)(Matrix(1, 1) << 3.).finished(), H.at(2))); EXPECT(assert_equal((Matrix)(Matrix(1, 1) << 4.).finished(), H.at(3))); - DIAGNOSTIC_POP() // And test "forward compatibility" using `key` and `ValueType` too static_assert(std::is_same, double>::value, @@ -489,7 +477,6 @@ TEST(NonlinearFactor, NoiseModelFactor4) { } /* ************************************************************************* */ -IGNORE_DEPRECATED_PUSH class TestFactor5 : public NoiseModelFactor5 { public: typedef NoiseModelFactor5 Base; @@ -513,7 +500,6 @@ public: .finished(); } }; -DIAGNOSTIC_POP() /* ************************************ */ TEST(NonlinearFactor, NoiseModelFactor5) { @@ -541,7 +527,6 @@ TEST(NonlinearFactor, NoiseModelFactor5) { } /* ************************************************************************* */ -IGNORE_DEPRECATED_PUSH class TestFactor6 : public NoiseModelFactor6 { public: typedef NoiseModelFactor6 Base; @@ -569,7 +554,6 @@ public: } }; -DIAGNOSTIC_POP() /* ************************************ */ TEST(NonlinearFactor, NoiseModelFactor6) { @@ -673,11 +657,11 @@ TEST(NonlinearFactor, NoiseModelFactorN) { EXPECT(assert_equal(H4_expected, H4)); // Test all functions/types for backwards compatibility - IGNORE_DEPRECATED_PUSH + static_assert(std::is_same::value, "X1 type incorrect"); EXPECT(assert_equal(tf.key3(), X(3))); - DIAGNOSTIC_POP() + // Test using `key` and `ValueType` static_assert(std::is_same, double>::value,