avoid inheritance by conditionally defining backwards compatibility types/funcs in NoiseModelFactorN

release/4.3a0
Gerry Chen 2021-12-03 06:17:14 -05:00
parent ea7d769476
commit ba3cc85701
No known key found for this signature in database
GPG Key ID: E9845092D3A57286
2 changed files with 385 additions and 225 deletions

View File

@ -306,6 +306,76 @@ public:
}; // \class NoiseModelFactor
/* ************************************************************************* */
/* We need some helper structs to help us with NoiseModelFactorN - specifically
* we need to alias X1, X2, X3, ... in the templated NoiseModelFactorN class to
* maintain backwards compatibility with NoiseModelFactor1, NoiseModelFactor2,
* NoiseModelFactor3, ...
*
* The tricky part is that we want to _conditionally_ alias these only if the
* `sizeof...(VALUES)` is greater than the index we want to alias (e.g. a 3-way
* factor should only have up to X3).
*
* The approach we use is to create structs which use template specialization to
* conditionally typedef X1, X2, ... for us, then inherit from them to inherit
* the aliases.
*
* Usage:
* ```
* template <class... VALUES>
* class MyClass : public AliasX3<VALUES...> { ... };
* ```
* This will only typedef X3 if VALUES has at least 3 template parameters. So
* then we can do something like:
* ```
* int main {
* MyClass<bool, int, double>::X3 a; // variable a will have type double
* // MyClass<bool, int>::X3 b; // this won't compile
* MyClass<bool, int, char, double>::X3 c; // variable c will have type char
* }
* ```
*/
// convenience macro extracts the type for the i'th VALUE in a parameter pack
#define GET_VALUE_I(VALUES, I) \
typename std::tuple_element<I, std::tuple<VALUES...>>::type
namespace detail {
// First handle `typedef X`. By default, we do not alias X (empty struct).
template <bool, class... VALUES>
struct AliasX_ {};
// But if `1 == sizeof...(VALUES)` is true, then we do alias X by specializing
// for when the first template parameter is true.
template <class... VALUES>
struct AliasX_<(1 == sizeof...(VALUES)), VALUES...> {
using X = GET_VALUE_I(VALUES, 0);
};
// We'll alias the "true" template version for convenience.
template <class... VALUES>
using AliasX = AliasX_<true, VALUES...>;
// Now do the same thing for X1, X2, ... using a macro.
#define ALIAS_HELPER_X(N) \
template <bool, class... VALUES> \
struct AliasX##N##_ {}; \
template <class... VALUES> \
struct AliasX##N##_<(N <= sizeof...(VALUES)), VALUES...> { \
using X##N = GET_VALUE_I(VALUES, N - 1); \
}; \
template <class... VALUES> \
using AliasX##N = AliasX##N##_<true, VALUES...>;
ALIAS_HELPER_X(1);
ALIAS_HELPER_X(2);
ALIAS_HELPER_X(3);
ALIAS_HELPER_X(4);
ALIAS_HELPER_X(5);
ALIAS_HELPER_X(6);
#undef ALIAS_HELPER_X
#undef GET_VALUE_I
} // namespace detail
/* ************************************************************************* */
/**
* A convenient base class for creating your own NoiseModelFactor
@ -337,11 +407,21 @@ public:
* objects in non-linear manifolds (Lie groups).
*/
template <class... VALUES>
class NoiseModelFactorN : public NoiseModelFactor {
class NoiseModelFactorN : public NoiseModelFactor,
public detail::AliasX<VALUES...>,
public detail::AliasX1<VALUES...>,
public detail::AliasX2<VALUES...>,
public detail::AliasX3<VALUES...>,
public detail::AliasX4<VALUES...>,
public detail::AliasX5<VALUES...>,
public detail::AliasX6<VALUES...> {
public:
/** The type of the N'th template param can be obtained as VALUE<N> */
template <int N>
using VALUE = typename std::tuple_element<N, std::tuple<VALUES...>>::type;
/// N is the number of variables (N-way factor)
enum { N = sizeof...(VALUES) };
/** The type of the i'th template param can be obtained as VALUE<I> */
template <int I, typename std::enable_if<(I < N), bool>::type = true>
using VALUE = typename std::tuple_element<I, std::tuple<VALUES...>>::type;
protected:
using Base = NoiseModelFactor;
@ -375,28 +455,42 @@ class NoiseModelFactorN : public NoiseModelFactor {
*/
NoiseModelFactorN(const SharedNoiseModel& noiseModel,
key_type<VALUES>... keys)
: Base(noiseModel, std::array<Key, sizeof...(VALUES)>{keys...}) {}
: Base(noiseModel, std::array<Key, N>{keys...}) {}
/**
* Constructor.
* Constructor. Only enabled for n-ary factors where n > 1.
* @param noiseModel Shared pointer to noise model.
* @param keys A container of keys for the variables in this factor.
*/
template <typename CONTAINER>
template <typename CONTAINER, // use "dummy" parameter T to delay deduction
size_t T = N, typename std::enable_if<(T > 1), bool>::type = true>
NoiseModelFactorN(const SharedNoiseModel& noiseModel, CONTAINER keys)
: Base(noiseModel, keys) {
assert(keys.size() == sizeof...(VALUES));
assert(keys.size() == N);
}
/// @}
~NoiseModelFactorN() override {}
/** Method to retrieve keys */
template <int N>
inline Key key() const {
return keys_[N];
/** Methods to retrieve keys */
#define SUB(Old, New) template <int Old = New> // to delay template deduction
#define KEY_IF_TRUE(Enable) typename std::enable_if<(Enable), Key>::type
// templated version of `key<I>()`
template <int I>
inline KEY_IF_TRUE(I < N) key() const {
return keys_[I];
}
// backwards-compatibility functions
SUB(T, N) inline KEY_IF_TRUE(T == 1) key() const { return keys_[0]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 1) key1() const { return keys_[0]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 2) key2() const { return keys_[1]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 3) key3() const { return keys_[2]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 4) key4() const { return keys_[3]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 5) key5() const { return keys_[4]; }
SUB(T, N) inline KEY_IF_TRUE(T >= 6) key6() const { return keys_[5]; }
#undef SUB
#undef KEY_IF_TRUE
/// @name NoiseModelFactor methods
/// @{
@ -458,8 +552,7 @@ class NoiseModelFactorN : public NoiseModelFactor {
/** Some optional jacobians omitted function overload */
template <typename... OptionalJacArgs,
typename std::enable_if<(sizeof...(OptionalJacArgs) > 0) &&
(sizeof...(OptionalJacArgs) <
sizeof...(VALUES)),
(sizeof...(OptionalJacArgs) < N),
bool>::type = true>
inline Vector evaluateError(const VALUES&... x,
OptionalJacArgs&&... H) const {
@ -498,245 +591,268 @@ class NoiseModelFactorN : public NoiseModelFactor {
}
}; // \class NoiseModelFactorN
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 1 variable. To derive from this class, implement evaluateError().
*/
template <class VALUE>
class NoiseModelFactor1 : public NoiseModelFactorN<VALUE> {
public:
// aliases for value types pulled from keys
using X = VALUE;
// template <class VALUE>
// using NoiseModelFactor1 = NoiseModelFactorN<VALUE>;
// template <class VALUE1, class VALUE2>
// using NoiseModelFactor2 = NoiseModelFactorN<VALUE1, VALUE2>;
// template <class VALUE1, class VALUE2, class VALUE3>
// using NoiseModelFactor3 = NoiseModelFactorN<VALUE1, VALUE2, VALUE3>;
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4>
// using NoiseModelFactor4 = NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4>;
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5>
// using NoiseModelFactor5 =
// NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5>;
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5,
// class VALUE6>
// using NoiseModelFactor6 =
// NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5, VALUE6>;
protected:
using Base = NoiseModelFactor; // grandparent, for backwards compatibility
using This = NoiseModelFactor1<VALUE>;
#define NoiseModelFactor1 NoiseModelFactorN
#define NoiseModelFactor2 NoiseModelFactorN
#define NoiseModelFactor3 NoiseModelFactorN
#define NoiseModelFactor4 NoiseModelFactorN
#define NoiseModelFactor5 NoiseModelFactorN
#define NoiseModelFactor6 NoiseModelFactorN
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE>::NoiseModelFactorN;
~NoiseModelFactor1() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 1 variable. To derive from this class, implement evaluateError().
// */
// template <class VALUE>
// class NoiseModelFactor1 : public NoiseModelFactorN<VALUE> {
// public:
// // aliases for value types pulled from keys
// using X = VALUE;
/** method to retrieve key */
inline Key key() const { return this->keys_[0]; }
// protected:
// using Base = NoiseModelFactor; // grandparent, for backwards compatibility
// using This = NoiseModelFactor1<VALUE>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor1
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE>::NoiseModelFactorN;
// ~NoiseModelFactor1() override {}
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 2 variables. To derive from this class, implement evaluateError().
*/
template <class VALUE1, class VALUE2>
class NoiseModelFactor2 : public NoiseModelFactorN<VALUE1, VALUE2> {
public:
// aliases for value types pulled from keys
using X1 = VALUE1;
using X2 = VALUE2;
// /** method to retrieve key */
// inline Key key() const { return this->keys_[0]; }
protected:
using Base = NoiseModelFactor;
using This = NoiseModelFactor2<VALUE1, VALUE2>;
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor1
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE1, VALUE2>::NoiseModelFactorN;
~NoiseModelFactor2() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 2 variables. To derive from this class, implement evaluateError().
// */
// template <class VALUE1, class VALUE2>
// class NoiseModelFactor2 : public NoiseModelFactorN<VALUE1, VALUE2> {
// public:
// // aliases for value types pulled from keys
// using X1 = VALUE1;
// using X2 = VALUE2;
/** methods to retrieve both keys */
inline Key key1() const { return this->keys_[0]; }
inline Key key2() const { return this->keys_[1]; }
// protected:
// using Base = NoiseModelFactor;
// using This = NoiseModelFactor2<VALUE1, VALUE2>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor2
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE1, VALUE2>::NoiseModelFactorN;
// ~NoiseModelFactor2() override {}
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 3 variables. To derive from this class, implement evaluateError().
*/
template <class VALUE1, class VALUE2, class VALUE3>
class NoiseModelFactor3 : public NoiseModelFactorN<VALUE1, VALUE2, VALUE3> {
public:
// aliases for value types pulled from keys
using X1 = VALUE1;
using X2 = VALUE2;
using X3 = VALUE3;
// /** methods to retrieve both keys */
// inline Key key1() const { return this->keys_[0]; }
// inline Key key2() const { return this->keys_[1]; }
protected:
using Base = NoiseModelFactor;
using This = NoiseModelFactor3<VALUE1, VALUE2, VALUE3>;
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor2
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE1, VALUE2, VALUE3>::NoiseModelFactorN;
~NoiseModelFactor3() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 3 variables. To derive from this class, implement evaluateError().
// */
// template <class VALUE1, class VALUE2, class VALUE3>
// class NoiseModelFactor3 : public NoiseModelFactorN<VALUE1, VALUE2, VALUE3> {
// public:
// // aliases for value types pulled from keys
// using X1 = VALUE1;
// using X2 = VALUE2;
// using X3 = VALUE3;
/** methods to retrieve keys */
inline Key key1() const { return this->keys_[0]; }
inline Key key2() const { return this->keys_[1]; }
inline Key key3() const { return this->keys_[2]; }
// protected:
// using Base = NoiseModelFactor;
// using This = NoiseModelFactor3<VALUE1, VALUE2, VALUE3>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor3
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE1, VALUE2, VALUE3>::NoiseModelFactorN;
// ~NoiseModelFactor3() override {}
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 4 variables. To derive from this class, implement evaluateError().
*/
template <class VALUE1, class VALUE2, class VALUE3, class VALUE4>
class NoiseModelFactor4
: public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4> {
public:
// aliases for value types pulled from keys
using X1 = VALUE1;
using X2 = VALUE2;
using X3 = VALUE3;
using X4 = VALUE4;
// /** methods to retrieve keys */
// inline Key key1() const { return this->keys_[0]; }
// inline Key key2() const { return this->keys_[1]; }
// inline Key key3() const { return this->keys_[2]; }
protected:
using Base = NoiseModelFactor;
using This = NoiseModelFactor4<VALUE1, VALUE2, VALUE3, VALUE4>;
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor3
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4>::NoiseModelFactorN;
~NoiseModelFactor4() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 4 variables. To derive from this class, implement evaluateError().
// */
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4>
// class NoiseModelFactor4
// : public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4> {
// public:
// // aliases for value types pulled from keys
// using X1 = VALUE1;
// using X2 = VALUE2;
// using X3 = VALUE3;
// using X4 = VALUE4;
/** methods to retrieve keys */
inline Key key1() const { return this->keys_[0]; }
inline Key key2() const { return this->keys_[1]; }
inline Key key3() const { return this->keys_[2]; }
inline Key key4() const { return this->keys_[3]; }
// protected:
// using Base = NoiseModelFactor;
// using This = NoiseModelFactor4<VALUE1, VALUE2, VALUE3, VALUE4>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor4
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4>::NoiseModelFactorN;
// ~NoiseModelFactor4() override {}
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 5 variables. To derive from this class, implement evaluateError().
*/
template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5>
class NoiseModelFactor5
: public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5> {
public:
// aliases for value types pulled from keys
using X1 = VALUE1;
using X2 = VALUE2;
using X3 = VALUE3;
using X4 = VALUE4;
using X5 = VALUE5;
// /** methods to retrieve keys */
// inline Key key1() const { return this->keys_[0]; }
// inline Key key2() const { return this->keys_[1]; }
// inline Key key3() const { return this->keys_[2]; }
// inline Key key4() const { return this->keys_[3]; }
protected:
using Base = NoiseModelFactor;
using This = NoiseModelFactor5<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5>;
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor4
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4,
VALUE5>::NoiseModelFactorN;
~NoiseModelFactor5() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 5 variables. To derive from this class, implement evaluateError().
// */
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5>
// class NoiseModelFactor5
// : public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5> {
// public:
// // aliases for value types pulled from keys
// using X1 = VALUE1;
// using X2 = VALUE2;
// using X3 = VALUE3;
// using X4 = VALUE4;
// using X5 = VALUE5;
/** methods to retrieve keys */
inline Key key1() const { return this->keys_[0]; }
inline Key key2() const { return this->keys_[1]; }
inline Key key3() const { return this->keys_[2]; }
inline Key key4() const { return this->keys_[3]; }
inline Key key5() const { return this->keys_[4]; }
// protected:
// using Base = NoiseModelFactor;
// using This = NoiseModelFactor5<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor5
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4,
// VALUE5>::NoiseModelFactorN;
// ~NoiseModelFactor5() override {}
/* ************************************************************************* */
/** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
* with VALUE<1>.
* A convenient base class for creating your own NoiseModelFactor
* with 6 variables. To derive from this class, implement evaluateError().
*/
template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5,
class VALUE6>
class NoiseModelFactor6
: public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5, VALUE6> {
public:
// aliases for value types pulled from keys
using X1 = VALUE1;
using X2 = VALUE2;
using X3 = VALUE3;
using X4 = VALUE4;
using X5 = VALUE5;
using X6 = VALUE6;
// /** methods to retrieve keys */
// inline Key key1() const { return this->keys_[0]; }
// inline Key key2() const { return this->keys_[1]; }
// inline Key key3() const { return this->keys_[2]; }
// inline Key key4() const { return this->keys_[3]; }
// inline Key key5() const { return this->keys_[4]; }
protected:
using Base = NoiseModelFactor;
using This =
NoiseModelFactor6<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5, VALUE6>;
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor5
public:
// inherit NoiseModelFactorN's constructors
using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5,
VALUE6>::NoiseModelFactorN;
~NoiseModelFactor6() override {}
// /* ************************************************************************* */
// /** @deprecated: use NoiseModelFactorN, replacing .key1() with .key<1> and X1
// * with VALUE<1>.
// * A convenient base class for creating your own NoiseModelFactor
// * with 6 variables. To derive from this class, implement evaluateError().
// */
// template <class VALUE1, class VALUE2, class VALUE3, class VALUE4, class VALUE5,
// class VALUE6>
// class NoiseModelFactor6
// : public NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5, VALUE6> {
// public:
// // aliases for value types pulled from keys
// using X1 = VALUE1;
// using X2 = VALUE2;
// using X3 = VALUE3;
// using X4 = VALUE4;
// using X5 = VALUE5;
// using X6 = VALUE6;
/** methods to retrieve keys */
inline Key key1() const { return this->keys_[0]; }
inline Key key2() const { return this->keys_[1]; }
inline Key key3() const { return this->keys_[2]; }
inline Key key4() const { return this->keys_[3]; }
inline Key key5() const { return this->keys_[4]; }
inline Key key6() const { return this->keys_[5]; }
// protected:
// using Base = NoiseModelFactor;
// using This =
// NoiseModelFactor6<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5, VALUE6>;
private:
/** Serialization function */
friend class boost::serialization::access;
template <class ARCHIVE>
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
ar& boost::serialization::make_nvp(
"NoiseModelFactor", boost::serialization::base_object<Base>(*this));
}
}; // \class NoiseModelFactor6
// public:
// // inherit NoiseModelFactorN's constructors
// using NoiseModelFactorN<VALUE1, VALUE2, VALUE3, VALUE4, VALUE5,
// VALUE6>::NoiseModelFactorN;
// ~NoiseModelFactor6() override {}
// /** methods to retrieve keys */
// inline Key key1() const { return this->keys_[0]; }
// inline Key key2() const { return this->keys_[1]; }
// inline Key key3() const { return this->keys_[2]; }
// inline Key key4() const { return this->keys_[3]; }
// inline Key key5() const { return this->keys_[4]; }
// inline Key key6() const { return this->keys_[5]; }
// private:
// /** Serialization function */
// friend class boost::serialization::access;
// template <class ARCHIVE>
// void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
// ar& boost::serialization::make_nvp(
// "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
// }
// }; // \class NoiseModelFactor6
} // \namespace gtsam

View File

@ -253,6 +253,50 @@ TEST( NonlinearFactor, cloneWithNewNoiseModel )
CHECK(assert_equal(expected, actual));
}
/* ************************************************************************* */
class TestFactor1 : public NoiseModelFactor1<double> {
static_assert(std::is_same<Base, NoiseModelFactor>::value, "Base type wrong");
static_assert(std::is_same<This, NoiseModelFactor1<double>>::value,
"This type wrong");
public:
typedef NoiseModelFactor1<double> Base;
TestFactor1() : Base(noiseModel::Diagonal::Sigmas(Vector1(2.0)), L(1)) {}
Vector evaluateError(const double& x1, boost::optional<Matrix&> H1 =
boost::none) const override {
if (H1) *H1 = (Matrix(1, 1) << 1.0).finished();
return (Vector(1) << x1).finished();
}
gtsam::NonlinearFactor::shared_ptr clone() const override {
return boost::static_pointer_cast<gtsam::NonlinearFactor>(
gtsam::NonlinearFactor::shared_ptr(new TestFactor1(*this)));
}
};
/* ************************************ */
TEST(NonlinearFactor, NoiseModelFactor1) {
TestFactor1 tf;
Values tv;
tv.insert(L(1), double((1.0)));
EXPECT(assert_equal((Vector(1) << 1.0).finished(), tf.unwhitenedError(tv)));
DOUBLES_EQUAL(0.25 / 2.0, tf.error(tv), 1e-9);
JacobianFactor jf(
*boost::dynamic_pointer_cast<JacobianFactor>(tf.linearize(tv)));
LONGS_EQUAL((long)L(1), (long)jf.keys()[0]);
EXPECT(assert_equal((Matrix)(Matrix(1, 1) << 0.5).finished(),
jf.getA(jf.begin())));
EXPECT(assert_equal((Vector)(Vector(1) << -0.5).finished(), jf.getb()));
// Test all functions/types for backwards compatibility
static_assert(std::is_same<TestFactor1::X, double>::value,
"X type incorrect");
EXPECT(assert_equal(tf.key(), L(1)));
std::vector<Matrix> H = {Matrix()};
EXPECT(assert_equal(Vector1(1.0), tf.unwhitenedError(tv, H)));
}
/* ************************************************************************* */
class TestFactor4 : public NoiseModelFactor4<double, double, double, double> {
static_assert(std::is_same<Base, NoiseModelFactor>::value, "Base type wrong");