GTSAM  4.0.2
C++ library for smoothing and mapping (SAM)
NonlinearEquality.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 
12 /*
13  * @file NonlinearEquality.h
14  * @brief Factor to handle enforced equality between factors
15  * @author Alex Cunningham
16  */
17 
18 #pragma once
19 
21 #include <gtsam/base/Testable.h>
22 #include <gtsam/base/Manifold.h>
23 
24 #include <limits>
25 #include <iostream>
26 #include <cmath>
27 
28 namespace gtsam {
29 
42 template<class VALUE>
43 class NonlinearEquality: public NoiseModelFactorN<VALUE> {
44 
45 public:
46  typedef VALUE T;
47 
48  // Provide access to the Matrix& version of evaluateError:
49  using NoiseModelFactor1<VALUE>::evaluateError;
50 
51 private:
52 
53  // feasible value
54  T feasible_;
55 
56  // error handling flag
57  bool allow_error_;
58 
59  // error gain in allow error case
60  double error_gain_;
61 
62  // typedef to this class
64 
65  // typedef to base class
67 
68 public:
69 
71  using CompareFunction = std::function<bool(const T&, const T&)>;
72  CompareFunction compare_;
73 
76  }
77 
78  ~NonlinearEquality() override {
79  }
80 
83 
87  NonlinearEquality(Key j, const T& feasible,
88  const CompareFunction &_compare = std::bind(traits<T>::Equals,
89  std::placeholders::_1, std::placeholders::_2, 1e-9)) :
90  Base(noiseModel::Constrained::All(traits<T>::GetDimension(feasible)),
91  j), feasible_(feasible), allow_error_(false), error_gain_(0.0), //
92  compare_(_compare) {
93  }
94 
98  NonlinearEquality(Key j, const T& feasible, double error_gain,
99  const CompareFunction &_compare = std::bind(traits<T>::Equals,
100  std::placeholders::_1, std::placeholders::_2, 1e-9)) :
101  Base(noiseModel::Constrained::All(traits<T>::GetDimension(feasible)),
102  j), feasible_(feasible), allow_error_(true), error_gain_(error_gain), //
103  compare_(_compare) {
104  }
105 
109 
110  void print(const std::string& s = "",
111  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
112  std::cout << (s.empty() ? s : s + " ") << "Constraint: on ["
113  << keyFormatter(this->key()) << "]\n";
114  traits<VALUE>::Print(feasible_, "Feasible Point:\n");
115  std::cout << "Variable Dimension: " << traits<T>::GetDimension(feasible_)
116  << std::endl;
117  }
118 
120  bool equals(const NonlinearFactor& f, double tol = 1e-9) const override {
121  const This* e = dynamic_cast<const This*>(&f);
122  return e && Base::equals(f) && traits<T>::Equals(feasible_,e->feasible_, tol)
123  && std::abs(error_gain_ - e->error_gain_) < tol;
124  }
125 
129 
131  double error(const Values& c) const override {
132  const T& xj = c.at<T>(this->key());
133  Vector e = this->unwhitenedError(c);
134  if (allow_error_ || !compare_(xj, feasible_)) {
135  return error_gain_ * dot(e, e);
136  } else {
137  return 0.0;
138  }
139  }
140 
142  Vector evaluateError(const T& xj, OptionalMatrixType H) const override {
143  const size_t nj = traits<T>::GetDimension(feasible_);
144  if (allow_error_) {
145  if (H)
146  *H = Matrix::Identity(nj,nj); // FIXME: this is not the right linearization for nonlinear compare
147  return traits<T>::Local(xj,feasible_);
148  } else if (compare_(feasible_, xj)) {
149  if (H)
150  *H = Matrix::Identity(nj,nj);
151  return Vector::Zero(nj); // set error to zero if equal
152  } else {
153  if (H)
154  throw std::invalid_argument(
155  "Linearization point not feasible for "
156  + DefaultKeyFormatter(this->key()) + "!");
157  return Vector::Constant(nj, std::numeric_limits<double>::infinity()); // set error to infinity if not equal
158  }
159  }
160 
162  GaussianFactor::shared_ptr linearize(const Values& x) const override {
163  const T& xj = x.at<T>(this->key());
164  Matrix A;
165  Vector b = evaluateError(xj, A);
166  SharedDiagonal model = noiseModel::Constrained::All(b.size());
168  new JacobianFactor(this->key(), A, b, model));
169  }
170 
172  gtsam::NonlinearFactor::shared_ptr clone() const override {
173  return std::static_pointer_cast<gtsam::NonlinearFactor>(
174  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
175  }
176 
178 
180 
181 private:
182 
183 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION
184  friend class boost::serialization::access;
186  template<class ARCHIVE>
187  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
188  // NoiseModelFactor1 instead of NoiseModelFactorN for backward compatibility
189  ar
190  & boost::serialization::make_nvp("NoiseModelFactor1",
191  boost::serialization::base_object<Base>(*this));
192  ar & BOOST_SERIALIZATION_NVP(feasible_);
193  ar & BOOST_SERIALIZATION_NVP(allow_error_);
194  ar & BOOST_SERIALIZATION_NVP(error_gain_);
195  }
196 #endif
197 
198 };
199 // \class NonlinearEquality
200 
201 template <typename VALUE>
202 struct traits<NonlinearEquality<VALUE>> : Testable<NonlinearEquality<VALUE>> {};
203 
204 /* ************************************************************************* */
208 template<class VALUE>
209 class NonlinearEquality1: public NoiseModelFactorN<VALUE> {
210 
211 public:
212  typedef VALUE X;
213 
214  // Provide access to Matrix& version of evaluateError:
215  using NoiseModelFactor1<VALUE>::evaluateError;
216 
217 protected:
220 
223  }
224 
225  X value_;
226 
227  GTSAM_CONCEPT_MANIFOLD_TYPE(X)
228  GTSAM_CONCEPT_TESTABLE_TYPE(X)
229 
230 public:
231 
232  typedef std::shared_ptr<NonlinearEquality1<VALUE> > shared_ptr;
233 
240  NonlinearEquality1(const X& value, Key key, double mu = 1000.0)
241  : Base(noiseModel::Constrained::All(traits<X>::GetDimension(value),
242  std::abs(mu)),
243  key),
244  value_(value) {}
245 
246  ~NonlinearEquality1() override {
247  }
248 
250  gtsam::NonlinearFactor::shared_ptr clone() const override {
251  return std::static_pointer_cast<gtsam::NonlinearFactor>(
252  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
253  }
254 
256  Vector evaluateError(const X& x1, OptionalMatrixType H) const override {
257  if (H)
258  (*H) = Matrix::Identity(traits<X>::GetDimension(x1),traits<X>::GetDimension(x1));
259  // manifold equivalent of h(x)-z -> log(z,h(x))
260  return traits<X>::Local(value_,x1);
261  }
262 
264  void print(const std::string& s = "",
265  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
266  std::cout << s << ": NonlinearEquality1(" << keyFormatter(this->key())
267  << ")," << "\n";
268  this->noiseModel_->print();
269  traits<X>::Print(value_, "Value");
270  }
271 
273 
274 private:
275 
276 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION
277  friend class boost::serialization::access;
279  template<class ARCHIVE>
280  void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
281  // NoiseModelFactor1 instead of NoiseModelFactorN for backward compatibility
282  ar
283  & boost::serialization::make_nvp("NoiseModelFactor1",
284  boost::serialization::base_object<Base>(*this));
285  ar & BOOST_SERIALIZATION_NVP(value_);
286  }
287 #endif
288 };
289 // \NonlinearEquality1
290 
291 template <typename VALUE>
292 struct traits<NonlinearEquality1<VALUE> >
293  : Testable<NonlinearEquality1<VALUE> > {};
294 
295 /* ************************************************************************* */
300 template <class T>
301 class NonlinearEquality2 : public NoiseModelFactorN<T, T> {
302  protected:
304  using This = NonlinearEquality2<T>;
305 
306  GTSAM_CONCEPT_MANIFOLD_TYPE(T)
307 
308 
310 
311  public:
312  typedef std::shared_ptr<NonlinearEquality2<T>> shared_ptr;
313 
314  // Provide access to the Matrix& version of evaluateError:
315  using Base::evaluateError;
316 
317 
324  NonlinearEquality2(Key key1, Key key2, double mu = 1e4)
325  : Base(noiseModel::Constrained::All(traits<T>::dimension, std::abs(mu)),
326  key1, key2) {}
327  ~NonlinearEquality2() override {}
328 
330  gtsam::NonlinearFactor::shared_ptr clone() const override {
331  return std::static_pointer_cast<gtsam::NonlinearFactor>(
332  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
333  }
334 
337  const T& x1, const T& x2, OptionalMatrixType H1, OptionalMatrixType H2) const override {
338  static const size_t p = traits<T>::dimension;
339  if (H1) *H1 = -Matrix::Identity(p, p);
340  if (H2) *H2 = Matrix::Identity(p, p);
341  return traits<T>::Local(x1, x2);
342  }
343 
345 
346  private:
347 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION
348  friend class boost::serialization::access;
350  template <class ARCHIVE>
351  void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
352  // NoiseModelFactor2 instead of NoiseModelFactorN for backward compatibility
353  ar& boost::serialization::make_nvp(
354  "NoiseModelFactor2", boost::serialization::base_object<Base>(*this));
355  }
356 #endif
357 };
358 // \NonlinearEquality2
359 
360 template <typename VALUE>
361 struct traits<NonlinearEquality2<VALUE>> : Testable<NonlinearEquality2<VALUE>> {
362 };
363 
364 }// namespace gtsam
Definition: NonlinearFactor.h:431
NonlinearEquality1()
Default constructor to allow for serialization.
Definition: NonlinearEquality.h:222
bool equals(const NonlinearFactor &f, double tol=1e-9) const override
Concept check for values that can be used in unit tests.
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition: NonlinearEquality.h:330
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition: NonlinearEquality.h:250
double dot(const V1 &a, const V2 &b)
Definition: Vector.h:195
std::string serialize(const T &input)
serializes to a string
Definition: serialization.h:113
const ValueType at(Key j) const
Definition: Values-inl.h:204
Definition: Factor.h:69
Definition: Testable.h:152
virtual Vector evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const=0
Definition: Group.h:43
Key key() const
Definition: NonlinearFactor.h:582
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition: NonlinearEquality.h:172
Definition: NonlinearFactor.h:68
NonlinearEquality1(const X &value, Key key, double mu=1000.0)
Definition: NonlinearEquality.h:240
Vector evaluateError(const T &x1, const T &x2, OptionalMatrixType H1, OptionalMatrixType H2) const override
g(x) with optional derivative2
Definition: NonlinearEquality.h:336
Definition: NonlinearEquality.h:43
GaussianFactor::shared_ptr linearize(const Values &x) const override
Linearize is over-written, because base linearization tries to whiten.
Definition: NonlinearEquality.h:162
const SharedNoiseModel & noiseModel() const
access to the noise model
Definition: NonlinearFactor.h:245
Matrix * OptionalMatrixType
Definition: NonlinearFactor.h:55
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition: NonlinearEquality.h:110
Base class and basic functions for Manifold types.
NonlinearEquality2(Key key1, Key key2, double mu=1e4)
Definition: NonlinearEquality.h:324
NonlinearEquality(Key j, const T &feasible, const CompareFunction &_compare=std::bind(traits< T >::Equals, std::placeholders::_1, std::placeholders::_2, 1e-9))
Definition: NonlinearEquality.h:87
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
Print.
Definition: NonlinearEquality.h:264
Definition: Values.h:65
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::shared_ptr< NonlinearEquality1< VALUE > > shared_ptr
fixed value for variable
Definition: NonlinearEquality.h:232
Definition: JacobianFactor.h:91
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactor.h:42
Vector evaluateError(const T &xj, OptionalMatrixType H) const override
Error function.
Definition: NonlinearEquality.h:142
Definition: chartTesting.h:28
Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const override
Definition: NonlinearFactor.h:606
std::shared_ptr< This > shared_ptr
Definition: NonlinearFactor.h:209
Non-linear factor base classes.
Vector evaluateError(const X &x1, OptionalMatrixType H) const override
g(x) with optional derivative
Definition: NonlinearEquality.h:256
Definition: NonlinearEquality.h:209
NonlinearEquality()
Default constructor - only for serialization.
Definition: NonlinearEquality.h:75
#define GTSAM_MAKE_ALIGNED_OPERATOR_NEW
Definition: types.h:284
double error(const Values &c) const override
Actual error function calculation.
Definition: NonlinearEquality.h:131
std::function< bool(const T &, const T &)> CompareFunction
Function that compares two values.
Definition: NonlinearEquality.h:71
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
Definition: NonlinearEquality.h:301
NonlinearEquality(Key j, const T &feasible, double error_gain, const CompareFunction &_compare=std::bind(traits< T >::Equals, std::placeholders::_1, std::placeholders::_2, 1e-9))
Definition: NonlinearEquality.h:98
bool equals(const NonlinearFactor &f, double tol=1e-9) const override
Definition: NonlinearEquality.h:120
static shared_ptr All(size_t dim)
Definition: NoiseModel.h:466