testPose3.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 
17 #include <gtsam/geometry/Pose3.h>
18 #include <gtsam/geometry/Pose2.h>
19 #include <gtsam/base/testLie.h>
20 #include <gtsam/base/lieProxies.h>
22 #include <gtsam/slam/expressions.h>
23 
24 
26 #include <cmath>
27 #include <functional>
28 
29 using namespace std;
30 using namespace gtsam;
31 using namespace std::placeholders;
32 
35 
36 static const Point3 P(0.2,0.7,-2);
37 static const Rot3 R = Rot3::Rodrigues(0.3,0,0);
38 static const Point3 P2(3.5,-8.2,4.2);
39 static const Pose3 T(R,P2);
40 static const Pose3 T2(Rot3::Rodrigues(0.3,0.2,0.1),P2);
41 static const Pose3 T3(Rot3::Rodrigues(-90, 0, 0), Point3(1, 2, 3));
42 static const double tol=1e-5;
43 
44 //******************************************************************************
45 TEST(Pose3 , Concept) {
47  GTSAM_CONCEPT_ASSERT(IsManifold<Pose3 >);
49 }
50 
51 /* ************************************************************************* */
53 {
54  Pose3 pose2 = T3;
56  Pose3 origin;
58 }
59 
60 /* ************************************************************************* */
61 TEST( Pose3, constructors)
62 {
63  Pose3 expected(Rot3::Rodrigues(0,0,3),Point3(1,2,0));
64  Pose2 pose2(1,2,3);
66 }
67 
68 /* ************************************************************************* */
69 #ifndef GTSAM_POSE3_EXPMAP
70 TEST( Pose3, retract_first_order)
71 {
72  Pose3 id;
73  Vector v = Z_6x1;
74  v(0) = 0.3;
75  EXPECT(assert_equal(Pose3(R, Point3(0,0,0)), id.retract(v),1e-2));
76  v(3)=0.2;v(4)=0.7;v(5)=-2;
77  EXPECT(assert_equal(Pose3(R, P),id.retract(v),1e-2));
78 }
79 #endif
80 /* ************************************************************************* */
81 TEST( Pose3, retract_expmap)
82 {
83  Vector v = Z_6x1; v(0) = 0.3;
85  EXPECT(assert_equal(Pose3(R, Point3(0,0,0)), pose, 1e-2));
86  EXPECT(assert_equal(v,Pose3::Logmap(pose),1e-2));
87 }
88 
89 /* ************************************************************************* */
90 TEST( Pose3, expmap_a_full)
91 {
92  Pose3 id;
93  Vector v = Z_6x1;
94  v(0) = 0.3;
95  EXPECT(assert_equal(expmap_default<Pose3>(id, v), Pose3(R, Point3(0,0,0))));
96  v(3)=0.2;v(4)=0.394742;v(5)=-2.08998;
97  EXPECT(assert_equal(Pose3(R, P),expmap_default<Pose3>(id, v),1e-5));
98 }
99 
100 /* ************************************************************************* */
101 TEST( Pose3, expmap_a_full2)
102 {
103  Pose3 id;
104  Vector v = Z_6x1;
105  v(0) = 0.3;
106  EXPECT(assert_equal(expmap_default<Pose3>(id, v), Pose3(R, Point3(0,0,0))));
107  v(3)=0.2;v(4)=0.394742;v(5)=-2.08998;
108  EXPECT(assert_equal(Pose3(R, P),expmap_default<Pose3>(id, v),1e-5));
109 }
110 
111 /* ************************************************************************* */
112 TEST(Pose3, expmap_b)
113 {
114  Pose3 p1(Rot3(), Point3(100, 0, 0));
115  Pose3 p2 = p1.retract((Vector(6) << 0.0, 0.0, 0.1, 0.0, 0.0, 0.0).finished());
116  Pose3 expected(Rot3::Rodrigues(0.0, 0.0, 0.1), Point3(100.0, 0.0, 0.0));
118 }
119 
120 /* ************************************************************************* */
121 // test case for screw motion in the plane
122 namespace screwPose3 {
123  double a=0.3, c=cos(a), s=sin(a), w=0.3;
124  Vector xi = (Vector(6) << 0.0, 0.0, w, w, 0.0, 1.0).finished();
125  Rot3 expectedR(c, -s, 0, s, c, 0, 0, 0, 1);
126  Point3 expectedT(0.29552, 0.0446635, 1);
128 }
129 
130 /* ************************************************************************* */
131 // Checks correct exponential map (Expmap) with brute force matrix exponential
132 TEST(Pose3, expmap_c_full)
133 {
136 }
137 
138 /* ************************************************************************* */
139 // assert that T*exp(xi)*T^-1 is equal to exp(Ad_T(xi))
140 TEST(Pose3, Adjoint_full)
141 {
142  Pose3 expected = T * Pose3::Expmap(screwPose3::xi) * T.inverse();
143  Vector xiprime = T.Adjoint(screwPose3::xi);
144  EXPECT(assert_equal(expected, Pose3::Expmap(xiprime), 1e-6));
145 
146  Pose3 expected2 = T2 * Pose3::Expmap(screwPose3::xi) * T2.inverse();
147  Vector xiprime2 = T2.Adjoint(screwPose3::xi);
148  EXPECT(assert_equal(expected2, Pose3::Expmap(xiprime2), 1e-6));
149 
150  Pose3 expected3 = T3 * Pose3::Expmap(screwPose3::xi) * T3.inverse();
151  Vector xiprime3 = T3.Adjoint(screwPose3::xi);
152  EXPECT(assert_equal(expected3, Pose3::Expmap(xiprime3), 1e-6));
153 }
154 
155 /* ************************************************************************* */
156 // Check Adjoint numerical derivatives
157 TEST(Pose3, Adjoint_jacobians)
158 {
159  Vector6 xi = (Vector6() << 0.1, 1.2, 2.3, 3.1, 1.4, 4.5).finished();
160 
161  // Check evaluation sanity check
162  EQUALITY(static_cast<gtsam::Vector>(T.AdjointMap() * xi), T.Adjoint(xi));
163  EQUALITY(static_cast<gtsam::Vector>(T2.AdjointMap() * xi), T2.Adjoint(xi));
164  EQUALITY(static_cast<gtsam::Vector>(T3.AdjointMap() * xi), T3.Adjoint(xi));
165 
166  // Check jacobians
167  Matrix6 actualH1, actualH2, expectedH1, expectedH2;
168  std::function<Vector6(const Pose3&, const Vector6&)> Adjoint_proxy =
169  [&](const Pose3& T, const Vector6& xi) { return T.Adjoint(xi); };
170 
171  T.Adjoint(xi, actualH1, actualH2);
172  expectedH1 = numericalDerivative21(Adjoint_proxy, T, xi);
173  expectedH2 = numericalDerivative22(Adjoint_proxy, T, xi);
174  EXPECT(assert_equal(expectedH1, actualH1));
175  EXPECT(assert_equal(expectedH2, actualH2));
176 
177  T2.Adjoint(xi, actualH1, actualH2);
178  expectedH1 = numericalDerivative21(Adjoint_proxy, T2, xi);
179  expectedH2 = numericalDerivative22(Adjoint_proxy, T2, xi);
180  EXPECT(assert_equal(expectedH1, actualH1));
181  EXPECT(assert_equal(expectedH2, actualH2));
182 
183  T3.Adjoint(xi, actualH1, actualH2);
184  expectedH1 = numericalDerivative21(Adjoint_proxy, T3, xi);
185  expectedH2 = numericalDerivative22(Adjoint_proxy, T3, xi);
186  EXPECT(assert_equal(expectedH1, actualH1));
187  EXPECT(assert_equal(expectedH2, actualH2));
188 }
189 
190 /* ************************************************************************* */
191 // Check AdjointTranspose and jacobians
192 TEST(Pose3, AdjointTranspose)
193 {
194  Vector6 xi = (Vector6() << 0.1, 1.2, 2.3, 3.1, 1.4, 4.5).finished();
195 
196  // Check evaluation
197  EQUALITY(static_cast<Vector>(T.AdjointMap().transpose() * xi),
198  T.AdjointTranspose(xi));
199  EQUALITY(static_cast<Vector>(T2.AdjointMap().transpose() * xi),
201  EQUALITY(static_cast<Vector>(T3.AdjointMap().transpose() * xi),
203 
204  // Check jacobians
205  Matrix6 actualH1, actualH2, expectedH1, expectedH2;
206  std::function<Vector6(const Pose3&, const Vector6&)> AdjointTranspose_proxy =
207  [&](const Pose3& T, const Vector6& xi) {
208  return T.AdjointTranspose(xi);
209  };
210 
211  T.AdjointTranspose(xi, actualH1, actualH2);
212  expectedH1 = numericalDerivative21(AdjointTranspose_proxy, T, xi);
213  expectedH2 = numericalDerivative22(AdjointTranspose_proxy, T, xi);
214  EXPECT(assert_equal(expectedH1, actualH1, 1e-8));
215  EXPECT(assert_equal(expectedH2, actualH2));
216 
217  T2.AdjointTranspose(xi, actualH1, actualH2);
218  expectedH1 = numericalDerivative21(AdjointTranspose_proxy, T2, xi);
219  expectedH2 = numericalDerivative22(AdjointTranspose_proxy, T2, xi);
220  EXPECT(assert_equal(expectedH1, actualH1, 1e-8));
221  EXPECT(assert_equal(expectedH2, actualH2));
222 
223  T3.AdjointTranspose(xi, actualH1, actualH2);
224  expectedH1 = numericalDerivative21(AdjointTranspose_proxy, T3, xi);
225  expectedH2 = numericalDerivative22(AdjointTranspose_proxy, T3, xi);
226  EXPECT(assert_equal(expectedH1, actualH1, 1e-8));
227  EXPECT(assert_equal(expectedH2, actualH2));
228 }
229 
230 /* ************************************************************************* */
231 TEST(Pose3, HatAndVee) {
232  // Create a few test vectors
233  Vector6 v1(1, 2, 3, 4, 5, 6);
234  Vector6 v2(0.1, -0.5, 1.0, -1.0, 0.5, 2.0);
235  Vector6 v3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
236 
237  // Test that Vee(Hat(v)) == v for various inputs
238  EXPECT(assert_equal(v1, Pose3::Vee(Pose3::Hat(v1))));
239  EXPECT(assert_equal(v2, Pose3::Vee(Pose3::Hat(v2))));
240  EXPECT(assert_equal(v3, Pose3::Vee(Pose3::Hat(v3))));
241 
242  // Check the structure of the Lie Algebra element
243  Matrix4 expected;
244  expected << 0, -3, 2, 4,
245  3, 0, -1, 5,
246  -2, 1, 0, 6,
247  0, 0, 0, 0;
248 
249  EXPECT(assert_equal(expected, Pose3::Hat(v1)));
250 }
251 
252 /* ************************************************************************* */
253 // assert that T*Hat(xi)*T^-1 is equal to Hat(Ad_T(xi))
254 TEST(Pose3, Adjoint_hat)
255 {
256  Matrix4 expected = T.matrix() * Pose3::Hat(screwPose3::xi) * T.matrix().inverse();
257  Matrix4 xiprime = Pose3::Hat(T.Adjoint(screwPose3::xi));
258  EXPECT(assert_equal(expected, xiprime, 1e-6));
259 
260  Matrix4 expected2 = T2.matrix() * Pose3::Hat(screwPose3::xi) * T2.matrix().inverse();
261  Matrix4 xiprime2 = Pose3::Hat(T2.Adjoint(screwPose3::xi));
262  EXPECT(assert_equal(expected2, xiprime2, 1e-6));
263 
264  Matrix4 expected3 = T3.matrix() * Pose3::Hat(screwPose3::xi) * T3.matrix().inverse();
265  Matrix4 xiprime3 = Pose3::Hat(T3.Adjoint(screwPose3::xi));
266  EXPECT(assert_equal(expected3, xiprime3, 1e-6));
267 }
268 
269 /* ************************************************************************* */
272  Vector w = xi.head(3);
273  Vector v = xi.tail(3);
274  double t = w.norm();
275  if (t < 1e-5)
276  return Pose3(Rot3(), Point3(v));
277  else {
278  Matrix W = skewSymmetric(w/t);
279  Matrix A = I_3x3 + ((1 - cos(t)) / t) * W + ((t - sin(t)) / t) * (W * W);
280  return Pose3(Rot3::Expmap (w), Point3(A * v));
281  }
282 }
283 
284 /* ************************************************************************* */
285 TEST(Pose3, expmaps_galore_full)
286 {
287  Vector xi; Pose3 actual;
288  xi = (Vector(6) << 0.1, 0.2, 0.3, 0.4, 0.5, 0.6).finished();
289  actual = Pose3::Expmap(xi);
290  EXPECT(assert_equal(expm<Pose3>(xi), actual,1e-6));
291  EXPECT(assert_equal(Agrawal06iros(xi), actual,1e-6));
292  EXPECT(assert_equal(xi, Pose3::Logmap(actual),1e-6));
293 
294  xi = (Vector(6) << 0.1, -0.2, 0.3, -0.4, 0.5, -0.6).finished();
295  for (double theta=1.0;0.3*theta<=M_PI;theta*=2) {
296  Vector txi = xi*theta;
297  actual = Pose3::Expmap(txi);
298  EXPECT(assert_equal(expm<Pose3>(txi,30), actual,1e-6));
299  EXPECT(assert_equal(Agrawal06iros(txi), actual,1e-6));
300  Vector log = Pose3::Logmap(actual);
301  EXPECT(assert_equal(actual, Pose3::Expmap(log),1e-6));
302  EXPECT(assert_equal(txi,log,1e-6)); // not true once wraps
303  }
304 
305  // Works with large v as well, but expm needs 10 iterations!
306  xi = (Vector(6) << 0.2, 0.3, -0.8, 100.0, 120.0, -60.0).finished();
307  actual = Pose3::Expmap(xi);
308  EXPECT(assert_equal(expm<Pose3>(xi,10), actual,1e-5));
309  EXPECT(assert_equal(Agrawal06iros(xi), actual,1e-9));
310  EXPECT(assert_equal(xi, Pose3::Logmap(actual),1e-9));
311 }
312 
313 /* ************************************************************************* */
314 // Check translation and its pushforward
316  Matrix actualH;
317  EXPECT(assert_equal(Point3(3.5, -8.2, 4.2), T.translation(actualH), 1e-8));
318 
319  std::function<Point3(const Pose3&)> f = [](const Pose3& T) { return T.translation(); };
320  Matrix numericalH = numericalDerivative11<Point3, Pose3>(f, T);
321  EXPECT(assert_equal(numericalH, actualH, 1e-6));
322 }
323 
324 /* ************************************************************************* */
325 // Check rotation and its pushforward
327  Matrix actualH;
328  EXPECT(assert_equal(R, T.rotation(actualH), 1e-8));
329 
330  std::function<Rot3(const Pose3&)> f = [](const Pose3& T) { return T.rotation(); };
331  Matrix numericalH = numericalDerivative11<Rot3, Pose3>(f, T);
332  EXPECT(assert_equal(numericalH, actualH, 1e-6));
333 }
334 
335 /* ************************************************************************* */
336 TEST(Pose3, Adjoint_compose_full)
337 {
338  // To debug derivatives of compose, assert that
339  // T1*T2*exp(Adjoint(inv(T2),x) = T1*exp(x)*T2
340  const Pose3& T1 = T;
341  Vector x = (Vector(6) << 0.1, 0.1, 0.1, 0.4, 0.2, 0.8).finished();
343  Vector y = T2.inverse().Adjoint(x);
344  Pose3 actual = T1 * T2 * Pose3::Expmap(y);
345  EXPECT(assert_equal(expected, actual, 1e-6));
346 }
347 
348 /* ************************************************************************* */
349 // Check compose and its pushforward
350 // NOTE: testing::compose<Pose3>(t1,t2) = t1.compose(t2) (see lieProxies.h)
352 {
353  Matrix actual = (T2*T2).matrix();
355  EXPECT(assert_equal(actual,expected,1e-8));
356 
357  Matrix actualDcompose1, actualDcompose2;
358  T2.compose(T2, actualDcompose1, actualDcompose2);
359 
360  Matrix numericalH1 = numericalDerivative21(testing::compose<Pose3>, T2, T2);
361  EXPECT(assert_equal(numericalH1,actualDcompose1,5e-3));
362  EXPECT(assert_equal(T2.inverse().AdjointMap(),actualDcompose1,5e-3));
363 
364  Matrix numericalH2 = numericalDerivative22(testing::compose<Pose3>, T2, T2);
365  EXPECT(assert_equal(numericalH2,actualDcompose2,1e-4));
366 }
367 
368 /* ************************************************************************* */
369 // Check compose and its pushforward, another case
370 TEST( Pose3, compose2 )
371 {
372  const Pose3& T1 = T;
373  Matrix actual = (T1*T2).matrix();
375  EXPECT(assert_equal(actual,expected,1e-8));
376 
377  Matrix actualDcompose1, actualDcompose2;
378  T1.compose(T2, actualDcompose1, actualDcompose2);
379 
380  Matrix numericalH1 = numericalDerivative21(testing::compose<Pose3>, T1, T2);
381  EXPECT(assert_equal(numericalH1,actualDcompose1,5e-3));
382  EXPECT(assert_equal(T2.inverse().AdjointMap(),actualDcompose1,5e-3));
383 
384  Matrix numericalH2 = numericalDerivative22(testing::compose<Pose3>, T1, T2);
385  EXPECT(assert_equal(numericalH2,actualDcompose2,1e-5));
386 }
387 
388 /* ************************************************************************* */
390 {
391  Matrix actualDinverse;
392  Matrix actual = T.inverse(actualDinverse).matrix();
393  Matrix expected = T.matrix().inverse();
394  EXPECT(assert_equal(actual,expected,1e-8));
395 
396  Matrix numericalH = numericalDerivative11(testing::inverse<Pose3>, T);
397  EXPECT(assert_equal(numericalH,actualDinverse,5e-3));
398  EXPECT(assert_equal(-T.AdjointMap(),actualDinverse,5e-3));
399 }
400 
401 /* ************************************************************************* */
402 TEST( Pose3, inverseDerivatives2)
403 {
404  Rot3 R = Rot3::Rodrigues(0.3,0.4,-0.5);
405  Point3 t(3.5,-8.2,4.2);
406  Pose3 T(R,t);
407 
408  Matrix numericalH = numericalDerivative11(testing::inverse<Pose3>, T);
409  Matrix actualDinverse;
410  T.inverse(actualDinverse);
411  EXPECT(assert_equal(numericalH,actualDinverse,5e-3));
412  EXPECT(assert_equal(-T.AdjointMap(),actualDinverse,5e-3));
413 }
414 
415 /* ************************************************************************* */
416 TEST( Pose3, compose_inverse)
417 {
418  Matrix actual = (T*T.inverse()).matrix();
419  Matrix expected = I_4x4;
420  EXPECT(assert_equal(actual,expected,1e-8));
421 }
422 
423 /* ************************************************************************* */
425  return pose.transformFrom(point);
426 }
427 TEST(Pose3, Dtransform_from1_a) {
428  Matrix actualDtransform_from1;
429  T.transformFrom(P, actualDtransform_from1, {});
431  EXPECT(assert_equal(numerical, actualDtransform_from1, 1e-8));
432 }
433 
434 TEST(Pose3, Dtransform_from1_b) {
435  Pose3 origin;
436  Matrix actualDtransform_from1;
437  origin.transformFrom(P, actualDtransform_from1, {});
439  EXPECT(assert_equal(numerical, actualDtransform_from1, 1e-8));
440 }
441 
442 TEST(Pose3, Dtransform_from1_c) {
443  Point3 origin(0, 0, 0);
444  Pose3 T0(R, origin);
445  Matrix actualDtransform_from1;
446  T0.transformFrom(P, actualDtransform_from1, {});
447  Matrix numerical = numericalDerivative21(transformFrom_, T0, P);
448  EXPECT(assert_equal(numerical, actualDtransform_from1, 1e-8));
449 }
450 
451 TEST(Pose3, Dtransform_from1_d) {
452  Rot3 I;
453  Point3 t0(100, 0, 0);
454  Pose3 T0(I, t0);
455  Matrix actualDtransform_from1;
456  T0.transformFrom(P, actualDtransform_from1, {});
457  // print(computed, "Dtransform_from1_d computed:");
458  Matrix numerical = numericalDerivative21(transformFrom_, T0, P);
459  // print(numerical, "Dtransform_from1_d numerical:");
460  EXPECT(assert_equal(numerical, actualDtransform_from1, 1e-8));
461 }
462 
463 /* ************************************************************************* */
464 TEST(Pose3, Dtransform_from2) {
465  Matrix actualDtransform_from2;
466  T.transformFrom(P, {}, actualDtransform_from2);
468  EXPECT(assert_equal(numerical, actualDtransform_from2, 1e-8));
469 }
470 
471 /* ************************************************************************* */
473  return pose.transformTo(point);
474 }
475 TEST(Pose3, Dtransform_to1) {
476  Matrix computed;
477  T.transformTo(P, computed, {});
479  EXPECT(assert_equal(numerical, computed, 1e-8));
480 }
481 
482 /* ************************************************************************* */
483 TEST(Pose3, Dtransform_to2) {
484  Matrix computed;
485  T.transformTo(P, {}, computed);
487  EXPECT(assert_equal(numerical, computed, 1e-8));
488 }
489 
490 /* ************************************************************************* */
491 TEST(Pose3, transform_to_with_derivatives) {
492  Matrix actH1, actH2;
493  T.transformTo(P, actH1, actH2);
496  EXPECT(assert_equal(expH1, actH1, 1e-8));
497  EXPECT(assert_equal(expH2, actH2, 1e-8));
498 }
499 
500 /* ************************************************************************* */
501 TEST(Pose3, transform_from_with_derivatives) {
502  Matrix actH1, actH2;
503  T.transformFrom(P, actH1, actH2);
506  EXPECT(assert_equal(expH1, actH1, 1e-8));
507  EXPECT(assert_equal(expH2, actH2, 1e-8));
508 }
509 
510 /* ************************************************************************* */
511 TEST(Pose3, transform_to_translate) {
512  Point3 actual =
513  Pose3(Rot3(), Point3(1, 2, 3)).transformTo(Point3(10., 20., 30.));
514  Point3 expected(9., 18., 27.);
515  EXPECT(assert_equal(expected, actual));
516 }
517 
518 /* ************************************************************************* */
519 TEST(Pose3, transform_to_rotate) {
520  Pose3 transform(Rot3::Rodrigues(0, 0, -1.570796), Point3(0, 0, 0));
521  Point3 actual = transform.transformTo(Point3(2, 1, 10));
522  Point3 expected(-1, 2, 10);
523  EXPECT(assert_equal(expected, actual, 0.001));
524 }
525 
526 /* ************************************************************************* */
527 // Check transformPoseFrom and its pushforward
528 Pose3 transformPoseFrom_(const Pose3& wTa, const Pose3& aTb) {
529  return wTa.transformPoseFrom(aTb);
530 }
531 
532 TEST(Pose3, transformPoseFrom)
533 {
534  Matrix actual = (T2*T2).matrix();
536  EXPECT(assert_equal(actual, expected, 1e-8));
537 
538  Matrix H1, H2;
539  T2.transformPoseFrom(T2, H1, H2);
540 
542  EXPECT(assert_equal(numericalH1, H1, 5e-3));
543  EXPECT(assert_equal(T2.inverse().AdjointMap(), H1, 5e-3));
544 
546  EXPECT(assert_equal(numericalH2, H2, 1e-4));
547 }
548 
549 /* ************************************************************************* */
551  Pose3 transform(Rot3::Rodrigues(0, 0, -1.570796), Point3(2, 4, 0));
552  Point3 actual = transform.transformTo(Point3(3, 2, 10));
553  Point3 expected(2, 1, 10);
554  EXPECT(assert_equal(expected, actual, 0.001));
555 }
556 
558  return pose.transformPoseTo(pose2);
559 }
560 
561 /* ************************************************************************* */
563  Pose3 origin = T.transformPoseTo(T);
565 }
566 
567 /* ************************************************************************* */
568 TEST(Pose3, transformPoseTo_with_derivatives) {
569  Matrix actH1, actH2;
570  Pose3 res = T.transformPoseTo(T2, actH1, actH2);
571  EXPECT(assert_equal(res, T.inverse().compose(T2)));
572 
575  EXPECT(assert_equal(expH1, actH1, 1e-8));
576  EXPECT(assert_equal(expH2, actH2, 1e-8));
577 }
578 
579 /* ************************************************************************* */
580 TEST(Pose3, transformPoseTo_with_derivatives2) {
581  Matrix actH1, actH2;
582  Pose3 res = T.transformPoseTo(T3, actH1, actH2);
583  EXPECT(assert_equal(res, T.inverse().compose(T3)));
584 
587  EXPECT(assert_equal(expH1, actH1, 1e-8));
588  EXPECT(assert_equal(expH2, actH2, 1e-8));
589 }
590 
591 /* ************************************************************************* */
593  Point3 actual = T3.transformFrom(Point3(0, 0, 0));
594  Point3 expected = Point3(1., 2., 3.);
595  EXPECT(assert_equal(expected, actual));
596 }
597 
598 /* ************************************************************************* */
599 TEST(Pose3, transform_roundtrip) {
600  Point3 actual = T3.transformFrom(T3.transformTo(Point3(12., -0.11, 7.0)));
601  Point3 expected(12., -0.11, 7.0);
602  EXPECT(assert_equal(expected, actual));
603 }
604 
605 /* ************************************************************************* */
606 TEST(Pose3, Retract_LocalCoordinates)
607 {
608  Vector6 d;
609  d << 1,2,3,4,5,6; d/=10;
610  const Rot3 R = Rot3::Retract(d.head<3>());
611  Pose3 t = Pose3::Retract(d);
612  EXPECT(assert_equal(d, Pose3::LocalCoordinates(t)));
613 }
614 /* ************************************************************************* */
615 TEST(Pose3, retract_localCoordinates)
616 {
617  Vector6 d12;
618  d12 << 1,2,3,4,5,6; d12/=10;
619  Pose3 t1 = T, t2 = t1.retract(d12);
620  EXPECT(assert_equal(d12, t1.localCoordinates(t2)));
621 }
622 /* ************************************************************************* */
623 TEST(Pose3, expmap_logmap)
624 {
625  Vector d12 = Vector6::Constant(0.1);
626  Pose3 t1 = T, t2 = t1.expmap(d12);
627  EXPECT(assert_equal(d12, t1.logmap(t2)));
628 }
629 
630 /* ************************************************************************* */
631 TEST(Pose3, retract_localCoordinates2)
632 {
633  Pose3 t1 = T;
634  Pose3 t2 = T3;
635  Pose3 origin;
636  Vector d12 = t1.localCoordinates(t2);
637  EXPECT(assert_equal(t2, t1.retract(d12)));
638  Vector d21 = t2.localCoordinates(t1);
639  EXPECT(assert_equal(t1, t2.retract(d21)));
640  // TODO(hayk): This currently fails!
641  // EXPECT(assert_equal(d12, -d21));
642 }
643 /* ************************************************************************* */
644 TEST(Pose3, manifold_expmap)
645 {
646  Pose3 t1 = T;
647  Pose3 t2 = T3;
648  Pose3 origin;
649  Vector d12 = t1.logmap(t2);
650  EXPECT(assert_equal(t2, t1.expmap(d12)));
651  Vector d21 = t2.logmap(t1);
652  EXPECT(assert_equal(t1, t2.expmap(d21)));
653 
654  // Check that log(t1,t2)=-log(t2,t1)
655  EXPECT(assert_equal(d12,-d21));
656 }
657 
658 /* ************************************************************************* */
659 TEST(Pose3, subgroups)
660 {
661  // Frank - Below only works for correct "Agrawal06iros style expmap
662  // lines in canonical coordinates correspond to Abelian subgroups in SE(3)
663  Vector d = (Vector(6) << 0.1, 0.2, 0.3, 0.4, 0.5, 0.6).finished();
664  // exp(-d)=inverse(exp(d))
666  // exp(5d)=exp(2*d+3*d)=exp(2*d)exp(3*d)=exp(3*d)exp(2*d)
667  Pose3 T2 = Pose3::Expmap(2*d);
668  Pose3 T3 = Pose3::Expmap(3*d);
669  Pose3 T5 = Pose3::Expmap(5*d);
672 }
673 
674 /* ************************************************************************* */
676 {
677  Pose3 expected = T2.inverse() * T3;
678  Matrix actualDBetween1,actualDBetween2;
679  Pose3 actual = T2.between(T3, actualDBetween1,actualDBetween2);
680  EXPECT(assert_equal(expected,actual));
681 
682  Matrix numericalH1 = numericalDerivative21(testing::between<Pose3> , T2, T3);
683  EXPECT(assert_equal(numericalH1,actualDBetween1,5e-3));
684 
685  Matrix numericalH2 = numericalDerivative22(testing::between<Pose3> , T2, T3);
686  EXPECT(assert_equal(numericalH2,actualDBetween2,1e-5));
687 }
688 
689 /* ************************************************************************* */
690 // some shared test values - pulled from equivalent test in Pose2
691 Point3 l1(1, 0, 0), l2(1, 1, 0), l3(2, 2, 0), l4(1, 4,-4);
692 Pose3 x1, x2(Rot3::Ypr(0.0, 0.0, 0.0), l2), x3(Rot3::Ypr(M_PI/4.0, 0.0, 0.0), l2);
693 Pose3
694  xl1(Rot3::Ypr(0.0, 0.0, 0.0), Point3(1, 0, 0)),
695  xl2(Rot3::Ypr(0.0, 1.0, 0.0), Point3(1, 1, 0)),
696  xl3(Rot3::Ypr(1.0, 0.0, 0.0), Point3(2, 2, 0)),
697  xl4(Rot3::Ypr(0.0, 0.0, 1.0), Point3(1, 4,-4));
698 
699 /* ************************************************************************* */
700 double range_proxy(const Pose3& pose, const Point3& point) {
701  return pose.range(point);
702 }
704 {
705  Matrix expectedH1, actualH1, expectedH2, actualH2;
706 
707  // establish range is indeed zero
709 
710  // establish range is indeed sqrt2
711  EXPECT_DOUBLES_EQUAL(sqrt(2.0),x1.range(l2),1e-9);
712 
713  // Another pair
714  double actual23 = x2.range(l3, actualH1, actualH2);
715  EXPECT_DOUBLES_EQUAL(sqrt(2.0),actual23,1e-9);
716 
717  // Check numerical derivatives
718  expectedH1 = numericalDerivative21(range_proxy, x2, l3);
719  expectedH2 = numericalDerivative22(range_proxy, x2, l3);
720  EXPECT(assert_equal(expectedH1,actualH1));
721  EXPECT(assert_equal(expectedH2,actualH2));
722 
723  // Another test
724  double actual34 = x3.range(l4, actualH1, actualH2);
725  EXPECT_DOUBLES_EQUAL(5,actual34,1e-9);
726 
727  // Check numerical derivatives
728  expectedH1 = numericalDerivative21(range_proxy, x3, l4);
729  expectedH2 = numericalDerivative22(range_proxy, x3, l4);
730  EXPECT(assert_equal(expectedH1,actualH1));
731  EXPECT(assert_equal(expectedH2,actualH2));
732 }
733 
734 /* ************************************************************************* */
735 double range_pose_proxy(const Pose3& pose, const Pose3& point) {
736  return pose.range(point);
737 }
738 TEST( Pose3, range_pose )
739 {
740  Matrix expectedH1, actualH1, expectedH2, actualH2;
741 
742  // establish range is indeed zero
744 
745  // establish range is indeed sqrt2
747 
748  // Another pair
749  double actual23 = x2.range(xl3, actualH1, actualH2);
750  EXPECT_DOUBLES_EQUAL(sqrt(2.0),actual23,1e-9);
751 
752  // Check numerical derivatives
755  EXPECT(assert_equal(expectedH1,actualH1));
756  EXPECT(assert_equal(expectedH2,actualH2));
757 
758  // Another test
759  double actual34 = x3.range(xl4, actualH1, actualH2);
760  EXPECT_DOUBLES_EQUAL(5,actual34,1e-9);
761 
762  // Check numerical derivatives
765  EXPECT(assert_equal(expectedH1,actualH1));
766  EXPECT(assert_equal(expectedH2,actualH2));
767 }
768 
769 /* ************************************************************************* */
771  return pose.bearing(point);
772 }
774  Matrix expectedH1, actualH1, expectedH2, actualH2;
775  EXPECT(assert_equal(Unit3(1, 0, 0), x1.bearing(l1, actualH1, actualH2), 1e-9));
776 
777  // Check numerical derivatives
778  expectedH1 = numericalDerivative21(bearing_proxy, x1, l1);
779  expectedH2 = numericalDerivative22(bearing_proxy, x1, l1);
780  EXPECT(assert_equal(expectedH1, actualH1, 1e-5));
781  EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
782 }
783 
784 TEST(Pose3, Bearing2) {
785  Matrix expectedH1, actualH1, expectedH2, actualH2;
786  EXPECT(assert_equal(Unit3(0,0.6,-0.8), x2.bearing(l4, actualH1, actualH2), 1e-9));
787 
788  // Check numerical derivatives
789  expectedH1 = numericalDerivative21(bearing_proxy, x2, l4);
790  expectedH2 = numericalDerivative22(bearing_proxy, x2, l4);
791  EXPECT(assert_equal(expectedH1, actualH1, 1e-5));
792  EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
793 }
794 
795 TEST(Pose3, PoseToPoseBearing) {
796  Matrix expectedH1, actualH1, expectedH2, actualH2, H2block;
797  EXPECT(assert_equal(Unit3(0,1,0), xl1.bearing(xl2, actualH1, actualH2), 1e-9));
798 
799  // Check numerical derivatives
800  std::function<Unit3(const Pose3&, const Pose3&)> f = [](const Pose3& a, const Pose3& b) { return a.bearing(b); };
801  expectedH1 = numericalDerivative21(f, xl1, xl2);
802  expectedH2 = numericalDerivative22(f, xl1, xl2);
803  EXPECT(assert_equal(expectedH1, actualH1, 1e-5));
804  EXPECT(assert_equal(expectedH2, actualH2, 1e-5));
805 }
806 
807 /* ************************************************************************* */
808 TEST( Pose3, unicycle )
809 {
810  // velocity in X should be X in inertial frame, rather than global frame
811  Vector x_step = Vector::Unit(6,3)*1.0;
812  EXPECT(assert_equal(Pose3(Rot3::Ypr(0,0,0), l1), expmap_default<Pose3>(x1, x_step), tol));
813  EXPECT(assert_equal(Pose3(Rot3::Ypr(0,0,0), Point3(2,1,0)), expmap_default<Pose3>(x2, x_step), tol));
814  EXPECT(assert_equal(Pose3(Rot3::Ypr(M_PI/4.0,0,0), Point3(2,2,0)), expmap_default<Pose3>(x3, sqrt(2.0) * x_step), tol));
815 }
816 
817 /* ************************************************************************* */
818 TEST( Pose3, adjointMap) {
819  Matrix res = Pose3::adjointMap(screwPose3::xi);
823  expected << wh, Z_3x3, vh, wh;
825 }
826 
827 /* ************************************************************************* */
828 TEST(Pose3, Align1) {
829  Pose3 expected(Rot3(), Point3(10,10,0));
830 
831  Point3Pair ab1(Point3(10,10,0), Point3(0,0,0));
832  Point3Pair ab2(Point3(30,20,0), Point3(20,10,0));
833  Point3Pair ab3(Point3(20,30,0), Point3(10,20,0));
834  const vector<Point3Pair> correspondences{ab1, ab2, ab3};
835 
836  std::optional<Pose3> actual = Pose3::Align(correspondences);
837  EXPECT(assert_equal(expected, *actual));
838 }
839 
840 /* ************************************************************************* */
841 TEST(Pose3, Align2) {
842  Point3 t(20,10,5);
843  Rot3 R = Rot3::RzRyRx(0.3, 0.2, 0.1);
844  Pose3 expected(R, t);
845 
846  Point3 p1(0,0,1), p2(10,0,2), p3(20,-10,30);
848  q2 = expected.transformFrom(p2),
849  q3 = expected.transformFrom(p3);
850  const Point3Pair ab1{q1, p1}, ab2{q2, p2}, ab3{q3, p3};
851  const vector<Point3Pair> correspondences{ab1, ab2, ab3};
852 
853  std::optional<Pose3> actual = Pose3::Align(correspondences);
854  EXPECT(assert_equal(expected, *actual, 1e-5));
855 }
856 
857 /* ************************************************************************* */
858 TEST(Pose3, ExpmapDerivative) {
859  // Iserles05an (Lie-group Methods) says:
860  // scalar is easy: d exp(a(t)) / dt = exp(a(t)) a'(t)
861  // matrix is hard: d exp(A(t)) / dt = exp(A(t)) dexp[-A(t)] A'(t)
862  // where A(t): T -> se(3) is a trajectory in the tangent space of SE(3)
863  // and dexp[A] is a linear map from 4*4 to 4*4 derivatives of se(3)
864  // Hence, the above matrix equation is typed: 4*4 = SE(3) * linear_map(4*4)
865 
866  // In GTSAM, we don't work with the Lie-algebra elements A directly, but with 6-vectors.
867  // xi is easy: d Expmap(xi(t)) / dt = ExmapDerivative[xi(t)] * xi'(t)
868 
869  // Let's verify the above formula.
870 
871  auto xi = [](double t) {
872  Vector6 v;
873  v << 2 * t, sin(t), 4 * t * t, 2 * t, sin(t), 4 * t * t;
874  return v;
875  };
876  auto xi_dot = [](double t) {
877  Vector6 v;
878  v << 2, cos(t), 8 * t, 2, cos(t), 8 * t;
879  return v;
880  };
881 
882  // We define a function T
883  auto T = [xi](double t) { return Pose3::Expmap(xi(t)); };
884 
885  for (double t = -2.0; t < 2.0; t += 0.3) {
886  const Matrix expected = numericalDerivative11<Pose3, double>(T, t);
887  const Matrix actual = Pose3::ExpmapDerivative(xi(t)) * xi_dot(t);
888  CHECK(assert_equal(expected, actual, 1e-7));
889  }
890 }
891 
892 //******************************************************************************
893 namespace test_cases {
894  static const std::vector<Vector3> small{ {0, 0, 0}, //
895  {1e-5, 0, 0}, {0, 1e-5, 0}, {0, 0, 1e-5}, //,
896  {1e-4, 0, 0}, {0, 1e-4, 0}, {0, 0, 1e-4} };
897  static const std::vector<Vector3> large{ {0, 0, 0}, {1, 0, 0}, {0, 1, 0},
898  {0, 0, 1}, {.1, .2, .3}, {1, -2, 3} };
899  auto omegas = [](bool nearZero) -> const std::vector<Vector3>&{ return nearZero ? small : large; };
900  static const std::vector<Vector3> vs{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
901  {.4, .3, .2}, {4, 5, 6}, {-10, -20, 30} };
902 } // namespace test_cases
903 
904 //******************************************************************************
905 TEST(Pose3, ExpmapDerivatives) {
906  for (bool nearZero : {true, false}) {
907  for (const Vector3& w : test_cases::omegas(nearZero)) {
908  for (Vector3 v : test_cases::vs) {
909  const Vector6 xi = (Vector6() << w, v).finished();
910  const Matrix6 expectedH =
911  numericalDerivative21<Pose3, Vector6, OptionalJacobian<6, 6> >(
912  &Pose3::Expmap, xi, {});
913  Matrix actualH;
914  Pose3::Expmap(xi, actualH);
915  EXPECT(assert_equal(expectedH, actualH));
916  }
917  }
918  }
919 }
920 
921 //******************************************************************************
922 // Check logmap for all small values, as we don't want wrapping.
923 TEST(Pose3, Logmap) {
924  static constexpr bool nearZero = true;
925  for (const Vector3& w : test_cases::omegas(nearZero)) {
926  for (Vector3 v : test_cases::vs) {
927  const Vector6 xi = (Vector6() << w, v).finished();
929  EXPECT(assert_equal(xi, Pose3::Logmap(pose)));
930  }
931  }
932 }
933 
934 //******************************************************************************
935 // Check logmap derivatives for all values
936 TEST(Pose3, LogmapDerivatives) {
937  for (bool nearZero : {true, false}) {
938  for (const Vector3& w : test_cases::omegas(nearZero)) {
939  std::cout << "w: " << w.transpose() << std::endl;
940  for (Vector3 v : test_cases::vs) {
941  std::cout << "v: " << v.transpose() << std::endl;
942  const Vector6 xi = (Vector6() << w, v).finished();
944  const Matrix6 expectedH =
945  numericalDerivative21<Vector6, Pose3, OptionalJacobian<6, 6> >(
946  &Pose3::Logmap, pose, {});
947  Matrix actualH;
948  Pose3::Logmap(pose, actualH);
949 #ifdef GTSAM_USE_QUATERNIONS
950  // TODO(Frank): Figure out why quaternions are not as accurate.
951  // Hint: 6 cases fail on Ubuntu 22.04, but none on MacOS.
952  EXPECT(assert_equal(expectedH, actualH, 1e-7));
953 #else
954  EXPECT(assert_equal(expectedH, actualH));
955 #endif
956  }
957  }
958  }
959 }
960 
961 //******************************************************************************
962 TEST(Pose3, LogmapDerivative) {
963  // Copied from testSO3.cpp
964  const Rot3 R2((Matrix3() << // Near pi
965  -0.750767, -0.0285082, -0.659952,
966  -0.0102558, -0.998445, 0.0547974,
967  -0.660487, 0.0479084, 0.749307).finished());
968  const Rot3 R3((Matrix3() << // Near pi
969  -0.747473, -0.00190019, -0.664289,
970  -0.0385114, -0.99819, 0.0461892,
971  -0.663175, 0.060108, 0.746047).finished());
972  const Rot3 R4((Matrix3() << // Final pose in a drone experiment
973  0.324237, 0.902975, 0.281968,
974  -0.674322, 0.429668, -0.600562,
975  -0.663445, 0.00458662, 0.748211).finished());
976 
977  // Now creates poses
978  const Pose3 T0; // Identity
979  const Vector6 xi(0.1, -0.1, 0.1, 0.1, -0.1, 0.1);
980  const Pose3 T1 = Pose3::Expmap(xi); // Small rotation
981  const Pose3 T2(R2, Point3(1, 2, 3));
982  const Pose3 T3(R3, Point3(1, 2, 3));
983  const Pose3 T4(R4, Point3(1, 2, 3));
984  size_t i = 0;
985  for (const Pose3& T : { T0, T1, T2, T3, T4 }) {
986  const bool nearPi = (i == 2 || i == 3); // Flag cases near pi
987 
988  Matrix6 actualH; // H computed by Logmap(T, H) using LogmapDerivative(xi)
989  const Vector6 xi = Pose3::Logmap(T, actualH);
990 
991  // 1. Check self-consistency of analytical derivative calculation:
992  // Does the H returned by Logmap match an independent calculation
993  // of J_r^{-1} using ExpmapDerivative with the computed xi?
994  Matrix6 J_r_inv = Pose3::ExpmapDerivative(xi).inverse(); // J_r^{-1}
995  EXPECT(assert_equal(J_r_inv, actualH)); // This test is crucial and should pass
996 
997  // 2. Check analytical derivative against numerical derivative:
998  // Only perform this check AWAY from the pi singularity, where
999  // numerical differentiation of Logmap is expected to be reliable
1000  // and should match the analytical derivative.
1001  if (!nearPi) {
1002  const Matrix expectedH = numericalDerivative11<Vector6, Pose3>(
1003  std::bind(&Pose3::Logmap, std::placeholders::_1, nullptr), T, 1e-7);
1004  EXPECT(assert_equal(expectedH, actualH, 1e-5)); // 1e-5 needed to pass R4
1005  }
1006  else {
1007  // We accept that the numerical derivative of this specific Logmap implementation
1008  // near pi will not match the standard analytical derivative J_r^{-1}.
1009  }
1010  i++;
1011  }
1012 }
1013 
1014 /* ************************************************************************* */
1015 Vector6 testDerivAdjoint(const Vector6& xi, const Vector6& v) {
1016  return Pose3::adjointMap(xi) * v;
1017 }
1018 
1020  Vector6 v = (Vector6() << 1, 2, 3, 4, 5, 6).finished();
1022 
1023  Matrix actualH1, actualH2;
1024  Vector actual = Pose3::adjoint(screwPose3::xi, v, actualH1, actualH2);
1025 
1026  Matrix numericalH1 = numericalDerivative21<Vector6, Vector6, Vector6>(
1028  Matrix numericalH2 = numericalDerivative22<Vector6, Vector6, Vector6>(
1030 
1031  EXPECT(assert_equal(expected,actual,1e-5));
1032  EXPECT(assert_equal(numericalH1,actualH1,1e-5));
1033  EXPECT(assert_equal(numericalH2,actualH2,1e-5));
1034 }
1035 
1036 /* ************************************************************************* */
1037 Vector6 testDerivAdjointTranspose(const Vector6& xi, const Vector6& v) {
1038  return Pose3::adjointMap(xi).transpose() * v;
1039 }
1040 
1041 TEST( Pose3, adjointTranspose) {
1042  Vector xi = (Vector(6) << 0.01, 0.02, 0.03, 1.0, 2.0, 3.0).finished();
1043  Vector v = (Vector(6) << 0.04, 0.05, 0.06, 4.0, 5.0, 6.0).finished();
1045 
1046  Matrix actualH1, actualH2;
1047  Vector actual = Pose3::adjointTranspose(xi, v, actualH1, actualH2);
1048 
1049  Matrix numericalH1 = numericalDerivative21<Vector6, Vector6, Vector6>(
1051  Matrix numericalH2 = numericalDerivative22<Vector6, Vector6, Vector6>(
1053 
1054  EXPECT(assert_equal(expected,actual,1e-15));
1055  EXPECT(assert_equal(numericalH1,actualH1,1e-5));
1056  EXPECT(assert_equal(numericalH2,actualH2,1e-5));
1057 }
1058 
1059 /* ************************************************************************* */
1061  std::ostringstream os;
1062  os << Pose3();
1063 
1064  string expected = "R: [\n\t1, 0, 0;\n\t0, 1, 0;\n\t0, 0, 1\n]\nt: 0 0 0";
1065  EXPECT(os.str() == expected);
1066 }
1067 
1068 //******************************************************************************
1069 TEST(Pose3 , Invariants) {
1070  Pose3 id;
1071 
1072  EXPECT(check_group_invariants(id,id));
1073  EXPECT(check_group_invariants(id,T3));
1074  EXPECT(check_group_invariants(T2,id));
1075  EXPECT(check_group_invariants(T2,T3));
1076 
1077  EXPECT(check_manifold_invariants(id,id));
1078  EXPECT(check_manifold_invariants(id,T3));
1079  EXPECT(check_manifold_invariants(T2,id));
1080  EXPECT(check_manifold_invariants(T2,T3));
1081 }
1082 
1083 //******************************************************************************
1084 TEST(Pose3 , LieGroupDerivatives) {
1085  Pose3 id;
1086 
1091 }
1092 
1093 //******************************************************************************
1094 TEST(Pose3 , ChartDerivatives) {
1095  Pose3 id;
1096  if (ROT3_DEFAULT_COORDINATES_MODE == Rot3::EXPMAP) {
1097  CHECK_CHART_DERIVATIVES(id,id);
1101  }
1102 }
1103 
1104 //******************************************************************************
1105 #include "testPoseAdjointMap.h"
1106 
1107 TEST(Pose3, TransformCovariance6MapTo2d) {
1108  // Create 3d scenarios that map to 2d configurations and compare with Pose2 results.
1109  using namespace test_pose_adjoint_map;
1110 
1111  Vector3 s2{0.1, 0.3, 0.7};
1112  Pose2 p2{1.1, 1.5, 31. * degree};
1113  auto cov2 = FullCovarianceFromSigmas<Pose2>(s2);
1114  auto transformed2 = TransformCovariance<Pose2>{p2}(cov2);
1115 
1116  auto match_cov3_to_cov2 = [&](int spatial_axis0, int spatial_axis1, int r_axis,
1117  const Pose2::Jacobian &cov2, const Pose3::Jacobian &cov3) -> void
1118  {
1120  Vector3{cov2.diagonal()},
1121  Vector3{cov3(spatial_axis0, spatial_axis0), cov3(spatial_axis1, spatial_axis1), cov3(r_axis, r_axis)}));
1123  Vector3{cov2(1, 0), cov2(2, 0), cov2(2, 1)},
1124  Vector3{cov3(spatial_axis1, spatial_axis0), cov3(r_axis, spatial_axis0), cov3(r_axis, spatial_axis1)}));
1125  };
1126 
1127  // rotate around x axis
1128  {
1129  auto cov3 = FullCovarianceFromSigmas<Pose3>((Vector6{} << s2(2), 0., 0., 0., s2(0), s2(1)).finished());
1130  auto transformed3 = TransformCovariance<Pose3>{{Rot3::RzRyRx(p2.theta(), 0., 0.), {0., p2.x(), p2.y()}}}(cov3);
1131  match_cov3_to_cov2(4, 5, 0, transformed2, transformed3);
1132  }
1133 
1134  // rotate around y axis
1135  {
1136  auto cov3 = FullCovarianceFromSigmas<Pose3>((Vector6{} << 0., s2(2), 0., s2(1), 0., s2(0)).finished());
1137  auto transformed3 = TransformCovariance<Pose3>{{Rot3::RzRyRx(0., p2.theta(), 0.), {p2.y(), 0., p2.x()}}}(cov3);
1138  match_cov3_to_cov2(5, 3, 1, transformed2, transformed3);
1139  }
1140 
1141  // rotate around z axis
1142  {
1143  auto cov3 = FullCovarianceFromSigmas<Pose3>((Vector6{} << 0., 0., s2(2), s2(0), s2(1), 0.).finished());
1144  auto transformed3 = TransformCovariance<Pose3>{{Rot3::RzRyRx(0., 0., p2.theta()), {p2.x(), p2.y(), 0.}}}(cov3);
1145  match_cov3_to_cov2(3, 4, 2, transformed2, transformed3);
1146  }
1147 }
1148 
1149 /* ************************************************************************* */
1150 TEST(Pose3, TransformCovariance6) {
1151  // Use simple covariance matrices and transforms to create tests that can be
1152  // validated with simple computations.
1153  using namespace test_pose_adjoint_map;
1154 
1155  // rotate 90 around z axis and then 90 around y axis
1156  {
1157  auto cov = FullCovarianceFromSigmas<Pose3>((Vector6{} << 0.1, 0.2, 0.3, 0.5, 0.7, 1.1).finished());
1158  auto transformed = TransformCovariance<Pose3>{{Rot3::RzRyRx(0., 90 * degree, 90 * degree), {0., 0., 0.}}}(cov);
1159  // x from y, y from z, z from x
1161  (Vector6{} << cov(1, 1), cov(2, 2), cov(0, 0), cov(4, 4), cov(5, 5), cov(3, 3)).finished(),
1162  Vector6{transformed.diagonal()}));
1163  // Both the x and z axes are pointing in the negative direction.
1165  (Vector5{} << -cov(2, 1), cov(0, 1), cov(4, 1), -cov(5, 1), cov(3, 1)).finished(),
1166  (Vector5{} << transformed(1, 0), transformed(2, 0), transformed(3, 0),
1167  transformed(4, 0), transformed(5, 0)).finished()));
1168  }
1169 
1170  // translate along the x axis with uncertainty in roty and rotz
1171  {
1172  auto cov = TwoVariableCovarianceFromSigmas<Pose3>(1, 2, 0.7, 0.3);
1173  auto transformed = TransformCovariance<Pose3>{{Rot3::RzRyRx(0., 0., 0.), {20., 0., 0.}}}(cov);
1174  // The uncertainty in roty and rotz causes off-diagonal covariances
1175  EXPECT(assert_equal(0.7 * 0.7 * 20., transformed(5, 1)));
1176  EXPECT(assert_equal(0.7 * 0.7 * 20. * 20., transformed(5, 5)));
1177  EXPECT(assert_equal(-0.3 * 0.3 * 20., transformed(4, 2)));
1178  EXPECT(assert_equal(0.3 * 0.3 * 20. * 20., transformed(4, 4)));
1179  EXPECT(assert_equal(-0.3 * 0.7 * 20., transformed(4, 1)));
1180  EXPECT(assert_equal(0.3 * 0.7 * 20., transformed(5, 2)));
1181  EXPECT(assert_equal(-0.3 * 0.7 * 20. * 20., transformed(5, 4)));
1182  }
1183 
1184  // rotate around x axis and translate along the x axis with uncertainty in rotx
1185  {
1186  auto cov = SingleVariableCovarianceFromSigma<Pose3>(0, 0.1);
1187  auto transformed = TransformCovariance<Pose3>{{Rot3::RzRyRx(90 * degree, 0., 0.), {20., 0., 0.}}}(cov);
1188  // No change
1189  EXPECT(assert_equal(cov, transformed));
1190  }
1191 
1192  // rotate around x axis and translate along the x axis with uncertainty in roty
1193  {
1194  auto cov = SingleVariableCovarianceFromSigma<Pose3>(1, 0.1);
1195  auto transformed = TransformCovariance<Pose3>{{Rot3::RzRyRx(90 * degree, 0., 0.), {20., 0., 0.}}}(cov);
1196  // Uncertainty is spread to other dimensions.
1198  (Vector6{} << 0., 0., 0.1 * 0.1, 0., 0.1 * 0.1 * 20. * 20., 0.).finished(),
1199  Vector6{transformed.diagonal()}));
1200  }
1201 }
1202 
1203 /* ************************************************************************* */
1207 
1208  // Trivial example: start at origin and move to (1, 0, 0) while rotating pi/2
1209  // about z-axis.
1210  Pose3 start;
1211  Pose3 end(Rot3::Rz(M_PI_2), Point3(1, 0, 0));
1212  // This interpolation is easy to calculate by hand.
1213  double t = 0.5;
1214  Pose3 expected0(Rot3::Rz(M_PI_4), Point3(0.5, 0, 0));
1215  EXPECT(assert_equal(expected0, start.interpolateRt(end, t)));
1216 
1217  // Example from Peter Corke
1218  // https://robotacademy.net.au/lesson/interpolating-pose-in-3d/
1219  t = 0.0759; // corresponds to the 10th element when calling `ctraj` in
1220  // the video
1221  Pose3 O;
1222  Pose3 F(Rot3::Roll(0.6).compose(Rot3::Pitch(0.8)).compose(Rot3::Yaw(1.4)),
1223  Point3(1, 2, 3));
1224 
1225  // The expected answer matches the result presented in the video.
1226  Pose3 expected1(interpolate(O.rotation(), F.rotation(), t),
1227  interpolate(O.translation(), F.translation(), t));
1228  EXPECT(assert_equal(expected1, O.interpolateRt(F, t)));
1229 
1230  // Non-trivial interpolation, translation value taken from output.
1231  Pose3 expected2(interpolate(T2.rotation(), T3.rotation(), t),
1233  EXPECT(assert_equal(expected2, T2.interpolateRt(T3, t)));
1234 }
1235 
1236 /* ************************************************************************* */
1237 Pose3 testing_interpolate(const Pose3& t1, const Pose3& t2, double gamma) { return interpolate(t1,t2,gamma); }
1238 
1239 TEST(Pose3, interpolateJacobians) {
1240  {
1241  Pose3 X = Pose3::Identity();
1242  Pose3 Y(Rot3::Rz(M_PI_2), Point3(1, 0, 0));
1243  double t = 0.5;
1244  Pose3 expectedPoseInterp(Rot3::Rz(M_PI_4), Point3(0.5, -0.207107, 0)); // note: different from test above: this is full Pose3 interpolation
1245  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1246  EXPECT(assert_equal(expectedPoseInterp, interpolate(X, Y, t, actualJacobianX, actualJacobianY, actualJacobianT), 1e-5));
1247 
1248  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1249  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1250 
1251  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1252  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1253 
1254  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1255  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1256  }
1257  {
1258  Pose3 X = Pose3::Identity();
1259  Pose3 Y(Rot3::Identity(), Point3(1, 0, 0));
1260  double t = 0.3;
1261  Pose3 expectedPoseInterp(Rot3::Identity(), Point3(0.3, 0, 0));
1262  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1263  EXPECT(assert_equal(expectedPoseInterp, interpolate(X, Y, t, actualJacobianX, actualJacobianY, actualJacobianT), 1e-5));
1264 
1265  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1266  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1267 
1268  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1269  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1270 
1271  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1272  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1273  }
1274  {
1275  Pose3 X = Pose3::Identity();
1276  Pose3 Y(Rot3::Rz(M_PI_2), Point3(0, 0, 0));
1277  double t = 0.5;
1278  Pose3 expectedPoseInterp(Rot3::Rz(M_PI_4), Point3(0, 0, 0));
1279  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1280  EXPECT(assert_equal(expectedPoseInterp, interpolate(X, Y, t, actualJacobianX, actualJacobianY, actualJacobianT), 1e-5));
1281 
1282  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1283  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1284 
1285  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1286  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1287 
1288  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1289  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1290  }
1291  {
1292  Pose3 X(Rot3::Ypr(0.1,0.2,0.3), Point3(10, 5, -2));
1293  Pose3 Y(Rot3::Ypr(1.1,-2.2,-0.3), Point3(-5, 1, 1));
1294  double t = 0.3;
1295  Pose3 expectedPoseInterp(Rot3::Rz(M_PI_4), Point3(0, 0, 0));
1296  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1297  interpolate(X, Y, t, actualJacobianX, actualJacobianY, actualJacobianT);
1298 
1299  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1300  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1301 
1302  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1303  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1304 
1305  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate, X, Y, t);
1306  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1307  }
1308 }
1309 /* ************************************************************************* */
1310 Pose3 testing_interpolate_rt(const Pose3& t1, const Pose3& t2, double gamma) { return t1.interpolateRt(t2, gamma); }
1311 
1312 TEST(Pose3, interpolateRtJacobians) {
1313  {
1314  Pose3 X = Pose3::Identity();
1315  Pose3 Y(Rot3::Rz(M_PI_2), Point3(1, 0, 0));
1316  double t = 0.5;
1317  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1318  X.interpolateRt(Y, t, actualJacobianX, actualJacobianY, actualJacobianT);
1319 
1320  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1321  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1322 
1323  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1324  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1325 
1326  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1327  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1328  }
1329  {
1330  Pose3 X = Pose3::Identity();
1331  Pose3 Y(Rot3::Identity(), Point3(1, 0, 0));
1332  double t = 0.3;
1333  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1334  X.interpolateRt(Y, t, actualJacobianX, actualJacobianY, actualJacobianT);
1335 
1336  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1337  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1338 
1339  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1340  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1341 
1342  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1343  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1344  }
1345  {
1346  Pose3 X = Pose3::Identity();
1347  Pose3 Y(Rot3::Rz(M_PI_2), Point3(0, 0, 0));
1348  double t = 0.5;
1349  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1350  X.interpolateRt(Y, t, actualJacobianX, actualJacobianY, actualJacobianT);
1351 
1352  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1353  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1354 
1355  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1356  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1357 
1358  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1359  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1360  }
1361  {
1362  Pose3 X(Rot3::Ypr(0.1,0.2,0.3), Point3(10, 5, -2));
1363  Pose3 Y(Rot3::Ypr(1.1,-2.2,-0.3), Point3(-5, 1, 1));
1364  double t = 0.3;
1365  Matrix actualJacobianX, actualJacobianY, actualJacobianT;
1366  X.interpolateRt(Y, t, actualJacobianX, actualJacobianY, actualJacobianT);
1367 
1368  Matrix expectedJacobianX = numericalDerivative31<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1369  EXPECT(assert_equal(expectedJacobianX,actualJacobianX,1e-6));
1370 
1371  Matrix expectedJacobianY = numericalDerivative32<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1372  EXPECT(assert_equal(expectedJacobianY,actualJacobianY,1e-6));
1373 
1374  Matrix expectedJacobianT = numericalDerivative33<Pose3,Pose3,Pose3,double>(testing_interpolate_rt, X, Y, t);
1375  EXPECT(assert_equal(expectedJacobianT,actualJacobianT,1e-6));
1376  }
1377 }
1378 
1379 TEST(Pose3, expressionWrappers) {
1380  Pose3 X(Rot3::Ypr(0.1,0.2,0.3), Point3(10, 5, -2));
1381  Pose3 Y(Rot3::Ypr(1.1,-2.2,-0.3), Point3(-5, 1, 1));
1382  double t = 0.3;
1383  Values vals;
1384  vals.insert(0,X);
1385  vals.insert(1,Y);
1386  vals.insert(2,t);
1387 
1388  { // interpolate (templated wrapper applies to all classes)
1389  Matrix expectedJacobianX, expectedJacobianY, expectedJacobianT;
1390  std::vector<Matrix> Hlist = {{},{},{}};
1391  Pose3 expected = interpolate(X, Y, t, expectedJacobianX, expectedJacobianY, expectedJacobianT);
1392  Pose3 actual = interpolate(Pose3_(Key(0)), Pose3_(Key(1)), Double_(Key(2))).value(vals, Hlist);
1393 
1394  EXPECT(assert_equal(expected,actual,1e-6));
1395  EXPECT(assert_equal(expectedJacobianX,Hlist[0],1e-6));
1396  EXPECT(assert_equal(expectedJacobianY,Hlist[1],1e-6));
1397  EXPECT(assert_equal(expectedJacobianT,Hlist[2],1e-6));
1398  }
1399  { // interpolateRt (Pose3 specialisation)
1400  Matrix expectedJacobianX, expectedJacobianY, expectedJacobianT;
1401  std::vector<Matrix> Hlist = {{},{},{}};
1402  Pose3 expected = X.interpolateRt(Y, t, expectedJacobianX, expectedJacobianY, expectedJacobianT);
1403  Pose3 actual = interpolateRt(Pose3_(Key(0)), Pose3_(Key(1)), Double_(Key(2))).value(vals, Hlist);
1404 
1405  EXPECT(assert_equal(expected,actual,1e-6));
1406  EXPECT(assert_equal(expectedJacobianX,Hlist[0],1e-6));
1407  EXPECT(assert_equal(expectedJacobianY,Hlist[1],1e-6));
1408  EXPECT(assert_equal(expectedJacobianT,Hlist[2],1e-6));
1409  }
1410 }
1411 
1412 /* ************************************************************************* */
1413 TEST(Pose3, Create) {
1414  Matrix63 actualH1, actualH2;
1415  Pose3 actual = Pose3::Create(R, P2, actualH1, actualH2);
1416  EXPECT(assert_equal(T, actual));
1417  std::function<Pose3(Rot3, Point3)> create = [](Rot3 R, Point3 t) {
1418  return Pose3::Create(R, t);
1419  };
1420  EXPECT(assert_equal(numericalDerivative21<Pose3,Rot3,Point3>(create, R, P2), actualH1, 1e-9));
1421  EXPECT(assert_equal(numericalDerivative22<Pose3,Rot3,Point3>(create, R, P2), actualH2, 1e-9));
1422 }
1423 
1424 /* ************************************************************************* */
1426  Pose3 pose(Rot3::Identity(), Point3(1, 2, 3));
1427 
1428  // Generate the expected output
1429  std::string expected = "R: [\n\t1, 0, 0;\n\t0, 1, 0;\n\t0, 0, 1\n]\nt: 1 2 3\n";
1430 
1432 }
1433 
1434 /* ************************************************************************* */
1435 TEST(Pose3, ExpmapChainRule) {
1436  // Muliply with an arbitrary matrix and exponentiate
1437  Matrix6 M;
1438  M << 1, 2, 3, 4, 5, 6, //
1439  7, 8, 9, 1, 2, 3, //
1440  4, 5, 6, 7, 8, 9, //
1441  1, 2, 3, 4, 5, 6, //
1442  7, 8, 9, 1, 2, 3, //
1443  4, 5, 6, 7, 8, 9;
1444  auto g = [&](const Vector6& omega) {
1445  return Pose3::Expmap(M*omega);
1446  };
1447 
1448  // Test the derivatives at zero
1449  const Matrix6 expected = numericalDerivative11<Pose3, Vector6>(g, Z_6x1);
1450  EXPECT(assert_equal<Matrix6>(expected, M, 1e-5)); // Pose3::ExpmapDerivative(Z_6x1) is identity
1451 
1452  // Test the derivatives at another value
1453  const Vector6 delta{0.1, 0.2, 0.3, 0.4, 0.5, 0.6};
1454  const Matrix6 expected2 = numericalDerivative11<Pose3, Vector6>(g, delta);
1455  const Matrix6 analytic = Pose3::ExpmapDerivative(M*delta) * M;
1456  EXPECT(assert_equal<Matrix6>(expected2, analytic, 1e-5)); // note tolerance
1457 }
1458 
1459 /* ************************************************************************* */
1460 TEST(Pose3, vec) {
1461  // Test the 'vec' method
1463  Vector16 expected_vec = Eigen::Map<Vector16>(T.matrix().data());
1464  Matrix actualH;
1465  Vector16 actual_vec = T.vec(actualH);
1466  EXPECT(assert_equal(expected_vec, actual_vec));
1467 
1468  // Verify Jacobian with numerical derivatives
1469  std::function<Vector16(const Pose3&)> f = [](const Pose3& p) { return p.vec(); };
1470  Matrix numericalH = numericalDerivative11<Vector16, Pose3>(f, T);
1471  EXPECT(assert_equal(numericalH, actualH, 1e-9));
1472 }
1473 
1474 /* ************************************************************************* */
1475 int main() {
1476  TestResult tr;
1477  return TestRegistry::runAllTests(tr);
1478 }
1479 /* ************************************************************************* */
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::internal::rotation
Rot3 rotation(const Pose3 &pose, OptionalJacobian< 3, 6 > H)
Definition: slam/expressions.h:84
create
ADT create(const Signature &signature)
Definition: testAlgebraicDecisionTree.cpp:145
gtsam::LieGroup::between
Class between(const Class &g) const
Definition: Lie.h:52
gtsam::Point3Pair
std::pair< Point3, Point3 > Point3Pair
Definition: Point3.h:42
Pose2.h
2D Pose
gtsam::TransformCovariance
Definition: Lie.h:390
l3
Point3 l3(2, 2, 0)
gtsam::Expression::value
T value(const Values &values, std::vector< Matrix > *H=nullptr) const
Return value and optional derivatives, reverse AD version Notes: this is not terribly efficient,...
Definition: Expression-inl.h:143
pose
static const Pose3 pose(Rot3(Vector3(1, -1, -1).asDiagonal()), Point3(0, 0, 0.5))
inverse
const EIGEN_DEVICE_FUNC InverseReturnType inverse() const
Definition: ArrayCwiseUnaryOps.h:411
gtsam::Double_
Expression< double > Double_
Definition: nonlinear/expressions.h:28
gtsam::Pose3::transformTo
Point3 transformTo(const Point3 &point, OptionalJacobian< 3, 6 > Hself={}, OptionalJacobian< 3, 3 > Hpoint={}) const
takes point in world coordinates and transforms it to Pose coordinates
Definition: Pose3.cpp:404
s
RealScalar s
Definition: level1_cplx_impl.h:126
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
d
static const double d[K][N]
Definition: igam.h:11
GTSAM_CONCEPT_TESTABLE_INST
#define GTSAM_CONCEPT_TESTABLE_INST(T)
Definition: Testable.h:176
gtsam::IsMatrixLieGroup
Definition: Lie.h:311
ceres::sin
Jet< T, N > sin(const Jet< T, N > &f)
Definition: jet.h:439
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
TestHarness.h
gtsam.examples.SFMExample_bal.stream
stream
Definition: SFMExample_bal.py:24
b
Scalar * b
Definition: benchVecAdd.cpp:17
test_cases::omegas
auto omegas
Definition: testPose3.cpp:899
gtsam::Y
GaussianFactorGraphValuePair Y
Definition: HybridGaussianProductFactor.cpp:29
screwPose3::w
double w
Definition: testPose3.cpp:123
gtsam::assert_print_equal
bool assert_print_equal(const std::string &expected, const V &actual, const std::string &s="")
Definition: TestableAssertions.h:353
gtsam::LieGroup::compose
Class compose(const Class &g) const
Definition: Lie.h:48
x
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
Definition: gnuplot_common_settings.hh:12
screwPose3::xi
Vector xi
Definition: testPose3.cpp:124
gtsam::numericalDerivative11
internal::FixedSizeMatrix< Y, X >::type numericalDerivative11(std::function< Y(const X &)> h, const X &x, double delta=1e-5)
New-style numerical derivatives using manifold_traits.
Definition: numericalDerivative.h:110
simple::R3
static Rot3 R3
Definition: testInitializePose3.cpp:54
gtsam::numericalDerivative22
internal::FixedSizeMatrix< Y, X2 >::type numericalDerivative22(std::function< Y(const X1 &, const X2 &)> h, const X1 &x1, const X2 &x2, double delta=1e-5)
Definition: numericalDerivative.h:195
bearing_proxy
Unit3 bearing_proxy(const Pose3 &pose, const Point3 &point)
Definition: testPose3.cpp:770
transformPoseTo_
Pose3 transformPoseTo_(const Pose3 &pose, const Pose3 &pose2)
Definition: testPose3.cpp:557
T3
static const Pose3 T3(Rot3::Rodrigues(-90, 0, 0), Point3(1, 2, 3))
gtsam::utils.numerical_derivative.retract
def retract(a, np.ndarray xi)
Definition: numerical_derivative.py:44
gtsam::Matrix
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
log
const EIGEN_DEVICE_FUNC LogReturnType log() const
Definition: ArrayCwiseUnaryOps.h:128
simple::pose2
static Pose3 pose2
Definition: testInitializePose3.cpp:58
X
#define X
Definition: icosphere.cpp:20
gtsam::interpolateRt
Pose3_ interpolateRt(const Pose3_ &p, const Pose3_ &q, const Double_ &t)
Definition: slam/expressions.h:61
test_cases::vs
static const std::vector< Vector3 > vs
Definition: testPose3.cpp:900
gtsam::Vector3
Eigen::Vector3d Vector3
Definition: Vector.h:44
testLie.h
test_pose_adjoint_map
Definition: testPoseAdjointMap.h:24
res
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Definition: PartialRedux_count.cpp:3
os
ofstream os("timeSchurFactors.csv")
tol
static const double tol
Definition: testPose3.cpp:42
TEST
TEST(Pose3, Concept)
Definition: testPose3.cpp:45
gtsam::IsGroup
Definition: Group.h:42
gtsam::Vector
Eigen::VectorXd Vector
Definition: Vector.h:39
gtsam::skewSymmetric
Matrix3 skewSymmetric(double wx, double wy, double wz)
Definition: base/Matrix.h:381
screwPose3::c
double c
Definition: testPose3.cpp:123
gtsam::Pose3::matrix
Matrix4 matrix() const
Definition: Pose3.cpp:356
x3
Pose3 x3(Rot3::Ypr(M_PI/4.0, 0.0, 0.0), l2)
EQUALITY
#define EQUALITY(expected, actual)
Definition: Test.h:127
ceres::cos
Jet< T, N > cos(const Jet< T, N > &f)
Definition: jet.h:426
TestableAssertions.h
Provides additional testing facilities for common data structures.
Eigen::Triplet::value
const Scalar & value() const
Definition: SparseUtil.h:178
gtsam::Pose3::range
double range(const Point3 &point, OptionalJacobian< 1, 6 > Hself={}, OptionalJacobian< 1, 3 > Hpoint={}) const
Definition: Pose3.cpp:432
A
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:48
l2
Point3 l2(1, 1, 0)
biased_x_rotation::omega
const double omega
Definition: testPreintegratedRotation.cpp:32
gtsam::Pose3::transformPoseFrom
Pose3 transformPoseFrom(const Pose3 &aTb, OptionalJacobian< 6, 6 > Hself={}, OptionalJacobian< 6, 6 > HaTb={}) const
Definition: Pose3.cpp:364
gtsam::range
Double_ range(const Point2_ &p, const Point2_ &q)
Definition: slam/expressions.h:30
simple::p2
static Point3 p2
Definition: testInitializePose3.cpp:51
gtsam::Pose3::AdjointTranspose
Vector6 AdjointTranspose(const Vector6 &x, OptionalJacobian< 6, 6 > H_this={}, OptionalJacobian< 6, 6 > H_x={}) const
The dual version of Adjoint.
Definition: Pose3.cpp:97
gtsam_unstable.tests.test_ProjectionFactorRollingShutter.point
point
Definition: test_ProjectionFactorRollingShutter.py:25
gtsam::Pose3::transformPoseTo
Pose3 transformPoseTo(const Pose3 &wTb, OptionalJacobian< 6, 6 > Hself={}, OptionalJacobian< 6, 6 > HwTb={}) const
Definition: Pose3.cpp:371
Expmap
Pose2_ Expmap(const Vector3_ &xi)
Definition: InverseKinematicsExampleExpressions.cpp:47
gtsam::Pose3::Adjoint
Vector6 Adjoint(const Vector6 &xi_b, OptionalJacobian< 6, 6 > H_this={}, OptionalJacobian< 6, 6 > H_xib={}) const
Definition: Pose3.cpp:79
transformPoseFrom_
Pose3 transformPoseFrom_(const Pose3 &wTa, const Pose3 &aTb)
Definition: testPose3.cpp:528
id
static const Similarity3 id
Definition: testSimilarity3.cpp:44
gtsam::transformFrom
Point3_ transformFrom(const Pose3_ &x, const Point3_ &p)
Definition: slam/expressions.h:47
testPoseAdjointMap.h
Support utilities for using AdjointMap for transforming Pose2 and Pose3 covariance matrices.
T4
static const Similarity3 T4(R, P, s)
gtsam.examples.PlanarManipulatorExample.delta
def delta(g0, g1)
Definition: PlanarManipulatorExample.py:45
xl4
Pose3 xl4(Rot3::Ypr(0.0, 0.0, 1.0), Point3(1, 4,-4))
screwPose3::expectedT
Point3 expectedT(0.29552, 0.0446635, 1)
xl2
Pose3 xl2(Rot3::Ypr(0.0, 1.0, 0.0), Point3(1, 1, 0))
I
#define I
Definition: main.h:112
gtsam::transformTo
Line3 transformTo(const Pose3 &wTc, const Line3 &wL, OptionalJacobian< 4, 6 > Dpose, OptionalJacobian< 4, 4 > Dline)
Definition: Line3.cpp:94
x1
Pose3 x1
Definition: testPose3.cpp:692
gtsam::Rot3
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition: Rot3.h:58
gtsam::Pose3
Definition: Pose3.h:37
GTSAM_CONCEPT_LIE_INST
#define GTSAM_CONCEPT_LIE_INST(T)
Definition: Lie.h:410
M_PI_4
#define M_PI_4
Definition: mconf.h:119
screwPose3::expected
Pose3 expected(expectedR, expectedT)
Agrawal06iros
Pose3 Agrawal06iros(const Vector &xi)
Definition: testPose3.cpp:271
gtsam::Pose3::inverse
Pose3 inverse() const
inverse transformation with derivatives
Definition: Pose3.cpp:61
gtsam::Pose3::interpolateRt
Pose3 interpolateRt(const Pose3 &T, double t, OptionalJacobian< 6, 6 > Hself={}, OptionalJacobian< 6, 6 > Harg={}, OptionalJacobian< 6, 1 > Ht={}) const
Definition: Pose3.cpp:189
gtsam::Pose3::equals
bool equals(const Pose3 &pose, double tol=1e-9) const
assert equality up to a tolerance
Definition: Pose3.cpp:184
degree
const double degree
Definition: SimpleRotation.cpp:59
gtsam::Pose3::translation
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
Definition: Pose3.cpp:342
l4
Point3 l4(1, 4,-4)
screwPose3::expectedR
Rot3 expectedR(c, -s, 0, s, c, 0, 0, 0, 1)
gtsam::Pose3::AdjointMap
Matrix6 AdjointMap() const
Definition: Pose3.cpp:69
CHECK_LIE_GROUP_DERIVATIVES
#define CHECK_LIE_GROUP_DERIVATIVES(t1, t2)
Definition: testLie.h:82
T5
static const Similarity3 T5(R, P, 10)
example2::aTb
Point3 aTb
Definition: testEssentialMatrixFactor.cpp:585
simple::p3
static Point3 p3
Definition: testInitializePose3.cpp:53
test_cases::large
static const std::vector< Vector3 > large
Definition: testPose3.cpp:897
T2
static const Pose3 T2(Rot3::Rodrigues(0.3, 0.2, 0.1), P2)
transform
EIGEN_DONT_INLINE void transform(const Transformation &t, Data &data)
Definition: geometry.cpp:25
Eigen::Triplet< double >
R
static const Rot3 R
Definition: testPose3.cpp:37
gamma
#define gamma
Definition: mconf.h:85
gtsam::LieGroup::localCoordinates
TangentVector localCoordinates(const Class &g) const
localCoordinates as required by manifold concept: finds tangent vector between *this and g
Definition: Lie.h:136
gtsam::symbol_shorthand::F
Key F(std::uint64_t j)
Definition: inference/Symbol.h:153
Eigen::Map
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:94
range_proxy
double range_proxy(const Pose3 &pose, const Point3 &point)
Definition: testPose3.cpp:700
gtsam::LieGroup::logmap
TangentVector logmap(const Class &g) const
Definition: Lie.h:84
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
p1
Vector3f p1
Definition: MatrixBase_all.cpp:2
g
void g(const string &key, int i)
Definition: testBTree.cpp:41
gtsam::equals
Definition: Testable.h:112
TestResult
Definition: TestResult.h:26
y
Scalar * y
Definition: level1_cplx_impl.h:124
matrix
Map< Matrix< T, Dynamic, Dynamic, ColMajor >, 0, OuterStride<> > matrix(T *data, int rows, int cols, int stride)
Definition: gtsam/3rdparty/Eigen/blas/common.h:110
M_PI_2
#define M_PI_2
Definition: mconf.h:118
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
screwPose3
Definition: testPose3.cpp:122
gtsam::Vector16
Eigen::Matrix< double, 16, 1 > Vector16
Definition: Pose3.cpp:531
gtsam::symbol_shorthand::O
Key O(std::uint64_t j)
Definition: inference/Symbol.h:162
gtsam::Pose3::bearing
Unit3 bearing(const Point3 &point, OptionalJacobian< 2, 6 > Hself={}, OptionalJacobian< 2, 3 > Hpoint={}) const
Definition: Pose3.cpp:460
gtsam::interpolate
T interpolate(const T &X, const T &Y, double t, typename MakeOptionalJacobian< T, T >::type Hx={}, typename MakeOptionalJacobian< T, T >::type Hy={}, typename MakeOptionalJacobian< T, double >::type Ht={})
Definition: Lie.h:363
gtsam::Pose3::rotation
const Rot3 & rotation(OptionalJacobian< 3, 6 > Hself={}) const
get rotation
Definition: Pose3.cpp:348
pose2
Definition: testFrobeniusFactor.cpp:193
xl3
Pose3 xl3(Rot3::Ypr(1.0, 0.0, 0.0), Point3(2, 2, 0))
so3::R2
SO3 R2
Definition: testShonanFactor.cpp:43
gtsam
traits
Definition: SFMdata.h:40
gtsam::Values
Definition: Values.h:65
test_cases::small
static const std::vector< Vector3 > small
Definition: testPose3.cpp:894
expressions.h
Common expressions for solving geometry/slam/sfm problems.
gtsam::symbol_shorthand::W
Key W(std::uint64_t j)
Definition: inference/Symbol.h:170
gtsam::testing::compose
T compose(const T &t1, const T &t2)
Definition: lieProxies.h:39
Pose3_
Expression< Pose3 > Pose3_
Definition: testExpression.cpp:32
CHECK
#define CHECK(condition)
Definition: Test.h:108
gtsam::internal::translation
Point3 translation(const Pose3 &pose, OptionalJacobian< 3, 6 > H)
Definition: slam/expressions.h:88
gtsam::numericalDerivative21
internal::FixedSizeMatrix< Y, X1 >::type numericalDerivative21(const std::function< Y(const X1 &, const X2 &)> &h, const X1 &x1, const X2 &x2, double delta=1e-5)
Definition: numericalDerivative.h:166
std
Definition: BFloat16.h:88
gtsam::Pose3::transformFrom
Point3 transformFrom(const Point3 &point, OptionalJacobian< 3, 6 > Hself={}, OptionalJacobian< 3, 3 > Hpoint={}) const
takes point in Pose coordinates and transforms it to world coordinates
Definition: Pose3.cpp:380
origin
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 origin
Definition: gnuplot_common_settings.hh:45
xl1
Pose3 xl1(Rot3::Ypr(0.0, 0.0, 0.0), Point3(1, 0, 0))
p
float * p
Definition: Tutorial_Map_using.cpp:9
testing_interpolate_rt
Pose3 testing_interpolate_rt(const Pose3 &t1, const Pose3 &t2, double gamma)
Definition: testPose3.cpp:1310
transformFrom_
Point3 transformFrom_(const Pose3 &pose, const Point3 &point)
Definition: testPose3.cpp:424
v2
Vector v2
Definition: testSerializationBase.cpp:39
gtsam::Values::insert
void insert(Key j, const Value &val)
Definition: Values.cpp:156
main
int main()
Definition: testPose3.cpp:1475
gtsam::Print
void Print(const CONTAINER &keys, const string &s, const KeyFormatter &keyFormatter)
Definition: Key.cpp:65
v
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
gtsam::Similarity3::matrix
Matrix4 matrix() const
Calculate 4*4 matrix group equivalent.
Definition: Similarity3.cpp:291
gtsam::testing::between
T between(const T &t1, const T &t2)
Definition: lieProxies.h:36
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:41
transform_to_
Point3 transform_to_(const Pose3 &pose, const Point3 &point)
Definition: testPose3.cpp:472
gtsam::Point3
Vector3 Point3
Definition: Point3.h:38
gtsam::LieGroup::retract
Class retract(const TangentVector &v) const
retract as required by manifold concept: applies v at *this
Definition: Lie.h:131
Eigen::Matrix< double, 6, 6 >
P
static const Point3 P(0.2, 0.7,-2)
l1
Point3 l1(1, 0, 0)
testDerivAdjointTranspose
Vector6 testDerivAdjointTranspose(const Vector6 &xi, const Vector6 &v)
Definition: testPose3.cpp:1037
gtsam::Unit3
Represents a 3D point on a unit sphere.
Definition: Unit3.h:42
v3
Vector v3
Definition: testSerializationBase.cpp:40
gtsam::internal::Align
static Similarity2 Align(const Point2Pairs &d_abPointPairs, const Rot2 &aRb, const Point2Pair &centroids)
This method estimates the similarity transform from differences point pairs, given a known or estimat...
Definition: Similarity2.cpp:74
gtsam::LieGroup::expmap
Class expmap(const TangentVector &v) const
Definition: Lie.h:78
M_PI
#define M_PI
Definition: mconf.h:117
screwPose3::a
double a
Definition: testPose3.cpp:123
Eigen::placeholders::end
static const EIGEN_DEPRECATED end_t end
Definition: IndexedViewHelper.h:181
T1
static const Similarity3 T1(R, Point3(3.5, -8.2, 4.2), 1)
gtsam::Bearing
Definition: BearingRange.h:35
gtsam::transformPoseTo
Pose3_ transformPoseTo(const Pose3_ &p, const Pose3_ &q)
Definition: slam/expressions.h:57
lieProxies.h
Provides convenient mappings of common member functions for testing.
align_3::t
Point2 t(10, 10)
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
ceres::Vector
Eigen::Matrix< double, Eigen::Dynamic, 1 > Vector
Definition: gtsam/3rdparty/ceres/eigen.h:38
testDerivAdjoint
Vector6 testDerivAdjoint(const Vector6 &xi, const Vector6 &v)
Definition: testPose3.cpp:1015
test_cases
Definition: testPose3.cpp:893
GTSAM_CONCEPT_ASSERT
#define GTSAM_CONCEPT_ASSERT(concept)
Definition: base/concepts.h:25
adjoint
void adjoint(const MatrixType &m)
Definition: adjoint.cpp:67
x2
Pose3 x2(Rot3::Ypr(0.0, 0.0, 0.0), l2)
CHECK_CHART_DERIVATIVES
#define CHECK_CHART_DERIVATIVES(t1, t2)
Definition: testLie.h:85
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
T
static const Pose3 T(R, P2)
Pose3.h
3D Pose manifold SO(3) x R^3 and group SE(3)
P2
static const Point3 P2(3.5,-8.2, 4.2)
testing_interpolate
Pose3 testing_interpolate(const Pose3 &t1, const Pose3 &t2, double gamma)
Definition: testPose3.cpp:1237
v1
Vector v1
Definition: testSerializationBase.cpp:38
gtsam::Pose2
Definition: Pose2.h:39
ROT3_DEFAULT_COORDINATES_MODE
#define ROT3_DEFAULT_COORDINATES_MODE
Definition: Rot3.h:43
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51
range_pose_proxy
double range_pose_proxy(const Pose3 &pose, const Pose3 &point)
Definition: testPose3.cpp:735


gtsam
Author(s):
autogenerated on Fri Apr 25 2025 03:06:54