gtsam
Loading...
Searching...
No Matches
ExpressionFactor.h
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
19
20#pragma once
21
22#include <array>
23#include <gtsam/config.h>
24#include <gtsam/base/Testable.h>
27
28#include <numeric>
29#include <utility>
30
31namespace gtsam {
32
45template <typename T>
47 GTSAM_CONCEPT_ASSERT(IsTestable<T>);
48
49protected:
50
51 typedef ExpressionFactor<T> This;
52 static const int Dim = traits<T>::dimension;
53
57
58
59 public:
60
61 // Provide access to the Matrix& version of unwhitenedError:
63 typedef std::shared_ptr<ExpressionFactor<T> > shared_ptr;
64
73 const T& measurement, const Expression<T>& expression)
74 : NoiseModelFactor(noiseModel), measured_(measurement) {
76 }
77
79 ~ExpressionFactor() override {}
80
82 const T& measured() const { return measured_; }
83
85 void print(const std::string& s = "",
86 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
87 NoiseModelFactor::print(s, keyFormatter);
88 traits<T>::Print(measured_, "ExpressionFactor with measurement: ");
89 }
90
92 bool equals(const NonlinearFactor& f, double tol) const override {
93 const ExpressionFactor* p = dynamic_cast<const ExpressionFactor*>(&f);
94 return p && NoiseModelFactor::equals(f, tol) &&
96 dims_ == p->dims_;
97 }
98
104 Vector unwhitenedError(const Values& x,
105 OptionalMatrixVecType H = nullptr) const override {
106 if (H) {
107 const T value = expression_.valueAndDerivatives(x, keys_, dims_, *H);
108 // NOTE(hayk): Doing the reverse, AKA Local(measured_, value) is not correct here
109 // because it would use the tangent space of the measurement instead of the value.
110 return -traits<T>::Local(value, measured_);
111 } else {
112 const T value = expression_.value(x);
113 return -traits<T>::Local(value, measured_);
114 }
115 }
116
117 std::shared_ptr<GaussianFactor> linearize(const Values& x) const override {
118 // Only linearize if the factor is active
119 if (!active(x))
120 return std::shared_ptr<JacobianFactor>();
121
122 // In case noise model is constrained, we need to provide a noise model
123 SharedDiagonal noiseModel;
124 if (noiseModel_ && noiseModel_->isConstrained()) {
125 noiseModel = std::static_pointer_cast<noiseModel::Constrained>(
126 noiseModel_)->unit();
127 }
128
129 // Create a writeable JacobianFactor in advance
130 std::shared_ptr<JacobianFactor> factor(
132
133 // Wrap keys and VerticalBlockMatrix into structure passed to expression_
134 VerticalBlockMatrix& Ab = factor->matrixObject();
135 internal::JacobianMap jacobianMap(keys_, Ab);
136
137 // Zero out Jacobian so we can simply add to it
138 Ab.matrix().setZero();
139
140 // Get value and Jacobians, writing directly into JacobianFactor
141 T value = expression_.valueAndJacobianMap(x, jacobianMap); // <<< Reverse AD happens here !
142
143 // Evaluate error and set RHS vector b
144 Ab(size()).col(0) = traits<T>::Local(value, measured_);
145
146 // Whiten the corresponding system, Ab already contains RHS
147 if (noiseModel_) {
148 Vector b = Ab(size()).col(0); // need b to be valid for Robust noise models
149 noiseModel_->WhitenSystem(Ab.matrix(), b);
150 }
151
152 return factor;
153 }
154
156 gtsam::NonlinearFactor::shared_ptr clone() const override {
157 return std::static_pointer_cast<gtsam::NonlinearFactor>(
158 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
159 }
160
161protected:
164
166 ExpressionFactor(const SharedNoiseModel& noiseModel, const T& measurement)
167 : NoiseModelFactor(noiseModel), measured_(measurement) {
168 // Not properly initialized yet, need to call initialize
169 }
170
173 if (!noiseModel_)
174 throw std::invalid_argument("ExpressionFactor: no NoiseModel.");
175 if (noiseModel_->dim() != Dim)
176 throw std::invalid_argument(
177 "ExpressionFactor was created with a NoiseModel of incorrect dimension.");
179
180 // Get keys and dimensions for Jacobian matrices
181 // An Expression is assumed unmutable, so we do this now
182 if (keys_.empty()) {
183 // This is the case when called in ExpressionFactor Constructor.
184 // We then take the keys from the expression in sorted order.
185 std::tie(keys_, dims_) = expression_.keysAndDims();
186 } else {
187 // This happens with classes derived from BinaryExpressionFactor etc.
188 // In that case, the keys_ are already defined and we just need to grab
189 // the dimensions in the correct order.
190 std::map<Key, int> keyedDims;
191 expression_.dims(keyedDims);
192 for (Key key : keys_) dims_.push_back(keyedDims[key]);
193 }
194 }
195
198 virtual Expression<T> expression() const {
199 throw std::runtime_error("ExpressionFactor::expression not provided: cannot deserialize.");
200 }
201
202private:
203#if GTSAM_ENABLE_BOOST_SERIALIZATION
205 template <class Archive>
206 void save(Archive& ar, const unsigned int /*version*/) const {
207 ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(NoiseModelFactor);
208 ar << boost::serialization::make_nvp("measured_", this->measured_);
209 }
210
213 template <class Archive>
214 void load(Archive& ar, const unsigned int /*version*/) {
215 ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(NoiseModelFactor);
216 ar >> boost::serialization::make_nvp("measured_", this->measured_);
217 this->initialize(expression());
218 }
219
220 // Indicate that we implement save/load separately, and be friendly to boost
221 BOOST_SERIALIZATION_SPLIT_MEMBER()
222
223 friend class boost::serialization::access;
224#endif
225};
226// ExpressionFactor
227
229template <typename T>
230struct traits<ExpressionFactor<T> > : public Testable<ExpressionFactor<T> > {};
231
243template <typename T, typename... Args>
245public:
246 static const std::size_t NARY_EXPRESSION_SIZE = sizeof...(Args);
247 using ArrayNKeys = std::array<Key, NARY_EXPRESSION_SIZE>;
248
249 // Provide access to the Matrix& version of unwhitenedError:
251
252 // Don't provide backward compatible evaluateVector(), due to its problematic
253 // variable length of optional Jacobian arguments. Vector evaluateError(const
254 // Args... args,...);
255
258 virtual Expression<T> expression(const ArrayNKeys &keys) const {
259 throw std::runtime_error(
260 "ExpressionFactorN::expression not provided: cannot deserialize.");
261 }
262
263protected:
265 ExpressionFactorN() = default;
266
269 const T &measurement)
270 : ExpressionFactor<T>(noiseModel, measurement) {
271 for (const auto &key : keys)
272 Factor::keys_.push_back(key);
273 }
274
275private:
277 Expression<T> expression() const override {
278 ArrayNKeys keys;
279 int idx = 0;
280 for (const auto &key : Factor::keys_)
281 keys[idx++] = key;
282 return expression(keys);
283 }
284
285#if GTSAM_ENABLE_BOOST_SERIALIZATION
286 friend class boost::serialization::access;
287 template <class ARCHIVE>
288 void serialize(ARCHIVE &ar, const unsigned int /*version*/) {
289 ar &boost::serialization::make_nvp(
290 "ExpressionFactorN",
291 boost::serialization::base_object<ExpressionFactor<T>>(*this));
292 }
293#endif
294};
295
296template <typename T, typename... Args>
297struct traits<ExpressionFactorN<T, Args...>>
298 : public Testable<ExpressionFactorN<T, Args...>> {};
299// ExpressionFactorN
300
301} // namespace gtsam
Concept check for values that can be used in unit tests.
Expressions for Block Automatic Differentiation.
Non-linear factor base classes.
std::vector< T, typename internal::FastDefaultVectorAllocator< T >::type > FastVector
FastVector is a type alias to a std::vector with a custom memory allocator.
Definition FastVector.h:33
Global functions in a separate testing namespace.
Definition chartTesting.h:28
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition Key.cpp:30
void save(const Matrix &A, const string &s, const string &filename)
save a matrix to file, which can be loaded by matlab
Definition Matrix.cpp:154
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition Key.h:35
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
A testable concept check that should be placed in applicable unit tests and in generic algorithms.
Definition Testable.h:59
A helper that implements the traits interface for GTSAM types.
Definition Testable.h:152
This class stores a dense matrix and allows it to be accessed as a collection of vertical blocks.
Definition VerticalBlockMatrix.h:47
const Matrix & matrix() const
Access to full matrix (including any portions excluded by rowStart(), rowEnd(), and firstBlock()).
Definition VerticalBlockMatrix.h:278
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
size_t size() const
Definition Factor.h:160
A Gaussian factor in the squared-error form.
Definition JacobianFactor.h:92
Factor that supports arbitrary expressions via AD.
Definition ExpressionFactor.h:46
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print relies on Testable traits being defined for T
Definition ExpressionFactor.h:85
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition ExpressionFactor.h:156
virtual Expression< T > expression() const
Recreate expression from keys_ and measured_, used in load below.
Definition ExpressionFactor.h:198
Expression< T > expression_
the expression that is AD enabled
Definition ExpressionFactor.h:55
T measured_
the measurement to be compared with the expression
Definition ExpressionFactor.h:54
FastVector< int > dims_
dimensions of the Jacobian matrices
Definition ExpressionFactor.h:56
Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const override
Error function without the NoiseModel, .
Definition ExpressionFactor.h:104
std::shared_ptr< GaussianFactor > linearize(const Values &x) const override
linearize to a GaussianFactor
Definition ExpressionFactor.h:117
const T & measured() const
return the measurement
Definition ExpressionFactor.h:82
~ExpressionFactor() override
Destructor.
Definition ExpressionFactor.h:79
bool equals(const NonlinearFactor &f, double tol) const override
equals relies on Testable traits being defined for T
Definition ExpressionFactor.h:92
ExpressionFactor(const SharedNoiseModel &noiseModel, const T &measurement)
Default constructor, for serialization.
Definition ExpressionFactor.h:166
ExpressionFactor(const SharedNoiseModel &noiseModel, const T &measurement, const Expression< T > &expression)
Constructor: creates a factor from a measurement and measurement function.
Definition ExpressionFactor.h:72
void initialize(const Expression< T > &expression)
Initialize with constructor arguments.
Definition ExpressionFactor.h:172
Expression class that supports automatic differentiation.
Definition Expression.h:49
N-ary variadic template for ExpressionFactor meant as a base class for N-ary factors.
Definition ExpressionFactor.h:244
virtual Expression< T > expression(const ArrayNKeys &keys) const
Recreate expression from given keys_ and measured_, used in load Needed to deserialize a derived fact...
Definition ExpressionFactor.h:258
ExpressionFactorN()=default
Default constructor, for serialization.
ExpressionFactorN(const ArrayNKeys &keys, const SharedNoiseModel &noiseModel, const T &measurement)
Constructor takes care of keys, but still need to call initialize.
Definition ExpressionFactor.h:268
Nonlinear factor base class.
Definition NonlinearFactor.h:70
virtual bool active(const Values &c) const
Checks whether a factor should be used based on a set of values.
Definition NonlinearFactor.h:143
A nonlinear sum-of-squares factor with a zero-mean noise model implementing the density Templated on...
Definition NonlinearFactor.h:208
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
Print.
Definition NonlinearFactor.cpp:82
virtual Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const =0
Error function without the NoiseModel, .
bool equals(const NonlinearFactor &f, double tol=1e-9) const override
Check if two factors are equal.
Definition NonlinearFactor.cpp:90
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
noise model to the factor, and calculates the error by asking the user to implement the method