testExpressionFactor.cpp
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 
20 #include <gtsam/slam/expressions.h>
28 #include <gtsam/base/Testable.h>
29 
31 
32 #include <boost/assign/list_of.hpp>
33 using boost::assign::list_of;
34 
35 using namespace std;
36 using namespace gtsam;
37 
38 Point2 measured(-17, 30);
39 SharedNoiseModel model = noiseModel::Unit::Create(2);
40 
41 // This deals with the overload problem and makes the expressions factor
42 // understand that we work on Point3
44 
45 namespace leaf {
46 // Create some values
47 struct MyValues: public Values {
49  insert(2, Point2(3, 5));
50  }
51 } values;
52 
53 // Create leaf
54 Point2_ p(2);
55 }
56 
57 /* ************************************************************************* */
58 // Leaf
60  using namespace leaf;
61 
62  // Create old-style factor to create expected value and derivatives
63  PriorFactor<Point2> old(2, Point2(0, 0), model);
64 
65  // Concise version
68  EXPECT_LONGS_EQUAL(2, f.dim());
69  boost::shared_ptr<GaussianFactor> gf2 = f.linearize(values);
70  EXPECT( assert_equal(*old.linearize(values), *gf2, 1e-9));
71 }
72 
73 /* ************************************************************************* */
74 // non-zero noise model
76  using namespace leaf;
77 
78  SharedNoiseModel model = noiseModel::Diagonal::Sigmas(Vector2(0.1, 0.01));
79 
80  // Create old-style factor to create expected value and derivatives
81  PriorFactor<Point2> old(2, Point2(0, 0), model);
82 
83  // Concise version
84  ExpressionFactor<Point2> f(model, Point2(0, 0), p);
85 
86  // Check values and derivatives
88  EXPECT_LONGS_EQUAL(2, f.dim());
89  boost::shared_ptr<GaussianFactor> gf2 = f.linearize(values);
90  EXPECT( assert_equal(*old.linearize(values), *gf2, 1e-9));
91  EXPECT_CORRECT_FACTOR_JACOBIANS(f, values, 1e-5, 1e-5); // another way
92 }
93 
94 /* ************************************************************************* */
95 // Constrained noise model
96 TEST(ExpressionFactor, Constrained) {
97  using namespace leaf;
98 
99  SharedDiagonal model = noiseModel::Constrained::MixedSigmas(Vector2(0.2, 0));
100 
101  // Create old-style factor to create expected value and derivatives
102  PriorFactor<Point2> old(2, Point2(0, 0), model);
103 
104  // Concise version
105  ExpressionFactor<Point2> f(model, Point2(0, 0), p);
107  EXPECT_LONGS_EQUAL(2, f.dim());
108  boost::shared_ptr<GaussianFactor> gf2 = f.linearize(values);
109  EXPECT( assert_equal(*old.linearize(values), *gf2, 1e-9));
110 }
111 
112 /* ************************************************************************* */
113 // Unary(Leaf))
115 
116  // Create some values
117  Values values;
118  values.insert(2, Point3(0, 0, 1));
119 
121  2, (Matrix(2, 3) << 1, 0, 0, 0, 1, 0).finished(), //
122  Vector2(-17, 30));
123 
124  // Create leaves
125  Point3_ p(2);
126 
127  // Concise version
129  EXPECT_LONGS_EQUAL(2, f.dim());
130  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
131  boost::shared_ptr<JacobianFactor> jf = //
132  boost::dynamic_pointer_cast<JacobianFactor>(gf);
133  EXPECT( assert_equal(expected, *jf, 1e-9));
134 }
135 
136 /* ************************************************************************* */
137 // Unary(Leaf)) and Unary(Unary(Leaf)))
138 // wide version (not handled in fixed-size pipeline)
140 Vector9 wide(const Point3& p, OptionalJacobian<9,3> H) {
141  Vector9 v;
142  v << p, p, p;
143  if (H) *H << I_3x3, I_3x3, I_3x3;
144  return v;
145 }
147 Vector9 id9(const Vector9& v, OptionalJacobian<9,9> H) {
148  if (H) *H = Matrix9::Identity();
149  return v;
150 }
152  // Create some values
153  Values values;
154  values.insert(2, Point3(0, 0, 1));
155  Point3_ point(2);
156  Vector9 measured;
157  measured.setZero();
158  Expression<Vector9> expression(wide,point);
159  SharedNoiseModel model = noiseModel::Unit::Create(9);
160 
161  ExpressionFactor<Vector9> f1(model, measured, expression);
162  EXPECT_CORRECT_FACTOR_JACOBIANS(f1, values, 1e-5, 1e-9);
163 
164  Expression<Vector9> expression2(id9,expression);
165  ExpressionFactor<Vector9> f2(model, measured, expression2);
166  EXPECT_CORRECT_FACTOR_JACOBIANS(f2, values, 1e-5, 1e-9);
167 }
168 
169 /* ************************************************************************* */
170 static Point2 myUncal(const Cal3_S2& K, const Point2& p,
172  return K.uncalibrate(p, Dcal, Dp);
173 }
174 
175 // Binary(Leaf,Leaf)
177 
178  typedef internal::BinaryExpression<Point2, Cal3_S2, Point2> Binary;
179 
180  Cal3_S2_ K_(1);
181  Point2_ p_(2);
182  Binary binary(myUncal, K_, p_);
183 
184  // Create some values
185  Values values;
186  values.insert(1, Cal3_S2());
187  values.insert(2, Point2(0, 0));
188 
189  // Check size
190  size_t size = binary.traceSize();
191  // Use Variable Length Array, allocated on stack by gcc
192  // Note unclear for Clang: http://clang.llvm.org/compatibility.html#vla
194  internal::ExecutionTrace<Point2> trace;
195  Point2 value = binary.traceExecution(values, trace, traceStorage);
196  EXPECT(assert_equal(Point2(0,0),value, 1e-9));
197  // trace.print();
198 
199  // Expected Jacobians
200  Matrix25 expected25;
201  expected25 << 0, 0, 0, 1, 0, 0, 0, 0, 0, 1;
202  Matrix2 expected22;
203  expected22 << 1, 0, 0, 1;
204 
205  // Check matrices
206  boost::optional<Binary::Record*> r = trace.record<Binary::Record>();
207  CHECK(r);
208  EXPECT(assert_equal(expected25, (Matrix ) (*r)->dTdA1, 1e-9));
209  EXPECT(assert_equal(expected22, (Matrix ) (*r)->dTdA2, 1e-9));
210 }
211 /* ************************************************************************* */
212 // Unary(Binary(Leaf,Leaf))
214 
215  // Create some values
216  Values values;
217  values.insert(1, Pose3());
218  values.insert(2, Point3(0, 0, 1));
219 
220  // Create old-style factor to create expected value and derivatives
222  boost::make_shared<Cal3_S2>());
223  double expected_error = old.error(values);
225 
226  // Create leaves
227  Pose3_ x_(1);
228  Point3_ p_(2);
229 
230  // Construct expression, concise evrsion
231  Point2_ expression = project(transformTo(x_, p_));
232 
233  // Get and check keys and dims
234  KeyVector keys;
235  FastVector<int> dims;
236  boost::tie(keys, dims) = expression.keysAndDims();
237  LONGS_EQUAL(2,keys.size());
238  LONGS_EQUAL(2,dims.size());
239  LONGS_EQUAL(1,keys[0]);
240  LONGS_EQUAL(2,keys[1]);
241  LONGS_EQUAL(6,dims[0]);
242  LONGS_EQUAL(3,dims[1]);
243 
244  // traceExecution of shallow tree
245  typedef internal::UnaryExpression<Point2, Point3> Unary;
246  size_t size = expression.traceSize();
248  internal::ExecutionTrace<Point2> trace;
249  Point2 value = expression.traceExecution(values, trace, traceStorage);
250  EXPECT(assert_equal(Point2(0,0),value, 1e-9));
251  // trace.print();
252 
253  // Expected Jacobians
254  Matrix23 expected23;
255  expected23 << 1, 0, 0, 0, 1, 0;
256 
257  // Check matrices
258  boost::optional<Unary::Record*> r = trace.record<Unary::Record>();
259  CHECK(r);
260  EXPECT(assert_equal(expected23, (Matrix)(*r)->dTdA1, 1e-9));
261 
262  // Linearization
264  EXPECT_DOUBLES_EQUAL(expected_error, f2.error(values), 1e-9);
265  EXPECT_LONGS_EQUAL(2, f2.dim());
266  boost::shared_ptr<GaussianFactor> gf2 = f2.linearize(values);
267  EXPECT( assert_equal(*expected, *gf2, 1e-9));
268 }
269 
270 /* ************************************************************************* */
271 // Binary(Leaf,Unary(Binary(Leaf,Leaf)))
273 
274  // Create some values
275  Values values;
276  values.insert(1, Pose3());
277  values.insert(2, Point3(0, 0, 1));
278  values.insert(3, Cal3_S2());
279 
280  // Create old-style factor to create expected value and derivatives
282  double expected_error = old.error(values);
284 
285  // Create leaves
286  Pose3_ x(1);
287  Point3_ p(2);
288  Cal3_S2_ K(3);
289 
290  // Create expression tree
292  Point2_ xy_hat(Project, p_cam);
293  Point2_ uv_hat(K, &Cal3_S2::uncalibrate, xy_hat);
294 
295  // Create factor and check value, dimension, linearization
297  EXPECT_DOUBLES_EQUAL(expected_error, f.error(values), 1e-9);
298  EXPECT_LONGS_EQUAL(2, f.dim());
299  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
300  EXPECT( assert_equal(*expected, *gf, 1e-9));
301 
302  // Concise version
304  uncalibrate(K, project(transformTo(x, p))));
305  EXPECT_DOUBLES_EQUAL(expected_error, f2.error(values), 1e-9);
306  EXPECT_LONGS_EQUAL(2, f2.dim());
307  boost::shared_ptr<GaussianFactor> gf2 = f2.linearize(values);
308  EXPECT( assert_equal(*expected, *gf2, 1e-9));
309 
310  // Try ternary version
312  EXPECT_DOUBLES_EQUAL(expected_error, f3.error(values), 1e-9);
313  EXPECT_LONGS_EQUAL(2, f3.dim());
314  boost::shared_ptr<GaussianFactor> gf3 = f3.linearize(values);
315  EXPECT( assert_equal(*expected, *gf3, 1e-9));
316 }
317 
318 /* ************************************************************************* */
319 TEST(ExpressionFactor, Compose1) {
320 
321  // Create expression
322  Rot3_ R1(1), R2(2);
323  Rot3_ R3 = R1 * R2;
324 
325  // Create factor
326  ExpressionFactor<Rot3> f(noiseModel::Unit::Create(3), Rot3(), R3);
327 
328  // Create some values
329  Values values;
330  values.insert(1, Rot3());
331  values.insert(2, Rot3());
332 
333  // Check unwhitenedError
334  std::vector<Matrix> H(2);
335  Vector actual = f.unwhitenedError(values, H);
336  EXPECT( assert_equal(I_3x3, H[0],1e-9));
337  EXPECT( assert_equal(I_3x3, H[1],1e-9));
338 
339  // Check linearization
340  JacobianFactor expected(1, I_3x3, 2, I_3x3, Z_3x1);
341  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
342  boost::shared_ptr<JacobianFactor> jf = //
343  boost::dynamic_pointer_cast<JacobianFactor>(gf);
344  EXPECT( assert_equal(expected, *jf,1e-9));
345 }
346 
347 /* ************************************************************************* */
348 // Test compose with arguments referring to the same rotation
349 TEST(ExpressionFactor, compose2) {
350 
351  // Create expression
352  Rot3_ R1(1), R2(1);
353  Rot3_ R3 = R1 * R2;
354 
355  // Create factor
356  ExpressionFactor<Rot3> f(noiseModel::Unit::Create(3), Rot3(), R3);
357 
358  // Create some values
359  Values values;
360  values.insert(1, Rot3());
361 
362  // Check unwhitenedError
363  std::vector<Matrix> H(1);
364  Vector actual = f.unwhitenedError(values, H);
365  EXPECT_LONGS_EQUAL(1, H.size());
366  EXPECT( assert_equal(2*I_3x3, H[0],1e-9));
367 
368  // Check linearization
369  JacobianFactor expected(1, 2 * I_3x3, Z_3x1);
370  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
371  boost::shared_ptr<JacobianFactor> jf = //
372  boost::dynamic_pointer_cast<JacobianFactor>(gf);
373  EXPECT( assert_equal(expected, *jf,1e-9));
374 }
375 
376 /* ************************************************************************* */
377 // Test compose with one arguments referring to a constant same rotation
378 TEST(ExpressionFactor, compose3) {
379 
380  // Create expression
381  Rot3_ R1(Rot3::identity()), R2(3);
382  Rot3_ R3 = R1 * R2;
383 
384  // Create factor
385  ExpressionFactor<Rot3> f(noiseModel::Unit::Create(3), Rot3(), R3);
386 
387  // Create some values
388  Values values;
389  values.insert(3, Rot3());
390 
391  // Check unwhitenedError
392  std::vector<Matrix> H(1);
393  Vector actual = f.unwhitenedError(values, H);
394  EXPECT_LONGS_EQUAL(1, H.size());
395  EXPECT( assert_equal(I_3x3, H[0],1e-9));
396 
397  // Check linearization
398  JacobianFactor expected(3, I_3x3, Z_3x1);
399  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
400  boost::shared_ptr<JacobianFactor> jf = //
401  boost::dynamic_pointer_cast<JacobianFactor>(gf);
402  EXPECT( assert_equal(expected, *jf,1e-9));
403 }
404 
405 /* ************************************************************************* */
406 // Test compose with three arguments
407 Rot3 composeThree(const Rot3& R1, const Rot3& R2, const Rot3& R3,
409  // return dummy derivatives (not correct, but that's ok for testing here)
410  if (H1)
411  *H1 = I_3x3;
412  if (H2)
413  *H2 = I_3x3;
414  if (H3)
415  *H3 = I_3x3;
416  return R1 * (R2 * R3);
417 }
418 
419 TEST(ExpressionFactor, composeTernary) {
420 
421  // Create expression
422  Rot3_ A(1), B(2), C(3);
423  Rot3_ ABC(composeThree, A, B, C);
424 
425  // Create factor
426  ExpressionFactor<Rot3> f(noiseModel::Unit::Create(3), Rot3(), ABC);
427 
428  // Create some values
429  Values values;
430  values.insert(1, Rot3());
431  values.insert(2, Rot3());
432  values.insert(3, Rot3());
433 
434  // Check unwhitenedError
435  std::vector<Matrix> H(3);
436  Vector actual = f.unwhitenedError(values, H);
437  EXPECT_LONGS_EQUAL(3, H.size());
438  EXPECT( assert_equal(I_3x3, H[0],1e-9));
439  EXPECT( assert_equal(I_3x3, H[1],1e-9));
440  EXPECT( assert_equal(I_3x3, H[2],1e-9));
441 
442  // Check linearization
443  JacobianFactor expected(1, I_3x3, 2, I_3x3, 3, I_3x3, Z_3x1);
444  boost::shared_ptr<GaussianFactor> gf = f.linearize(values);
445  boost::shared_ptr<JacobianFactor> jf = //
446  boost::dynamic_pointer_cast<JacobianFactor>(gf);
447  EXPECT( assert_equal(expected, *jf,1e-9));
448 }
449 
450 TEST(ExpressionFactor, tree_finite_differences) {
451 
452  // Create some values
453  Values values;
454  values.insert(1, Pose3());
455  values.insert(2, Point3(0, 0, 1));
456  values.insert(3, Cal3_S2());
457 
458  // Create leaves
459  Pose3_ x(1);
460  Point3_ p(2);
461  Cal3_S2_ K(3);
462 
463  // Create expression tree
465  Point2_ xy_hat(Project, p_cam);
466  Point2_ uv_hat(K, &Cal3_S2::uncalibrate, xy_hat);
467 
468  const double fd_step = 1e-5;
469  const double tolerance = 1e-5;
470  EXPECT_CORRECT_EXPRESSION_JACOBIANS(uv_hat, values, fd_step, tolerance);
471 }
472 
473 TEST(ExpressionFactor, push_back) {
475  graph.addExpressionFactor(model, Point2(0, 0), leaf::p);
476 }
477 
478 /* ************************************************************************* */
479 // Test with multiple compositions on duplicate keys
480 struct Combine {
481  double a, b;
482  Combine(double a, double b) : a(a), b(b) {}
483  double operator()(const double& x, const double& y, OptionalJacobian<1, 1> H1,
485  if (H1) (*H1) << a;
486  if (H2) (*H2) << b;
487  return a * x + b * y;
488  }
489 };
490 
491 TEST(Expression, testMultipleCompositions) {
492  const double tolerance = 1e-5;
493  const double fd_step = 1e-5;
494 
495  Values values;
496  values.insert(1, 10.0);
497  values.insert(2, 20.0);
498 
499  Expression<double> v1_(Key(1));
500  Expression<double> v2_(Key(2));
501 
502  // BinaryExpression(1,2)
503  // Leaf, key = 1
504  // Leaf, key = 2
505  Expression<double> sum1_(Combine(1, 2), v1_, v2_);
506  EXPECT(sum1_.keys() == list_of(1)(2));
507  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum1_, values, fd_step, tolerance);
508 
509  // BinaryExpression(3,4)
510  // BinaryExpression(1,2)
511  // Leaf, key = 1
512  // Leaf, key = 2
513  // Leaf, key = 1
514  Expression<double> sum2_(Combine(3, 4), sum1_, v1_);
515  EXPECT(sum2_.keys() == list_of(1)(2));
516  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum2_, values, fd_step, tolerance);
517 
518  // BinaryExpression(5,6)
519  // BinaryExpression(3,4)
520  // BinaryExpression(1,2)
521  // Leaf, key = 1
522  // Leaf, key = 2
523  // Leaf, key = 1
524  // BinaryExpression(1,2)
525  // Leaf, key = 1
526  // Leaf, key = 2
527  Expression<double> sum3_(Combine(5, 6), sum1_, sum2_);
528  EXPECT(sum3_.keys() == list_of(1)(2));
529  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum3_, values, fd_step, tolerance);
530 }
531 
532 /* ************************************************************************* */
533 // Another test, with Ternary Expressions
534 static double combine3(const double& x, const double& y, const double& z,
537  if (H1) (*H1) << 1.0;
538  if (H2) (*H2) << 2.0;
539  if (H3) (*H3) << 3.0;
540  return x + 2.0 * y + 3.0 * z;
541 }
542 
543 TEST(Expression, testMultipleCompositions2) {
544  const double tolerance = 1e-5;
545  const double fd_step = 1e-5;
546 
547  Values values;
548  values.insert(1, 10.0);
549  values.insert(2, 20.0);
550  values.insert(3, 30.0);
551 
552  Expression<double> v1_(Key(1));
553  Expression<double> v2_(Key(2));
554  Expression<double> v3_(Key(3));
555 
556  Expression<double> sum1_(Combine(4,5), v1_, v2_);
557  EXPECT(sum1_.keys() == list_of(1)(2));
558  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum1_, values, fd_step, tolerance);
559 
560  Expression<double> sum2_(combine3, v1_, v2_, v3_);
561  EXPECT(sum2_.keys() == list_of(1)(2)(3));
562  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum2_, values, fd_step, tolerance);
563 
564  Expression<double> sum3_(combine3, v3_, v2_, v1_);
565  EXPECT(sum3_.keys() == list_of(1)(2)(3));
566  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum3_, values, fd_step, tolerance);
567 
568  Expression<double> sum4_(combine3, sum1_, sum2_, sum3_);
569  EXPECT(sum4_.keys() == list_of(1)(2)(3));
570  EXPECT_CORRECT_EXPRESSION_JACOBIANS(sum4_, values, fd_step, tolerance);
571 }
572 
573 /* ************************************************************************* */
574 // Test multiplication with the inverse of a matrix
576  auto model = noiseModel::Isotropic::Sigma(3, 1);
577 
578  // Create expression
580 
581  // Check derivatives
582  Values values;
583  Matrix3 A = Vector3(1, 2, 3).asDiagonal();
584  A(0, 1) = 0.1;
585  A(0, 2) = 0.1;
586  const Vector3 b(0.1, 0.2, 0.3);
587  values.insert<Matrix3>(0, A);
588  values.insert<Vector3>(1, b);
589  ExpressionFactor<Vector3> factor(model, Vector3::Zero(), f_expr);
590  EXPECT_CORRECT_FACTOR_JACOBIANS(factor, values, 1e-5, 1e-5);
591 }
592 
593 /* ************************************************************************* */
594 // Test multiplication with the inverse of a matrix function
595 namespace test_operator {
598  Matrix3 A = Vector3(1, 2, 3).asDiagonal();
599  A(0, 1) = a.x();
600  A(0, 2) = a.y();
601  A(1, 0) = a.x();
602  if (H1) *H1 << b.y(), b.z(), b.x(), 0, 0, 0;
603  if (H2) *H2 = A;
604  return A * b;
605 };
606 }
607 
609  auto model = noiseModel::Isotropic::Sigma(3, 1);
610 
611  using test_operator::f;
614 
615  // Check derivatives
616  Point2 a(1, 2);
617  const Vector3 b(0.1, 0.2, 0.3);
618  Matrix32 H1;
619  Matrix3 A;
620  const Vector Ab = f(a, b, H1, A);
621  CHECK(assert_equal(A * b, Ab));
622  CHECK(assert_equal(numericalDerivative11<Vector3, Point2>(
623  boost::bind(f, _1, b, boost::none, boost::none), a),
624  H1));
625 
626  Values values;
627  values.insert<Point2>(0, a);
628  values.insert<Vector3>(1, b);
629  ExpressionFactor<Vector3> factor(model, Vector3::Zero(), f_expr);
630  EXPECT_CORRECT_FACTOR_JACOBIANS(factor, values, 1e-5, 1e-5);
631 }
632 
633 
634 /* ************************************************************************* */
635 // Test N-ary variadic template
637  : public gtsam::ExpressionFactorN<gtsam::Point3 /*return type*/,
638  gtsam::Rot3, gtsam::Point3,
639  gtsam::Rot3,gtsam::Point3> {
640 private:
642  using Base =
643  gtsam::ExpressionFactorN<gtsam::Point3 /*return type*/,
645 
646 public:
648  TestNaryFactor() = default;
649  ~TestNaryFactor() override = default;
650 
652  const gtsam::SharedNoiseModel &model, const gtsam::Point3& measured)
653  : Base({kR1, kV1, kR2, kV2}, model, measured) {
654  this->initialize(expression({kR1, kV1, kR2, kV2}));
655  }
656 
659  return boost::static_pointer_cast<gtsam::NonlinearFactor>(
661  }
662 
663  // Return measurement expression
665  const std::array<gtsam::Key, NARY_EXPRESSION_SIZE> &keys) const override {
666  gtsam::Expression<gtsam::Rot3> R1_(keys[0]);
668  gtsam::Expression<gtsam::Rot3> R2_(keys[2]);
670  return {gtsam::rotate(R1_, V1_) - gtsam::rotate(R2_, V2_)};
671  }
672 
674  void print(const std::string &s,
675  const gtsam::KeyFormatter &keyFormatter =
676  gtsam::DefaultKeyFormatter) const override {
677  std::cout << s << "TestNaryFactor("
678  << keyFormatter(Factor::keys_[0]) << ","
679  << keyFormatter(Factor::keys_[1]) << ","
680  << keyFormatter(Factor::keys_[2]) << ","
681  << keyFormatter(Factor::keys_[3]) << ")\n";
682  gtsam::traits<gtsam::Point3>::Print(measured_, " measured: ");
683  this->noiseModel_->print(" noise model: ");
684  }
685 
688  double tol = 1e-9) const override {
689  const This *e = dynamic_cast<const This *>(&expected);
690  return e != nullptr && Base::equals(*e, tol) &&
691  gtsam::traits<gtsam::Point3>::Equals(measured_,e->measured_, tol);
692  }
693 
694 private:
696  friend class boost::serialization::access;
697  template <class ARCHIVE>
698  void serialize(ARCHIVE &ar, const unsigned int /*version*/) {
699  ar &boost::serialization::make_nvp(
700  "TestNaryFactor",
701  boost::serialization::base_object<Base>(*this));
702  ar &BOOST_SERIALIZATION_NVP(measured_);
703  }
704 };
705 
706 TEST(ExpressionFactor, variadicTemplate) {
709 
710  // Create factor
711  TestNaryFactor f(R(0),V(0), R(1), V(1), noiseModel::Unit::Create(3), Point3(0,0,0));
712 
713  // Create some values
714  Values values;
715  values.insert(R(0), Rot3::Ypr(0.1, 0.2, 0.3));
716  values.insert(V(0), Point3(1, 2, 3));
717  values.insert(R(1), Rot3::Ypr(0.2, 0.5, 0.2));
718  values.insert(V(1), Point3(5, 6, 7));
719 
720  // Check unwhitenedError
721  std::vector<Matrix> H(4);
722  Vector actual = f.unwhitenedError(values, H);
723  EXPECT_LONGS_EQUAL(4, H.size());
724  EXPECT(assert_equal(Eigen::Vector3d(-5.63578115, -4.85353243, -1.4801204), actual, 1e-5));
725 
726  EXPECT_CORRECT_FACTOR_JACOBIANS(f, values, 1e-8, 1e-5);
727 }
728 
729 
730 /* ************************************************************************* */
731 int main() {
732  TestResult tr;
733  return TestRegistry::runAllTests(tr);
734 }
735 /* ************************************************************************* */
736 
Point2 measured(-17, 30)
Combine(double a, double b)
#define CHECK(condition)
Definition: Test.h:109
boost::shared_ptr< GaussianFactor > linearize(const Values &x) const override
double error(const Values &c) const override
static Point2 project(const Pose3 &pose, const Unit3 &pointAtInfinity, const Cal3_S2::shared_ptr &cal)
A insert(1, 2)=0
size_t dim() const override
static const Eigen::MatrixBase< Vector3 >::ConstantReturnType Z_3x1
Definition: Vector.h:46
Vector9 id9(const Vector9 &v, OptionalJacobian< 9, 9 > H)
Scalar * y
Scalar * b
Definition: benchVecAdd.cpp:17
Concept check for values that can be used in unit tests.
static int runAllTests(TestResult &result)
Eigen::Vector3d Vector3
Definition: Vector.h:43
Factor Graph consisting of non-linear factors.
void insert(Key j, const Value &val)
Definition: Values.cpp:140
Matrix expected
Definition: testMatrix.cpp:974
bool equals(const gtsam::NonlinearFactor &expected, double tol=1e-9) const override
Vector2 Point2
Definition: Point2.h:27
ArrayXcf v
Definition: Cwise_arg.cpp:1
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:43
Rot2 R(Rot2::fromAngle(0.1))
leaf::MyValues values
static Cal3_S2 K(500, 500, 0.1, 640/2, 480/2)
Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const override
noiseModel::Isotropic::shared_ptr Model
Definition: Half.h:150
static double combine3(const double &x, const double &y, const double &z, OptionalJacobian< 1, 1 > H1, OptionalJacobian< 1, 1 > H2, OptionalJacobian< 1, 1 > H3)
double f2(const Vector2 &x)
void print(const std::string &s, const gtsam::KeyFormatter &keyFormatter=gtsam::DefaultKeyFormatter) const override
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate set rrange[*:*] noreverse nowriteback set trange[*:*] noreverse nowriteback set urange[*:*] noreverse nowriteback set vrange[*:*] noreverse nowriteback set xlabel matrix size set x2label set timefmt d m y n H
NonlinearFactorGraph graph
Matrix< SCALARB, Dynamic, Dynamic > B
Definition: bench_gemm.cpp:36
static const KeyFormatter DefaultKeyFormatter
Definition: Key.h:43
Point2 uncalibrate(const Point2 &p, OptionalJacobian< 2, 5 > Dcal=boost::none, OptionalJacobian< 2, 2 > Dp=boost::none) const
Definition: Cal3_S2.cpp:44
boost::aligned_storage< 1, TraceAlignment >::type ExecutionTraceStorage
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:162
TEST(ExpressionFactor, Leaf)
Rot3 composeThree(const Rot3 &R1, const Rot3 &R2, const Rot3 &R3, OptionalJacobian< 3, 3 > H1, OptionalJacobian< 3, 3 > H2, OptionalJacobian< 3, 3 > H3)
#define EXPECT_CORRECT_EXPRESSION_JACOBIANS(expression, values, numerical_derivative_step, tolerance)
Check the Jacobians produced by an expression against finite differences.
Array33i a
Point3 point(10, 0,-5)
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
Eigen::VectorXd Vector
Definition: Vector.h:38
double operator()(const double &x, const double &y, OptionalJacobian< 1, 1 > H1, OptionalJacobian< 1, 1 > H2)
void addExpressionFactor(const SharedNoiseModel &R, const T &z, const Expression< T > &h)
Test harness methods for expressions.
KeysAndDims keysAndDims() const
Eigen::Matrix< double, 9, 3 > Matrix93
gtsam::NonlinearFactor::shared_ptr clone() const override
#define EXPECT(condition)
Definition: Test.h:151
boost::shared_ptr< This > shared_ptr
Point3_ p_cam(x,&Pose3::transformTo, p)
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
void serialize(ARCHIVE &ar, const unsigned int)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RealScalar s
Point3_ rotate(const Rot3_ &x, const Point3_ &p)
SharedNoiseModel model
Eigen::Matrix< double, 9, 9 > Matrix9
Q R1(Eigen::AngleAxisd(1, Q_z_axis))
Basic bearing factor from 2D measurement.
#define This
std::set< Key > keys() const
Return keys that play in this expression.
boost::shared_ptr< This > shared_ptr
shared_ptr to this class
Expression< Point2 > uv_hat(uncalibrate< Cal3_S2 >, K, projection)
Matrix< Scalar, Dynamic, Dynamic > C
Definition: bench_gemm.cpp:37
#define LONGS_EQUAL(expected, actual)
Definition: Test.h:135
Vector9 wide(const Point3 &p, OptionalJacobian< 9, 3 > H)
noiseModel::Diagonal::shared_ptr SharedDiagonal
Definition: NoiseModel.h:736
traits
Definition: chartTesting.h:28
static Rot3 R3
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:42
TestNaryFactor(gtsam::Key kR1, gtsam::Key kV1, gtsam::Key kR2, gtsam::Key kV2, const gtsam::SharedNoiseModel &model, const gtsam::Point3 &measured)
Eigen::Vector2d Vector2
Definition: Vector.h:42
#define EXPECT_LONGS_EQUAL(expected, actual)
Definition: Test.h:155
Key R(std::uint64_t j)
T traceExecution(const Values &values, internal::ExecutionTrace< T > &trace, void *traceStorage) const
trace execution, very unsafe
Point2 f1(const Point3 &p, OptionalJacobian< 2, 3 > H)
#define EXPECT_CORRECT_FACTOR_JACOBIANS(factor, values, numerical_derivative_step, tolerance)
Check the Jacobians produced by a factor against finite differences.
Key V(std::uint64_t j)
float * p
Point2(* Project)(const Point3 &, OptionalJacobian< 2, 3 >)
double f3(double x1, double x2)
size_t traceSize() const
Return size needed for memory buffer in traceExecution.
std::vector< T, typename internal::FastDefaultVectorAllocator< T >::type > FastVector
Definition: FastVector.h:34
boost::shared_ptr< GaussianFactor > linearize(const Values &x) const override
Line3 transformTo(const Pose3 &wTc, const Line3 &wL, OptionalJacobian< 4, 6 > Dpose, OptionalJacobian< 4, 4 > Dline)
Definition: Line3.cpp:94
Point2_ p(2)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > Matrix
const G double tol
Definition: Group.h:83
Vector3 Point3
Definition: Point3.h:35
static Point2 myUncal(const Cal3_S2 &K, const Point2 &p, OptionalJacobian< 2, 5 > Dcal, OptionalJacobian< 2, 2 > Dp)
const KeyVector keys
a general SFM factor with an unknown calibration
gtsam::Expression< gtsam::Point3 > expression(const std::array< gtsam::Key, NARY_EXPRESSION_SIZE > &keys) const override
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
static Point2 project3(const Pose3 &pose, const Point3 &point, const Cal3_S2 &cal)
Values initialize(const NonlinearFactorGraph &graph, bool useOdometricPath)
Definition: lago.cpp:338
Q R2(Eigen::AngleAxisd(2, Vector3(0, 1, 0)))
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:61
void Print(const CONTAINER &keys, const string &s, const KeyFormatter &keyFormatter)
Definition: Key.cpp:59
noiseModel::Base::shared_ptr SharedNoiseModel
Definition: NoiseModel.h:734
Vector3 f(const Point2 &a, const Vector3 &b, OptionalJacobian< 3, 2 > H1, OptionalJacobian< 3, 3 > H2)
Point2 uncalibrate(const CAL &K, const Point2 &p, OptionalJacobian< 2, 5 > Dcal, OptionalJacobian< 2, 2 > Dp)
int main()
Expression< Vector3 > Vector3_


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:46:35