gtsam
Loading...
Searching...
No Matches
NoiseModelFactorN.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
20
21#pragma once
22// \callgraph
23
26
27#include <array>
28#include <type_traits>
29#include <utility>
30#include <vector>
31
32namespace gtsam {
33
34/* ************************************************************************* */
35namespace detail {
48template <typename, typename...>
50template <typename T1>
52 using X = T1;
53 using X1 = T1;
54};
55template <typename T1, typename T2>
57 using X1 = T1;
58 using X2 = T2;
59};
60template <typename T1, typename T2, typename T3>
62 using X1 = T1;
63 using X2 = T2;
64 using X3 = T3;
65};
66template <typename T1, typename T2, typename T3, typename T4>
68 using X1 = T1;
69 using X2 = T2;
70 using X3 = T3;
71 using X4 = T4;
72};
73template <typename T1, typename T2, typename T3, typename T4, typename T5>
75 using X1 = T1;
76 using X2 = T2;
77 using X3 = T3;
78 using X4 = T4;
79 using X5 = T5;
80};
81template <typename T1, typename T2, typename T3, typename T4, typename T5,
82 typename T6, typename... TExtra>
83struct NoiseModelFactorAliases<T1, T2, T3, T4, T5, T6, TExtra...> {
84 using X1 = T1;
85 using X2 = T2;
86 using X3 = T3;
87 using X4 = T4;
88 using X5 = T5;
89 using X6 = T6;
90};
91
92} // namespace detail
93
94/* ************************************************************************* */
152template <class OutputVec, class... ValueTypes>
154 : public NoiseModelFactor,
155 public detail::NoiseModelFactorAliases<ValueTypes...> {
156 public:
158 inline constexpr static auto N = sizeof...(ValueTypes);
159
161
162 protected:
163 using Base = NoiseModelFactor;
164 using This = NoiseModelFactorT<OutputVec, ValueTypes...>;
165
168
169 template <typename From, typename To>
170 using IsConvertible =
171 typename std::enable_if<std::is_convertible<From, To>::value, void>::type;
172
173 template <int I>
174 using IndexIsValid = typename std::enable_if<(I >= 1) && (I <= N),
175 void>::type; // 1-indexed!
176
177 template <typename Container>
178 using ContainerElementType =
179 typename std::decay<decltype(*std::declval<Container>().begin())>::type;
180 template <typename Container>
181 using IsContainerOfKeys = IsConvertible<ContainerElementType<Container>, Key>;
182
187 template <typename Ret, typename... Args>
189 std::enable_if_t<(... && std::is_convertible<Args, Matrix&>::value), Ret>;
190
191 template <typename Arg>
192 using IsMatrixPointer = std::is_same<typename std::decay_t<Arg>, Matrix*>;
193
194 template <typename Arg>
195 using IsNullpointer =
196 std::is_same<typename std::decay_t<Arg>, std::nullptr_t>;
197
202 template <typename Ret, typename... Args>
204 std::enable_if_t<(... && (IsMatrixPointer<Args>::value ||
205 IsNullpointer<Args>::value)),
206 Ret>;
207
209
210 /* Like std::void_t, except produces `OptionalMatrixType` instead of
211 * `void`. Used to expand fixed-type parameter-packs with same length as
212 * ValueTypes. */
213 template <typename T = void>
214 using OptionalMatrixTypeT = Matrix*;
215
216 /* Like std::void_t, except produces `Key` instead of `void`. Used to expand
217 * fixed-type parameter-packs with same length as ValueTypes. */
218 template <typename T>
219 using KeyType = Key;
220
221 /* Like std::void_t, except produces `Matrix` instead of
222 * `void`. Used to expand fixed-type parameter-packs with same length as
223 * ValueTypes. This helps in creating an evaluateError overload that accepts
224 * Matrices instead of pointers to matrices */
225 template <typename T = void>
226 using MatrixTypeT = Matrix;
227
228 public:
248 template <int I, typename = IndexIsValid<I>>
249 using ValueType =
250 typename std::tuple_element<I - 1, std::tuple<ValueTypes...>>::type;
251
252 public:
255
258
267 KeyType<ValueTypes>... keys)
268 : Base(noiseModel, std::array<Key, N>{keys...}) {}
269
278 template <typename CONTAINER = std::initializer_list<Key>,
279 typename = IsContainerOfKeys<CONTAINER>>
281 : Base(noiseModel, keys) {
282 if (keys.size() != N) {
283 throw std::invalid_argument(
284 "NoiseModelFactorT: wrong number of keys given");
286 }
287
289
290 ~NoiseModelFactorT() override {}
291
306 template <int I = 1>
307 inline Key key() const {
308 static_assert(I <= N, "Index out of bounds");
309 return keys_[I - 1];
310 }
311
314
320 std::shared_ptr<GaussianFactor> linearize(
321 const Values& values) const override {
322 using Dimensions = internal::FixedSizeDimensions<OutputVec, ValueTypes...>;
324 Dimensions::M, traits<ValueTypes>::dimension...>;
325 using UseFixed = std::bool_constant<Dimensions::allFixed &&
326 Factory::available>;
327 return linearizeImpl<Factory>(values, UseFixed{});
328 }
329
330 private:
332 template <typename Factory>
333 std::shared_ptr<GaussianFactor> linearizeImpl(const Values& values,
334 std::true_type) const {
335 using Dimensions = internal::FixedSizeDimensions<OutputVec, ValueTypes...>;
336 constexpr int M = Dimensions::M;
337 static_assert(M > 0 && ((traits<ValueTypes>::dimension > 0) && ...),
338 "Fixed factor dimensions must be positive");
339
340 if (!this->active(values)) return std::shared_ptr<JacobianFactor>();
341
342 std::vector<Matrix> jacobians(Dimensions::arity);
343 Vector b = -this->unwhitenedError(values, jacobians);
344 const SharedNoiseModel& noiseModel = this->noiseModel();
345 if (noiseModel && static_cast<size_t>(b.size()) != noiseModel->dim()) {
346 throw std::invalid_argument(
347 "NoiseModelFactor: NoiseModel has dimension " +
348 std::to_string(noiseModel->dim()) + " instead of " +
349 std::to_string(b.size()) + ".");
350 }
351 if (b.size() != M || jacobians.size() != Dimensions::arity ||
352 !internal::dimensionsMatch<Dimensions>(
353 jacobians, std::make_index_sequence<Dimensions::arity>{})) {
354 throw std::invalid_argument(
355 "NoiseModelFactorT::linearize: error or Jacobian dimension "
356 "mismatch");
357 }
358
359 if (noiseModel) {
360 noiseModel->WhitenSystem(jacobians, b);
361 }
362
363 SharedDiagonal linearModel;
364 if (noiseModel && noiseModel->isConstrained()) {
365 const auto constrained =
366 std::static_pointer_cast<noiseModel::Constrained>(noiseModel);
367 linearModel = constrained->unit();
368 }
369
370 return Factory::create(this->keys_, jacobians, b, linearModel);
371 }
372
374 template <typename Factory>
375 std::shared_ptr<GaussianFactor> linearizeImpl(const Values& values,
376 std::false_type) const {
377 return NoiseModelFactor::linearize(values);
378 }
379
380 public:
381
398 Vector unwhitenedError(const Values& x,
399 OptionalMatrixVecType H = nullptr) const override {
400 return unwhitenedError(gtsam::index_sequence_for<ValueTypes...>{}, x, H);
401 }
402
406
429 virtual OutputVec evaluateError(
430 const ValueTypes&... x, OptionalMatrixTypeT<ValueTypes>... H) const = 0;
431
439 Vector evaluateError(const ValueTypes&... x,
440 MatrixTypeT<ValueTypes>&... H) const {
441 return evaluateError(x..., (&H)...);
442 }
443
447
454 inline Vector evaluateError(const ValueTypes&... x) const {
455 return evaluateError(x..., OptionalMatrixTypeT<ValueTypes>()...);
456 }
457
462 template <typename... OptionalJacArgs,
463 typename = IndexIsValid<sizeof...(OptionalJacArgs) + 1>>
465 const ValueTypes&... x, OptionalJacArgs&&... H) const {
466 return evaluateError(x..., (&H)...);
467 }
468
473 template <typename... OptionalJacArgs,
474 typename = IndexIsValid<sizeof...(OptionalJacArgs) + 1>>
476 const ValueTypes&... x, OptionalJacArgs&&... H) const {
477 // If they are pointer version, ensure to cast them all to be Matrix* types
478 // This will ensure any arguments inferred as std::nonetype_t are cast to
479 // (Matrix*) nullptr This guides the compiler to the correct overload which
480 // is the one that takes pointers
481 return evaluateError(x..., std::forward<OptionalJacArgs>(H)...,
482 static_cast<OptionalMatrixType>(OptionalNone));
483 }
484
486
487 private:
494 template <std::size_t... Indices>
496 const Values& x,
497 OptionalMatrixVecType H = nullptr) const {
498 if (this->active(x)) {
499 if (H) {
500 return evaluateError(x.at<ValueTypes>(keys_[Indices])...,
501 (*H)[Indices]...);
502 } else {
503 return evaluateError(x.at<ValueTypes>(keys_[Indices])...);
504 }
505 } else {
506 return Vector::Zero(this->dim());
507 }
508 }
509
510#if GTSAM_ENABLE_BOOST_SERIALIZATION
512 friend class boost::serialization::access;
513 template <class ARCHIVE>
514 void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
515 ar& boost::serialization::make_nvp(
516 "NoiseModelFactor", boost::serialization::base_object<Base>(*this));
517 }
518#endif
519
520 public:
523
524 inline Key key1() const { return key<1>(); }
525 template <int I = 2>
526 inline Key key2() const {
527 static_assert(I <= N, "Index out of bounds");
528 return key<2>();
529 }
530 template <int I = 3>
531 inline Key key3() const {
532 static_assert(I <= N, "Index out of bounds");
533 return key<3>();
534 }
535 template <int I = 4>
536 inline Key key4() const {
537 static_assert(I <= N, "Index out of bounds");
538 return key<4>();
539 }
540 template <int I = 5>
541 inline Key key5() const {
542 static_assert(I <= N, "Index out of bounds");
543 return key<5>();
544 }
545 template <int I = 6>
546 inline Key key6() const {
547 static_assert(I <= N, "Index out of bounds");
548 return key<6>();
549 }
550
552
553}; // \class NoiseModelFactorT
554
560template <class... ValueTypes>
561using NoiseModelFactorN = NoiseModelFactorT<Vector, ValueTypes...>;
562
563#define NoiseModelFactor1 NoiseModelFactorN
564#define NoiseModelFactor2 NoiseModelFactorN
565#define NoiseModelFactor3 NoiseModelFactorN
566#define NoiseModelFactor4 NoiseModelFactorN
567#define NoiseModelFactor5 NoiseModelFactorN
568#define NoiseModelFactor6 NoiseModelFactorN
569} // namespace gtsam
Arbitrary-arity Jacobian factor with compile-time block dimensions.
Non-linear factor base classes.
#define OptionalNone
These typedefs and aliases will help with making the evaluateError interface independent of boost TOD...
Definition NonlinearFactor.h:51
STL namespace.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
Matrix * OptionalMatrixType
This typedef will be used everywhere boost::optional<Matrix&> reference was used previously.
Definition NonlinearFactor.h:57
NoiseModelFactorT< Vector, ValueTypes... > NoiseModelFactorN
Noise model factor with N value types and dynamic-sized error vector.
Definition NoiseModelFactorN.h:561
std::vector< Matrix > * OptionalMatrixVecType
The OptionalMatrixVecType is a pointer to a vector of matrices.
Definition NonlinearFactor.h:63
noiseModel::Base::shared_ptr SharedNoiseModel
Aliases.
Definition NoiseModel.h:846
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
All noise models live in the noiseModel namespace.
Definition LossFunctions.cpp:33
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
Definition utilities.h:44
const KeyVector & keys() const
Access the factor's involved variable keys.
Definition Factor.h:143
KeyVector keys_
The keys involved in this factor.
Definition Factor.h:88
Compile-time residual and variable dimensions for a factor of any arity.
Definition FixedJacobianFactor.h:48
Construct the fixed-size Jacobian factor for a dimension pack.
Definition FixedJacobianFactor.h:327
Convenience base class to add aliases X1, X2, ..., X6 -> ValueType<N>.
Definition NoiseModelFactorN.h:49
A convenient base class for creating your own NoiseModelFactor with n variables.
Definition NoiseModelFactorN.h:155
NoiseModelFactorT()
Default Constructor for I/O.
Definition NoiseModelFactorN.h:257
std::enable_if_t<(... &&(IsMatrixPointer< Args >::value||IsNullpointer< Args >::value)), Ret > AreAllMatrixPtrs
Definition NoiseModelFactorN.h:203
Vector evaluateError(const ValueTypes &... x, MatrixTypeT< ValueTypes > &... H) const
If all the optional arguments are matrices then redirect the call to the one which takes pointers.
Definition NoiseModelFactorN.h:439
NoiseModelFactorT(const SharedNoiseModel &noiseModel, KeyType< ValueTypes >... keys)
Constructor.
Definition NoiseModelFactorN.h:266
std::enable_if_t<(... &&std::is_convertible< Args, Matrix & >::value), Ret > AreAllMatrixRefs
Definition NoiseModelFactorN.h:188
Vector evaluateError(const ValueTypes &... x) const
No-Jacobians requested function overload.
Definition NoiseModelFactorN.h:454
virtual OutputVec evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const =0
Override evaluateError to finish implementing an n-way factor.
AreAllMatrixPtrs< Vector, OptionalJacArgs... > evaluateError(const ValueTypes &... x, OptionalJacArgs &&... H) const
Some (but not all) optional Jacobians are omitted (function overload) and the jacobians are pointers ...
Definition NoiseModelFactorN.h:475
typename std::tuple_element< I - 1, std::tuple< ValueTypes... > >::type ValueType
Definition NoiseModelFactorN.h:249
static constexpr auto N
Definition NoiseModelFactorN.h:158
Key key() const
Returns a key.
Definition NoiseModelFactorN.h:307
AreAllMatrixRefs< Vector, OptionalJacArgs... > evaluateError(const ValueTypes &... x, OptionalJacArgs &&... H) const
Some (but not all) optional Jacobians are omitted (function overload) and the jacobians are l-value r...
Definition NoiseModelFactorN.h:464
Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const override
This implements the unwhitenedError virtual function by calling the n-key specific version of evaluat...
Definition NoiseModelFactorN.h:398
std::shared_ptr< GaussianFactor > linearize(const Values &values) const override
Linearize factors whose error and argument dimensions are all fixed to an arbitrary-arity FixedJacobi...
Definition NoiseModelFactorN.h:320
NoiseModelFactorT(const SharedNoiseModel &noiseModel, CONTAINER keys)
Constructor.
Definition NoiseModelFactorN.h:280
virtual bool active(const Values &c) const
Checks whether a factor should be used based on a set of values.
Definition NonlinearFactor.h:143
std::shared_ptr< GaussianFactor > linearize(const Values &x) const override
Linearize a non-linearFactorN to get a GaussianFactor, Hence .
Definition NonlinearFactor.cpp:160
virtual Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const =0
Error function without the NoiseModel, .
size_t dim() const override
get the dimension of the factor (number of rows on linearization)
Definition NonlinearFactor.h:251
NoiseModelFactor()
Default constructor for I/O only.
Definition NonlinearFactor.h:223
const SharedNoiseModel & noiseModel() const
access to the noise model
Definition NonlinearFactor.h:258
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65
const ValueType at(Key j) const
Retrieve a variable by key j.
Definition Values-inl.h:260