2014-09-30 18:30:15 +08:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
|
|
|
* Atlanta, Georgia 30332-0415
|
|
|
|
|
* All Rights Reserved
|
|
|
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
|
|
|
|
|
|
* See LICENSE for the license information
|
|
|
|
|
|
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @file Expression.h
|
|
|
|
|
* @date September 18, 2014
|
|
|
|
|
* @author Frank Dellaert
|
|
|
|
|
* @author Paul Furgale
|
|
|
|
|
* @brief Expressions for Block Automatic Differentiation
|
|
|
|
|
*/
|
|
|
|
|
|
2014-11-22 21:55:32 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
2014-11-27 00:26:04 +08:00
|
|
|
#include <gtsam/nonlinear/Expression.h>
|
2014-09-30 18:30:15 +08:00
|
|
|
#include <gtsam/nonlinear/NonlinearFactor.h>
|
2014-10-02 17:01:39 +08:00
|
|
|
#include <gtsam/base/Testable.h>
|
2014-10-15 06:28:53 +08:00
|
|
|
#include <numeric>
|
2014-09-30 18:30:15 +08:00
|
|
|
|
|
|
|
|
namespace gtsam {
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-09 19:00:56 +08:00
|
|
|
* Factor that supports arbitrary expressions via AD
|
2014-09-30 18:30:15 +08:00
|
|
|
*/
|
|
|
|
|
template<class T>
|
2014-10-09 19:00:56 +08:00
|
|
|
class ExpressionFactor: public NoiseModelFactor {
|
2014-09-30 18:30:15 +08:00
|
|
|
|
2014-12-10 17:43:08 +08:00
|
|
|
protected:
|
|
|
|
|
|
2014-10-16 17:15:47 +08:00
|
|
|
T measurement_; ///< the measurement to be compared with the expression
|
|
|
|
|
Expression<T> expression_; ///< the expression that is AD enabled
|
2014-11-25 18:29:50 +08:00
|
|
|
FastVector<int> dims_; ///< dimensions of the Jacobian matrices
|
2014-09-30 18:30:15 +08:00
|
|
|
|
2014-12-21 03:36:54 +08:00
|
|
|
static const int Dim = traits_x<T>::dimension;
|
2014-10-21 07:26:17 +08:00
|
|
|
|
2014-09-30 18:30:15 +08:00
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
/// Constructor
|
2014-10-09 19:00:56 +08:00
|
|
|
ExpressionFactor(const SharedNoiseModel& noiseModel, //
|
2014-10-02 17:01:39 +08:00
|
|
|
const T& measurement, const Expression<T>& expression) :
|
2014-09-30 18:30:15 +08:00
|
|
|
measurement_(measurement), expression_(expression) {
|
2014-10-14 17:13:49 +08:00
|
|
|
if (!noiseModel)
|
|
|
|
|
throw std::invalid_argument("ExpressionFactor: no NoiseModel.");
|
2014-10-21 07:26:17 +08:00
|
|
|
if (noiseModel->dim() != Dim)
|
2014-10-14 17:13:49 +08:00
|
|
|
throw std::invalid_argument(
|
|
|
|
|
"ExpressionFactor was created with a NoiseModel of incorrect dimension.");
|
2014-10-16 18:01:20 +08:00
|
|
|
noiseModel_ = noiseModel;
|
2014-10-16 17:15:47 +08:00
|
|
|
|
2014-11-25 17:53:26 +08:00
|
|
|
// Get keys and dimensions for Jacobian matrices
|
2014-10-16 17:15:47 +08:00
|
|
|
// An Expression is assumed unmutable, so we do this now
|
2014-11-25 18:29:50 +08:00
|
|
|
boost::tie(keys_, dims_) = expression_.keysAndDims();
|
2014-09-30 18:30:15 +08:00
|
|
|
}
|
|
|
|
|
|
2014-10-02 17:01:39 +08:00
|
|
|
/**
|
2014-11-01 18:50:28 +08:00
|
|
|
* Error function *without* the NoiseModel, \f$ h(x)-z \f$.
|
2014-10-02 17:01:39 +08:00
|
|
|
* We override this method to provide
|
|
|
|
|
* both the function evaluation and its derivative(s) in H.
|
|
|
|
|
*/
|
|
|
|
|
virtual Vector unwhitenedError(const Values& x,
|
|
|
|
|
boost::optional<std::vector<Matrix>&> H = boost::none) const {
|
2014-12-21 03:36:54 +08:00
|
|
|
if (H) {
|
2014-11-25 23:13:30 +08:00
|
|
|
const T value = expression_.value(x, keys_, dims_, *H);
|
2014-12-21 03:36:54 +08:00
|
|
|
return traits_x<T>::Local(measurement_, value);
|
2014-10-02 17:01:39 +08:00
|
|
|
} else {
|
2014-11-25 18:29:50 +08:00
|
|
|
const T value = expression_.value(x);
|
2014-12-21 03:36:54 +08:00
|
|
|
return traits_x<T>::Local(measurement_, value);
|
2014-10-02 17:01:39 +08:00
|
|
|
}
|
2014-09-30 18:30:15 +08:00
|
|
|
}
|
|
|
|
|
|
2014-10-15 06:28:53 +08:00
|
|
|
virtual boost::shared_ptr<GaussianFactor> linearize(const Values& x) const {
|
2014-11-02 20:53:22 +08:00
|
|
|
// Only linearize if the factor is active
|
2014-11-02 21:37:52 +08:00
|
|
|
if (!active(x))
|
2014-11-02 20:53:22 +08:00
|
|
|
return boost::shared_ptr<JacobianFactor>();
|
|
|
|
|
|
2014-11-01 22:12:06 +08:00
|
|
|
// Create a writeable JacobianFactor in advance
|
2014-11-02 20:45:54 +08:00
|
|
|
// In case noise model is constrained, we need to provide a noise model
|
2014-11-26 19:33:17 +08:00
|
|
|
bool constrained = noiseModel_->isConstrained();
|
2014-11-02 18:40:48 +08:00
|
|
|
boost::shared_ptr<JacobianFactor> factor(
|
2014-11-25 18:29:50 +08:00
|
|
|
constrained ? new JacobianFactor(keys_, dims_, Dim,
|
2014-11-02 20:45:54 +08:00
|
|
|
boost::static_pointer_cast<noiseModel::Constrained>(noiseModel_)->unit()) :
|
2014-11-25 18:29:50 +08:00
|
|
|
new JacobianFactor(keys_, dims_, Dim));
|
2014-10-12 17:05:43 +08:00
|
|
|
|
2014-11-01 18:35:49 +08:00
|
|
|
// Wrap keys and VerticalBlockMatrix into structure passed to expression_
|
2014-11-02 19:01:52 +08:00
|
|
|
VerticalBlockMatrix& Ab = factor->matrixObject();
|
2014-11-25 17:53:26 +08:00
|
|
|
JacobianMap jacobianMap(keys_, Ab);
|
2014-11-02 19:01:52 +08:00
|
|
|
|
|
|
|
|
// Zero out Jacobian so we can simply add to it
|
|
|
|
|
Ab.matrix().setZero();
|
2014-10-19 17:19:09 +08:00
|
|
|
|
2014-11-25 18:29:50 +08:00
|
|
|
// Get value and Jacobians, writing directly into JacobianFactor
|
2014-11-25 17:53:26 +08:00
|
|
|
T value = expression_.value(x, jacobianMap); // <<< Reverse AD happens here !
|
2014-11-25 18:29:50 +08:00
|
|
|
|
|
|
|
|
// Evaluate error and set RHS vector b
|
2014-12-21 03:36:54 +08:00
|
|
|
Ab(size()).col(0) = -traits_x<T>::Local(measurement_, value);
|
2014-10-14 17:13:49 +08:00
|
|
|
|
2014-11-02 21:42:59 +08:00
|
|
|
// Whiten the corresponding system, Ab already contains RHS
|
|
|
|
|
Vector dummy(Dim);
|
2014-11-25 18:29:50 +08:00
|
|
|
noiseModel_->WhitenSystem(Ab.matrix(), dummy);
|
2014-10-11 23:05:53 +08:00
|
|
|
|
2014-11-01 22:12:06 +08:00
|
|
|
return factor;
|
2014-10-11 23:05:53 +08:00
|
|
|
}
|
2014-09-30 18:30:15 +08:00
|
|
|
};
|
2014-10-09 19:00:56 +08:00
|
|
|
// ExpressionFactor
|
2014-09-30 18:30:15 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|