dcsam
Factored inference for discrete-continuous smoothing and mapping
DCFactor.h
Go to the documentation of this file.
1 
8 #pragma once
9 
10 #include <gtsam/discrete/DiscreteFactor.h>
11 #include <gtsam/discrete/DiscreteKey.h>
12 #include <gtsam/nonlinear/NonlinearFactor.h>
13 #include <gtsam/nonlinear/Symbol.h>
14 #include <math.h>
15 
16 #include <algorithm>
17 #include <limits>
18 #include <string>
19 #include <vector>
20 
21 #include "dcsam/DCSAM_types.h"
22 #include "dcsam/DCSAM_utils.h"
23 
24 namespace dcsam {
25 
33 class DCFactor : public gtsam::Factor {
34  protected:
35  // Set of DiscreteKeys for this factor.
36  gtsam::DiscreteKeys discreteKeys_;
37 
38  public:
39  using Base = gtsam::Factor;
40 
41  DCFactor() = default;
42 
50  DCFactor(const gtsam::KeyVector& continuousKeys,
51  const gtsam::DiscreteKeys& discreteKeys)
52  : Base(continuousKeys), discreteKeys_(discreteKeys) {}
53 
54  // NOTE unsure if needed?
55  explicit DCFactor(const gtsam::DiscreteKeys& discreteKeys)
57 
58  DCFactor& operator=(const DCFactor& rhs) {
59  Base::operator=(rhs);
61  return *this;
62  }
63 
64  virtual ~DCFactor() = default;
65 
85  virtual double error(
86  const gtsam::Values& continuousVals,
87  const gtsam::DiscreteFactor::Values& discreteVals) const = 0;
88 
102  virtual boost::shared_ptr<gtsam::GaussianFactor> linearize(
103  const gtsam::Values& continuousVals,
104  const DiscreteValues& discreteVals) const = 0;
105 
115  virtual bool equals(const DCFactor& other, double tol = 1e-9) const = 0;
116 
130  virtual size_t dim() const = 0;
131 
132  /*
133  * Return the discrete keys for this factor.
134  */
135  gtsam::DiscreteKeys discreteKeys() const { return discreteKeys_; }
136 
156  virtual gtsam::DecisionTreeFactor toDecisionTreeFactor(
157  const gtsam::Values& continuousVals,
158  const DiscreteValues& discreteVals) const {
159  gtsam::DecisionTreeFactor converted;
160  for (const gtsam::DiscreteKey& dkey : discreteKeys_) {
161  std::vector<double> probs = evalProbs(dkey, continuousVals);
162  // Cardinality of gtsam::DiscreteKey is located at `second`
163  assert(probs.size() == dkey.second);
164  gtsam::DecisionTreeFactor unary(dkey, probs);
165  converted = converted * unary;
166  }
167  return converted;
168  }
169 
178  virtual double logNormalizingConstant(const gtsam::Values& values) const {
179  throw std::logic_error(
180  "Normalizing constant not implemented."
181  "One or more of the factors in use requires access to the normalization"
182  "constant for a child class of DCFactor, but`logNormalizingConstant` "
183  "has not been overridden.");
184  }
185 
192  template <typename NonlinearFactorType>
194  const NonlinearFactorType& factor, const gtsam::Values& values) const {
195  // Information matrix (inverse covariance matrix) for the factor.
196  gtsam::Matrix infoMat;
197 
198  // NOTE: This is sloppy, is there a cleaner way?
199  boost::shared_ptr<NonlinearFactorType> fPtr =
200  boost::make_shared<NonlinearFactorType>(factor);
201  boost::shared_ptr<NonlinearFactorType> factorPtr(fPtr);
202 
203  // If this is a NoiseModelFactor, we'll use its noiseModel to
204  // otherwise noiseModelFactor will be nullptr
205  boost::shared_ptr<gtsam::NoiseModelFactor> noiseModelFactor =
206  boost::dynamic_pointer_cast<gtsam::NoiseModelFactor>(factorPtr);
207  if (noiseModelFactor) {
208  // If dynamic cast to NoiseModelFactor succeeded, see if the noise model
209  // is Gaussian
210  gtsam::noiseModel::Base::shared_ptr noiseModel =
211  noiseModelFactor->noiseModel();
212 
213  boost::shared_ptr<gtsam::noiseModel::Gaussian> gaussianNoiseModel =
214  boost::dynamic_pointer_cast<gtsam::noiseModel::Gaussian>(noiseModel);
215  if (gaussianNoiseModel) {
216  // If the noise model is Gaussian, retrieve the information matrix
217  infoMat = gaussianNoiseModel->information();
218  } else {
219  // If the factor is not a Gaussian factor, we'll linearize it to get
220  // something with a normalized noise model
221  // TODO(kevin): does this make sense to do? I think maybe not in
222  // general? Should we just yell at the user?
223  boost::shared_ptr<gtsam::GaussianFactor> gaussianFactor =
224  factor.linearize(values);
225  infoMat = gaussianFactor->information();
226  }
227  }
228 
229  // Compute the (negative) log of the normalizing constant
230  return (factor.dim() * log(2.0 * M_PI) / 2.0) -
231  (log(infoMat.determinant()) / 2.0);
232  }
233 
254  std::vector<double> evalProbs(const gtsam::DiscreteKey& dk,
255  const gtsam::Values& continuousVals) const {
256  std::vector<double> logProbs;
257  for (size_t i = 0; i < dk.second; i++) {
258  DiscreteValues testDiscreteVals;
259  testDiscreteVals[dk.first] = i;
260  // Recall: `error` returns -log(prob), so we compute exp(-error) to
261  // recover probability
262  double logProb = -error(continuousVals, testDiscreteVals);
263  logProbs.push_back(logProb);
264  }
265  return expNormalize(logProbs);
266  }
267 
280  gtsam::DecisionTreeFactor conditionalTimes(
281  const gtsam::DecisionTreeFactor& f, const gtsam::Values& continuousVals,
282  const DiscreteValues& discreteVals) const {
283  return toDecisionTreeFactor(continuousVals, discreteVals) * f;
284  }
285 };
286 } // namespace dcsam
Some convenient types for DCSAM.
Some utilities for DCSAM.
Abstract class implementing a discrete-continuous factor.
Definition: DCFactor.h:33
virtual boost::shared_ptr< gtsam::GaussianFactor > linearize(const gtsam::Values &continuousVals, const DiscreteValues &discreteVals) const =0
gtsam::DiscreteKeys discreteKeys_
Definition: DCFactor.h:36
std::vector< double > evalProbs(const gtsam::DiscreteKey &dk, const gtsam::Values &continuousVals) const
Definition: DCFactor.h:254
DCFactor & operator=(const DCFactor &rhs)
Definition: DCFactor.h:58
virtual gtsam::DecisionTreeFactor toDecisionTreeFactor(const gtsam::Values &continuousVals, const DiscreteValues &discreteVals) const
Definition: DCFactor.h:156
gtsam::DiscreteKeys discreteKeys() const
Definition: DCFactor.h:135
virtual size_t dim() const =0
DCFactor(const gtsam::KeyVector &continuousKeys, const gtsam::DiscreteKeys &discreteKeys)
Definition: DCFactor.h:50
gtsam::DecisionTreeFactor conditionalTimes(const gtsam::DecisionTreeFactor &f, const gtsam::Values &continuousVals, const DiscreteValues &discreteVals) const
Definition: DCFactor.h:280
DCFactor(const gtsam::DiscreteKeys &discreteKeys)
Definition: DCFactor.h:55
virtual double logNormalizingConstant(const gtsam::Values &values) const
Definition: DCFactor.h:178
gtsam::Factor Base
Definition: DCFactor.h:39
double nonlinearFactorLogNormalizingConstant(const NonlinearFactorType &factor, const gtsam::Values &values) const
Definition: DCFactor.h:193
DCFactor()=default
virtual bool equals(const DCFactor &other, double tol=1e-9) const =0
virtual double error(const gtsam::Values &continuousVals, const gtsam::DiscreteFactor::Values &discreteVals) const =0
virtual ~DCFactor()=default
Definition: DCContinuousFactor.h:24
std::vector< double > expNormalize(const std::vector< double > &logProbs)
Definition: DCSAM_utils.h:20
gtsam::DiscreteFactor::Values DiscreteValues
Definition: DCSAM_types.h:19
const double tol
Definition: testDCSAM.cpp:40