gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExtendedKalmanFilter-inl.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 
19 #pragma once
20 
25 
26 namespace gtsam {
27 
28  /* ************************************************************************* */
29  template<class VALUE>
30  typename ExtendedKalmanFilter<VALUE>::T ExtendedKalmanFilter<VALUE>::solve_(
31  const GaussianFactorGraph& linearFactorGraph,
32  const Values& linearizationPoints, Key lastKey,
33  JacobianFactor::shared_ptr& newPrior) const
34  {
35  // Compute the marginal on the last key
36  // Solve the linear factor graph, converting it into a linear Bayes Network
37  // P(x0,x1) = P(x0|x1)*P(x1)
38  Ordering lastKeyAsOrdering;
39  lastKeyAsOrdering += lastKey;
40  const GaussianConditional::shared_ptr marginal =
41  linearFactorGraph.marginalMultifrontalBayesNet(lastKeyAsOrdering)->front();
42 
43  // Extract the current estimate of x1,P1
44  VectorValues result = marginal->solve(VectorValues());
45  T x = linearizationPoints.at<T>(lastKey).retract(result[lastKey]);
46 
47  // Create a Jacobian Factor from the root node of the produced Bayes Net.
48  // This will act as a prior for the next iteration.
49  // The linearization point of this prior must be moved to the new estimate of x,
50  // and the key/index needs to be reset to 0, the first key in the next iteration.
51  assert(marginal->nrFrontals() == 1);
52  assert(marginal->nrParents() == 0);
53  newPrior = boost::make_shared<JacobianFactor>(
54  marginal->keys().front(),
55  marginal->getA(marginal->begin()),
56  marginal->getb() - marginal->getA(marginal->begin()) * result[lastKey],
57  marginal->get_model());
58 
59  return x;
60  }
61 
62  /* ************************************************************************* */
63  template<class VALUE>
64  ExtendedKalmanFilter<VALUE>::ExtendedKalmanFilter(Key key_initial, T x_initial,
65  noiseModel::Gaussian::shared_ptr P_initial) {
66 
67  // Set the initial linearization point to the provided mean
68  x_ = x_initial;
69 
70  // Create a Jacobian Prior Factor directly P_initial.
71  // Since x0 is set to the provided mean, the b vector in the prior will be zero
72  // TODO Frank asks: is there a reason why noiseModel is not simply P_initial ?
73  priorFactor_ = JacobianFactor::shared_ptr(
74  new JacobianFactor(key_initial, P_initial->R(), Vector::Zero(x_initial.dim()),
75  noiseModel::Unit::Create(P_initial->dim())));
76  }
77 
78  /* ************************************************************************* */
79  template<class VALUE>
80  typename ExtendedKalmanFilter<VALUE>::T ExtendedKalmanFilter<VALUE>::predict(
81  const MotionFactor& motionFactor) {
82 
83  // TODO: This implementation largely ignores the actual factor symbols.
84  // Calling predict() then update() with drastically
85  // different keys will still compute as if a common key-set was used
86 
87  // Create Keys
88  Key x0 = motionFactor.key1();
89  Key x1 = motionFactor.key2();
90 
91  // Create a set of linearization points
92  Values linearizationPoints;
93  linearizationPoints.insert(x0, x_);
94  linearizationPoints.insert(x1, x_); // TODO should this really be x_ ?
95 
96  // Create a Gaussian Factor Graph
97  GaussianFactorGraph linearFactorGraph;
98 
99  // Add in previous posterior as prior on the first state
100  linearFactorGraph.push_back(priorFactor_);
101 
102  // Linearize motion model and add it to the Kalman Filter graph
103  linearFactorGraph.push_back(
104  motionFactor.linearize(linearizationPoints));
105 
106  // Solve the factor graph and update the current state estimate
107  // and the posterior for the next iteration.
108  x_ = solve_(linearFactorGraph, linearizationPoints, x1, priorFactor_);
109 
110  return x_;
111  }
112 
113  /* ************************************************************************* */
114  template<class VALUE>
115  typename ExtendedKalmanFilter<VALUE>::T ExtendedKalmanFilter<VALUE>::update(
116  const MeasurementFactor& measurementFactor) {
117 
118  // TODO: This implementation largely ignores the actual factor symbols.
119  // Calling predict() then update() with drastically
120  // different keys will still compute as if a common key-set was used
121 
122  // Create Keys
123  Key x0 = measurementFactor.key();
124 
125  // Create a set of linearization points
126  Values linearizationPoints;
127  linearizationPoints.insert(x0, x_);
128 
129  // Create a Gaussian Factor Graph
130  GaussianFactorGraph linearFactorGraph;
131 
132  // Add in the prior on the first state
133  linearFactorGraph.push_back(priorFactor_);
134 
135  // Linearize measurement factor and add it to the Kalman Filter graph
136  linearFactorGraph.push_back(
137  measurementFactor.linearize(linearizationPoints));
138 
139  // Solve the factor graph and update the current state estimate
140  // and the prior factor for the next iteration
141  x_ = solve_(linearFactorGraph, linearizationPoints, x0, priorFactor_);
142 
143  return x_;
144  }
145 
146 } // namespace gtsam
Non-linear factor base classes.
T predict(const MotionFactor &motionFactor)
TODO: comment.
Definition: ExtendedKalmanFilter-inl.h:80
static shared_ptr Create(size_t dim)
Create a unit covariance noise model.
Definition: NoiseModel.h:585
T update(const MeasurementFactor &measurementFactor)
TODO: comment.
Definition: ExtendedKalmanFilter-inl.h:115
void insert(Key j, const Value &val)
Add a variable with the given j, throws KeyAlreadyExists<J> if j is already present.
Definition: Values.cpp:127
Chordal Bayes Net, the result of eliminating a factor graph.
boost::shared_ptr< GaussianFactor > linearize(const Values &x) const
Linearize a non-linearFactorN to get a GaussianFactor, Hence .
Definition: NonlinearFactor.h:297
boost::enable_if< boost::is_base_of< FactorType, DERIVEDFACTOR > >::type push_back(boost::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:155
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:75
boost::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianConditional.h:42
Key key1() const
methods to retrieve both keys
Definition: NonlinearFactor.h:455
size_t Key
Integer nonlinear key type.
Definition: types.h:59
A convenient base class for creating your own NoiseModelFactor with 1 variable.
Definition: NonlinearFactor.h:354
A Linear Factor Graph is a factor graph where all factors are Gaussian, i.e.
Definition: GaussianFactorGraph.h:65
Class to perform generic Kalman Filtering using nonlinear factor graphs.
boost::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: JacobianFactor.h:87
Linear Factor Graph where all factors are Gaussians.