testGal3.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
3  * Atlanta, Georgia 30332-0415
4  * All Rights Reserved
5  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
6  * See LICENSE for the license information
7  * -------------------------------------------------------------------------- */
8 
16 #include <gtsam/geometry/Gal3.h>
17 
20 #include <gtsam/base/testLie.h> // For CHECK_LIE_GROUP_DERIVATIVES, etc.
21 #include <gtsam/geometry/Rot3.h>
22 #include <gtsam/geometry/Point3.h>
23 #include <gtsam/geometry/Pose3.h> // Included for kTestPose definition
24 
26 #include <vector>
27 #include <functional> // For std::bind if using numerical derivatives
28 
29 using namespace std;
30 using namespace gtsam;
31 
32 // Define tolerance
33 static const double kTol = 1e-8;
34 
35 // Instantiate Testable and Lie concepts for Gal3
38 
39 // Define common test values
40 const Rot3 kTestRot = Rot3::RzRyRx(0.1, -0.2, 0.3);
41 const Point3 kTestPos(1.0, -2.0, 3.0);
42 const Velocity3 kTestVel(0.5, 0.6, -0.7);
43 const double kTestTime = 1.5;
46 
47 
48 /* ************************************************************************* */
49 TEST(Gal3, Concept) {
51  GTSAM_CONCEPT_ASSERT(IsManifold<Gal3>);
53 }
54 
55 /* ************************************************************************* */
56 // Define test instances for Lie group checks
57 const Gal3 kTestGal3_Lie1(Rot3::RzRyRx(0.1, -0.2, 0.3), Point3(1.0, -2.0, 3.0), Velocity3(0.5, 0.6, -0.7), 1.5);
58 const Gal3 kTestGal3_Lie2(Rot3::RzRyRx(-0.2, 0.3, 0.1), Point3(-2.0, 3.0, 1.0), Velocity3(0.6, -0.7, 0.5), 2.0);
59 const Gal3 kIdentity_Lie = Gal3::Identity();
60 
61 /* ************************************************************************* */
62 // Use GTSAM's Lie Group Test Macros
63 TEST(Gal3, LieGroupDerivatives) {
68 }
69 
70 /* ************************************************************************* */
71 // Check derivatives of retract and localCoordinates
72 TEST(Gal3, ChartDerivatives) {
77 }
78 
79 
80 /* ************************************************************************* */
81 TEST(Gal3, StaticConstructorsValue) {
82  Gal3 g1 = Gal3::Create(kTestRot, kTestPos, kTestVel, kTestTime);
84 
85  Gal3 g2 = Gal3::FromPoseVelocityTime(kTestPose, kTestVel, kTestTime);
87 }
88 
89 /* ************************************************************************* */
90 TEST(Gal3, ComponentAccessorsValue) {
101 }
102 
103 /* ************************************************************************* */
104 TEST(Gal3, MatrixConstructorValue) {
105  Matrix5 M_known = kTestGal3.matrix();
106  Gal3 g_from_matrix(M_known);
107  EXPECT(assert_equal(kTestGal3, g_from_matrix, kTol));
108 
109  // Test invalid matrix construction (violating zero structure)
110  Matrix5 M_invalid_zero = M_known;
111  M_invalid_zero(4, 0) = 1e-5;
112  try {
113  Gal3 g_invalid(M_invalid_zero);
114  FAIL("Constructor should have thrown for invalid matrix structure (zero violation).");
115  } catch (const std::invalid_argument& e) {
116  // Expected exception
117  } catch (...) {
118  FAIL("Constructor threw unexpected exception type for invalid matrix.");
119  }
120 
121  // Test invalid matrix construction (violating M(3,3) == 1)
122  Matrix5 M_invalid_diag = M_known;
123  M_invalid_diag(3, 3) = 0.9;
124  try {
125  Gal3 g_invalid(M_invalid_diag);
126  FAIL("Constructor should have thrown for invalid matrix structure (M(3,3) != 1).");
127  } catch (const std::invalid_argument& e) {
128  // Expected exception
129  } catch (...) {
130  FAIL("Constructor threw unexpected exception type for invalid matrix.");
131  }
132 }
133 
134 /* ************************************************************************* */
135 /* ************************************************************************* */
136 TEST(Gal3, Identity) {
137  // Original hardcoded expected data (kept for functional equivalence)
138  const Matrix3 expected_R_mat = Matrix3::Identity();
139  const Vector3 expected_r_vec = Vector3::Zero();
140  const Vector3 expected_v_vec = Vector3::Zero();
141  const double expected_t_val = 0.0;
142 
143  Gal3 custom_ident = Gal3::Identity();
144 
145  // Original component checks (kept for functional equivalence)
146  EXPECT(assert_equal(expected_R_mat, custom_ident.rotation().matrix(), kTol));
147  EXPECT(assert_equal(Point3(expected_r_vec), custom_ident.translation(), kTol));
148  EXPECT(assert_equal(expected_v_vec, custom_ident.velocity(), kTol));
149  EXPECT_DOUBLES_EQUAL(expected_t_val, custom_ident.time(), kTol);
150 
151  // Original full object check (kept for functional equivalence)
152  EXPECT(assert_equal(Gal3(Rot3(expected_R_mat), Point3(expected_r_vec), expected_v_vec, expected_t_val), custom_ident, kTol));
153 }
154 
155 /* ************************************************************************* */
156 TEST(Gal3, HatVee) {
157  // Test Case 1
158  const Vector10 tau_vec_1 = (Vector10() <<
159  -0.9919387548344049, 0.41796965721894275, -0.08567669832855362, // rho
160  -0.24728318780816563, 0.42470896104182426, 0.37654216726012074, // nu
161  -0.4665439537974297, -0.46391731412948783, -0.46638346398428376, // theta
162  -0.2703091399101363 // t_tan
163  ).finished();
164  const Matrix5 expected_xi_matrix_1 = (Matrix5() <<
165  0.0, 0.46638346398428376, -0.46391731412948783, -0.24728318780816563, -0.9919387548344049,
166  -0.46638346398428376, 0.0, 0.4665439537974297, 0.42470896104182426, 0.41796965721894275,
167  0.46391731412948783, -0.4665439537974297, 0.0, 0.37654216726012074, -0.08567669832855362,
168  0.0, 0.0, 0.0, 0.0, -0.2703091399101363,
169  0.0, 0.0, 0.0, 0.0, 0.0
170  ).finished();
171 
172  Matrix5 custom_Xi_1 = Gal3::Hat(tau_vec_1);
173  EXPECT(assert_equal(expected_xi_matrix_1, custom_Xi_1, kTol));
174 
175  Vector10 custom_tau_rec_1 = Gal3::Vee(expected_xi_matrix_1);
176  EXPECT(assert_equal(tau_vec_1, custom_tau_rec_1, kTol));
177 
178  // Round trip check
179  Vector10 custom_tau_rec_roundtrip_1 = Gal3::Vee(custom_Xi_1);
180  EXPECT(assert_equal(tau_vec_1, custom_tau_rec_roundtrip_1, kTol));
181 }
182 
183 /* ************************************************************************* */
185  // Test Case 1
186  const Vector10 tau_vec_1 = (Vector10() <<
187  -0.6659680127970163, 0.0801034296770802, -0.005425197747099379, // rho
188  -0.24823309993679712, -0.3282613511681929, -0.3614305580886979, // nu
189  0.3267045270397072, -0.21318895514136532, -0.1810111529904679, // theta
190  -0.11137002094819903 // t_tan
191  ).finished();
192  const Matrix3 expected_R_mat_1 = (Matrix3() <<
193  0.961491754653074, 0.14119138670272793, -0.23579354964696073,
194  -0.20977429976081094, 0.9313179826319476, -0.297727322203087,
195  0.17756223949368974, 0.33572579219851445, 0.925072885538575
196  ).finished();
197  const Point3 expected_r_vec_1(-0.637321673031978, 0.16116104619552254, -0.03248254605908951);
198  const Velocity3 expected_v_vec_1(-0.22904001980446076, -0.23988916442951638, -0.4308710747620977);
199  const double expected_t_val_1 = -0.11137002094819903;
200  const Gal3 expected_exp_1(Rot3(expected_R_mat_1), expected_r_vec_1, expected_v_vec_1, expected_t_val_1);
201 
202  Gal3 custom_exp_1 = Gal3::Expmap(tau_vec_1);
203  EXPECT(assert_equal(expected_exp_1, custom_exp_1, kTol));
204 
205  // Check derivatives
206  Matrix10 aH;
207  Gal3::Expmap(tau_vec_1, aH);
208  std::function<Gal3(const Vector10&)> expmap_func = [](const Vector10& v){ return Gal3::Expmap(v); };
209  Matrix expectedH = numericalDerivative11(expmap_func, tau_vec_1);
210  EXPECT(assert_equal(expectedH, aH, 1e-6));
211 }
212 
213 /* ************************************************************************* */
214 TEST(Gal3, Logmap) {
215  // Test case 1: Logmap(GroupElement)
216  const Matrix3 input_R_mat_1 = (Matrix3() <<
217  -0.8479395778141634, 0.26601628670932354, -0.4585126035145831,
218  0.5159883846729487, 0.612401478276553, -0.5989327310201821,
219  0.1214679351060988, -0.744445944720015, -0.6565407650184298
220  ).finished();
221  const Point3 input_r_vec_1(0.6584021866593519, -0.3393257406257678, -0.5420636579124554);
222  const Velocity3 input_v_vec_1(0.1772802663861217, 0.3146080790621266, 0.7173535084539808);
223  const double input_t_val_1 = -0.12088016100268817;
224  const Gal3 custom_g_1(Rot3(input_R_mat_1), input_r_vec_1, input_v_vec_1, input_t_val_1);
225 
226  const Vector10 expected_log_tau_1 = (Vector10() <<
227  -0.6366686897004876, -0.2565186503803428, -1.1108185946230884, // rho
228  1.122213550821757, -0.21828427331226408, 0.03100839182220047, // nu
229  -0.6312616056853186, -2.516056355068653, 1.0844223965979727, // theta
230  -0.12088016100268817 // t_tan
231  ).finished();
232 
233  Vector10 custom_log_tau_1 = Gal3::Logmap(custom_g_1);
234  // Note: Logmap can have higher errors near singularities
235  EXPECT(assert_equal(expected_log_tau_1, custom_log_tau_1, kTol * 1e3));
236 
237  // Test Log(Exp(tau)) round trip (using data from Expmap test)
238  const Vector10 tau_vec_orig_rt1 = (Vector10() <<
239  -0.6659680127970163, 0.0801034296770802, -0.005425197747099379,
240  -0.24823309993679712, -0.3282613511681929, -0.3614305580886979,
241  0.3267045270397072, -0.21318895514136532, -0.1810111529904679,
242  -0.11137002094819903
243  ).finished();
244  Gal3 g_exp_rt1 = Gal3::Expmap(tau_vec_orig_rt1);
245  Vector10 tau_log_exp_rt1 = Gal3::Logmap(g_exp_rt1);
246  EXPECT(assert_equal(tau_vec_orig_rt1, tau_log_exp_rt1, kTol * 10));
247 
248  // Test Exp(Log(g)) round trip (using data from first Logmap test)
249  Gal3 custom_g_orig_rt2 = custom_g_1;
250  Vector10 tau_log_rt2 = Gal3::Logmap(custom_g_orig_rt2);
251  Gal3 g_exp_log_rt2 = Gal3::Expmap(tau_log_rt2);
252  EXPECT(assert_equal(custom_g_orig_rt2, g_exp_log_rt2, kTol * 10));
253 }
254 
255 /* ************************************************************************* */
256 TEST(Gal3, Compose) {
257  // Test Case 1
258  const Matrix3 g1_R_mat_1 = (Matrix3() <<
259  -0.5427153955878299, 0.8391431164114453, 0.03603927817303032,
260  0.8040805715986894, 0.5314810596281534, -0.2664250694549225,
261  -0.24272295682417533, -0.11561450357036887, -0.963181630220753
262  ).finished();
263  const Point3 g1_r_vec_1(0.9978490360071179, -0.5634861893781862, 0.025864788808796835);
264  const Velocity3 g1_v_vec_1(0.04857438013356852, -0.012834026018545996, 0.945550047767139);
265  const double g1_t_val_1 = -0.41496643117394594;
266  const Gal3 c1_1(Rot3(g1_R_mat_1), g1_r_vec_1, g1_v_vec_1, g1_t_val_1);
267 
268  const Matrix3 g2_R_mat_1 = (Matrix3() <<
269  -0.3264538540162394, 0.24276278793202133, -0.9135064914894779,
270  0.9430076454867458, 0.1496317101600385, -0.2972321178273404,
271  0.06453264097716288, -0.9584761760784951, -0.27777501352435885
272  ).finished();
273  const Point3 g2_r_vec_1(-0.1995427558196442, 0.7830589040103644, -0.433370507989717);
274  const Velocity3 g2_v_vec_1(0.8986541507293722, 0.051990700444202176, -0.8278883042875157);
275  const double g2_t_val_1 = -0.6155723080111539;
276  const Gal3 c2_1(Rot3(g2_R_mat_1), g2_r_vec_1, g2_v_vec_1, g2_t_val_1);
277 
278  const Matrix3 expected_R_mat_1 = (Matrix3() <<
279  0.9708156167565788, -0.04073147244077803, 0.23634294026763253,
280  0.22150238776832248, 0.5300893429357028, -0.8184998355032984,
281  -0.09194417042137741, 0.8469629482207595, 0.5236411308011658
282  ).finished();
283  const Point3 expected_r_vec_1(1.7177230471349891, -0.18439262777314758, -0.18087448280827323);
284  const Velocity3 expected_v_vec_1(-0.4253479212754224, 0.9579585887030762, 1.5188219826819997);
285  const double expected_t_val_1 = -1.0305387391850998;
286  const Gal3 expected_comp_1(Rot3(expected_R_mat_1), expected_r_vec_1, expected_v_vec_1, expected_t_val_1);
287 
288  Gal3 custom_comp_1 = c1_1 * c2_1; // Or c1_1.compose(c2_1)
289  EXPECT(assert_equal(expected_comp_1, custom_comp_1, kTol));
290 }
291 
292 /* ************************************************************************* */
294  Gal3 expected_identity = Gal3::Identity();
295 
296  // Test Case 1
297  const Matrix3 g_R_mat_1 = (Matrix3() <<
298  0.6680516673568877, 0.2740542884848495, -0.6918101016209183,
299  0.6729369985913887, -0.6193062871756463, 0.4044941514923666,
300  -0.31758898858193396, -0.7357676057205693, -0.5981498680963873
301  ).finished();
302  const Point3 g_r_vec_1(0.06321286832132045, -0.9214393132931736, -0.12472480681013542);
303  const Velocity3 g_v_vec_1(0.4770686298036335, 0.2799576331302327, -0.29190264050471715);
304  const double g_t_val_1 = 0.3757227805330059;
305  const Gal3 custom_g_1(Rot3(g_R_mat_1), g_r_vec_1, g_v_vec_1, g_t_val_1);
306 
307  const Matrix3 expected_inv_R_mat_1 = (Matrix3() <<
308  0.6680516673568877, 0.6729369985913887, -0.31758898858193396,
309  0.2740542884848495, -0.6193062871756463, -0.7357676057205693,
310  -0.6918101016209183, 0.4044941514923666, -0.5981498680963873
311  ).finished();
312  const Point3 expected_inv_r_vec_1(0.7635904739613719, -0.6150700906051861, 0.32598918251792036);
313  const Velocity3 expected_inv_v_vec_1(-0.5998054073176801, -0.17213568846657853, 0.042198146082895516);
314  const double expected_inv_t_val_1 = -0.3757227805330059;
315  const Gal3 expected_inv_1(Rot3(expected_inv_R_mat_1), expected_inv_r_vec_1, expected_inv_v_vec_1, expected_inv_t_val_1);
316 
317  Gal3 custom_inv_1 = custom_g_1.inverse();
318  EXPECT(assert_equal(expected_inv_1, custom_inv_1, kTol));
319 
320  // Check g * g.inverse() == Identity
321  Gal3 ident_c_1 = custom_g_1 * custom_inv_1;
322  EXPECT(assert_equal(expected_identity, ident_c_1, kTol));
323 }
324 
325 /* ************************************************************************* */
327  // Test Case 1
328  const Matrix3 g1_R_mat_1 = (Matrix3() <<
329  -0.2577418495238488, 0.7767168385303765, 0.5747000015202739,
330  -0.6694062876067332, -0.572463082520484, 0.47347781496466923,
331  0.6967527259484512, -0.26267274676776586, 0.6674868290752107
332  ).finished();
333  const Point3 g1_r_vec_1(0.680375434309419, -0.21123414636181392, 0.5661984475172117);
334  const Velocity3 g1_v_vec_1(0.536459189623808, -0.44445057839362445, 0.10793991159086103);
335  const double g1_t_val_1 = -0.0452058962756795;
336  const Gal3 c1_1(Rot3(g1_R_mat_1), g1_r_vec_1, g1_v_vec_1, g1_t_val_1);
337 
338  const Matrix3 g2_R_mat_1 = (Matrix3() <<
339  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
340  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
341  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
342  ).finished();
343  const Point3 g2_r_vec_1(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
344  const Velocity3 g2_v_vec_1(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
345  const double g2_t_val_1 = -0.6866418214918308;
346  const Gal3 c2_1(Rot3(g2_R_mat_1), g2_r_vec_1, g2_v_vec_1, g2_t_val_1);
347 
348  // Expected: c1.inverse() * c2
349  const Matrix3 expected_R_mat_1 = (Matrix3() <<
350  -0.6566377699430239, 0.753549894443112, -0.0314546605295386,
351  -0.4242286152401611, -0.3345440819370167, 0.8414929228771536,
352  0.6235839326792096, 0.5659000033801861, 0.5393517081447288
353  ).finished();
354  const Point3 expected_r_vec_1(-0.8113603292280276, 0.06632931940009146, 0.535144598419476);
355  const Velocity3 expected_v_vec_1(0.8076311151757332, -0.7866187376416414, -0.4028976707214998);
356  const double expected_t_val_1 = -0.6414359252161513;
357  const Gal3 expected_btw_1(Rot3(expected_R_mat_1), expected_r_vec_1, expected_v_vec_1, expected_t_val_1);
358 
359  Gal3 custom_btw_1 = c1_1.between(c2_1);
360  EXPECT(assert_equal(expected_btw_1, custom_btw_1, kTol));
361 }
362 
363 /* ************************************************************************* */
364 TEST(Gal3, MatrixComponents) {
365  // Test Case 1
366  const Matrix3 source_R_mat_1 = (Matrix3() <<
367  0.43788117516687186, -0.12083239518241493, -0.8908757538001356,
368  0.4981128609611659, 0.8575347951217139, 0.12852102124027118,
369  0.7484274541861499, -0.5000336063006573, 0.43568651389548174
370  ).finished();
371  const Point3 source_r_vec_1(0.3684370505476542, 0.8219440615838134, -0.03501868668711683);
372  const Velocity3 source_v_vec_1(0.7621243390078305, 0.282161192634218, -0.13609316346053646);
373  const double source_t_val_1 = 0.23919296788014144;
374  const Gal3 c1(Rot3(source_R_mat_1), source_r_vec_1, source_v_vec_1, source_t_val_1);
375 
376  Matrix5 expected_Mc;
377  expected_Mc << source_R_mat_1, source_v_vec_1, source_r_vec_1,
378  Vector3::Zero().transpose(), 1.0, source_t_val_1,
379  Vector4::Zero().transpose(), 1.0;
380 
381  Matrix5 Mc = c1.matrix();
382  EXPECT(assert_equal(expected_Mc, Mc, kTol));
383 }
384 
385 /* ************************************************************************* */
386 TEST(Gal3, Associativity) {
387  // Test Case 1
388  const Vector10 tau1_1 = (Vector10() <<
389  0.14491869060866264, -0.21431172810692092, -0.4956042914756127,
390  -0.13411549788475238, 0.44534636811395767, -0.33281648500962074,
391  -0.012095339359589743, -0.20104157502639808, 0.08197507996416392,
392  -0.006285789459736368
393  ).finished();
394  const Vector10 tau2_1 = (Vector10() <<
395  0.29551108535517384, 0.2938672197508704, 0.0788811297200055,
396  -0.07107463852205165, 0.22379088709954872, -0.26508231911443875,
397  -0.11625916165500054, 0.04661407377867886, 0.1788274027858556,
398  -0.015243024791797033
399  ).finished();
400  const Vector10 tau3_1 = (Vector10() <<
401  0.37646834040234084, 0.3782542871960659, -0.6525520272351378,
402  0.005426723127791683, 0.09951505587485733, 0.3813252061414707,
403  -0.09289643299325814, -0.0017149201262141199, -0.08507973168896384,
404  -0.1109049754985476
405  ).finished();
406 
407  Gal3 g1_1 = Gal3::Expmap(tau1_1);
408  Gal3 g2_1 = Gal3::Expmap(tau2_1);
409  Gal3 g3_1 = Gal3::Expmap(tau3_1);
410 
411  Gal3 left_assoc_1 = (g1_1 * g2_1) * g3_1;
412  Gal3 right_assoc_1 = g1_1 * (g2_1 * g3_1);
413 
414  // Use slightly larger tolerance for composed operations
415  EXPECT(assert_equal(left_assoc_1, right_assoc_1, kTol * 10));
416 }
417 
418 /* ************************************************************************* */
419 TEST(Gal3, IdentityProperties) {
420  Gal3 custom_identity = Gal3::Identity();
421 
422  // Test data
423  const Matrix3 g_R_mat_1 = (Matrix3() <<
424  -0.5204974727334908, 0.7067813015326174, 0.4791060140322894,
425  0.773189425449982, 0.15205374379417114, 0.6156766776243058,
426  0.3622989004266723, 0.6908978584436601, -0.6256194178153267
427  ).finished();
428  const Point3 g_r_vec_1(-0.8716573584227159, -0.9599539022706234, -0.08459652545144625);
429  const Velocity3 g_v_vec_1(0.7018395735425127, -0.4666685012479632, 0.07952068144433233);
430  const double g_t_val_1 = -0.24958604725524136;
431  const Gal3 custom_g_1(Rot3(g_R_mat_1), g_r_vec_1, g_v_vec_1, g_t_val_1);
432 
433  // g * g.inverse() == identity
434  Gal3 g_inv_1 = custom_g_1.inverse();
435  Gal3 g_times_inv_1 = custom_g_1 * g_inv_1;
436  EXPECT(assert_equal(custom_identity, g_times_inv_1, kTol * 10)); // Use slightly larger tol for round trip
437 
438  // identity * g == g
439  Gal3 id_times_g_1 = custom_identity * custom_g_1;
440  EXPECT(assert_equal(custom_g_1, id_times_g_1, kTol));
441 
442  // g * identity == g
443  Gal3 g_times_id_1 = custom_g_1 * custom_identity;
444  EXPECT(assert_equal(custom_g_1, g_times_id_1, kTol));
445 }
446 
447 /* ************************************************************************* */
448 TEST(Gal3, Adjoint) {
449  // Test data
450  const Matrix3 g_R_mat_1 = (Matrix3() <<
451  -0.2577418495238488, 0.7767168385303765, 0.5747000015202739,
452  -0.6694062876067332, -0.572463082520484, 0.47347781496466923,
453  0.6967527259484512, -0.26267274676776586, 0.6674868290752107
454  ).finished();
455  const Point3 g_r_vec_1(0.680375434309419, -0.21123414636181392, 0.5661984475172117);
456  const Velocity3 g_v_vec_1(0.536459189623808, -0.44445057839362445, 0.10793991159086103);
457  const double g_t_val_1 = -0.0452058962756795;
458  const Gal3 test_g(Rot3(g_R_mat_1), g_r_vec_1, g_v_vec_1, g_t_val_1);
459 
460  // Expected Adjoint Map
461  Matrix10 expected_adj_matrix = (Matrix10() <<
462  -0.2577418495238488, 0.7767168385303765, 0.5747000015202739, -0.011651451315476903, 0.03511218083817791, 0.025979828658358354, 0.22110620799336958, 0.3876840721487304, -0.42479976201969083, 0.536459189623808,
463  -0.6694062876067332, -0.572463082520484, 0.47347781496466923, -0.03026111120383766, -0.025878706730076754, 0.021403988992128208, -0.6381411631187845, 0.6286520658991062, -0.14213043434767314, -0.44445057839362445,
464  0.6967527259484512, -0.26267274676776586, 0.6674868290752107, 0.03149733145902263, -0.011874356944831452, 0.03017434036055619, -0.5313038186955878, -0.22369794100291154, 0.4665680546909384, 0.10793991159086103,
465  0.0, 0.0, 0.0, -0.2577418495238488, 0.7767168385303765, 0.5747000015202739, -0.23741649654248634, 0.1785366687454684, -0.3477720607401242, 0.0,
466  0.0, 0.0, 0.0, -0.6694062876067332, -0.572463082520484, 0.47347781496466923, -0.40160003518135456, 0.22475195574939733, -0.2960463760548867, 0.0,
467  0.0, 0.0, 0.0, 0.6967527259484512, -0.26267274676776586, 0.6674868290752107, -0.47366266867570694, 0.03810916679440729, 0.5094272729993004, 0.0,
468  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2577418495238488, 0.7767168385303765, 0.5747000015202739, 0.0,
469  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.6694062876067332, -0.572463082520484, 0.47347781496466923, 0.0,
470  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.6967527259484512, -0.26267274676776586, 0.6674868290752107, 0.0,
471  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0
472  ).finished();
473 
474  Matrix10 computed_adj = test_g.AdjointMap();
475  EXPECT(assert_equal(expected_adj_matrix, computed_adj, kTol * 10)); // Slightly larger tolerance
476 
477  // Test tangent vector for adjoint action
478  Vector10 test_tangent = (Vector10() <<
479  -0.28583171387804845, -0.7221038902918132, -0.09516831208249353,
480  -0.13619637934919504, -0.05432836001072756, 0.1629798883384306,
481  -0.20194877118636279, -0.18928645162443278, 0.07312685929426145,
482  -0.042327821984942095
483  ).finished();
484 
485  // Expected result after applying adjoint to tangent vector
486  Vector10 expected_adj_tau = (Vector10() <<
487  -0.7097860882934639, 0.5869666797222274, 0.10746143202899403,
488  0.07529021542994252, 0.21635024626679053, 0.15385717129791027,
489  -0.05294531834013589, 0.27816922833676766, -0.042176749221369034,
490  -0.042327821984942095
491  ).finished();
492 
493  Vector10 computed_adj_tau = test_g.Adjoint(test_tangent);
494  EXPECT(assert_equal(expected_adj_tau, computed_adj_tau, kTol * 10)); // Slightly larger tolerance
495 
496  // Test the adjoint property: Log(g * Exp(tau) * g^-1) = Ad(g) * tau
497  Gal3 exp_tau = Gal3::Expmap(test_tangent);
498  Gal3 g_exp_tau_ginv = test_g * exp_tau * test_g.inverse();
499  Vector10 log_result = Gal3::Logmap(g_exp_tau_ginv);
500 
501  // Expected result for Adjoint(test_tangent) (should match expected_adj_tau)
502  // Recalculated here from Python code to ensure consistency for this specific check
503  Vector10 expected_log_result = (Vector10() <<
504  -0.7097860882934638, 0.5869666797222274, 0.10746143202899389,
505  0.07529021542994252, 0.21635024626679047, 0.15385717129791018,
506  -0.05294531834013579, 0.27816922833676755, -0.04217674922136877,
507  -0.04232782198494209
508  ).finished();
509 
510  // Compare Log(g*Exp(tau)*g^-1) with Ad(g)*tau
511  EXPECT(assert_equal(expected_log_result, log_result, kTol * 10)); // Use larger tolerance for Exp/Log round trip
512  // Also check against previously calculated Adjoint result
513  EXPECT(assert_equal(computed_adj_tau, log_result, kTol * 10));
514 }
515 
516 /* ************************************************************************* */
517 TEST(Gal3, Jacobian_Compose) {
518  // Test data
519  Matrix3 g1_R_mat = (Matrix3() <<
520  -0.3264538540162394, 0.24276278793202133, -0.9135064914894779,
521  0.9430076454867458, 0.1496317101600385, -0.2972321178273404,
522  0.06453264097716288, -0.9584761760784951, -0.27777501352435885
523  ).finished();
524  Point3 g1_r_vec(-0.1995427558196442, 0.7830589040103644, -0.433370507989717);
525  Velocity3 g1_v_vec(0.8986541507293722, 0.051990700444202176, -0.8278883042875157);
526  double g1_t_val = -0.6155723080111539;
527  Gal3 g1(Rot3(g1_R_mat), g1_r_vec, g1_v_vec, g1_t_val);
528 
529  Matrix3 g2_R_mat = (Matrix3() <<
530  -0.5204974727334908, 0.7067813015326174, 0.4791060140322894,
531  0.773189425449982, 0.15205374379417114, 0.6156766776243058,
532  0.3622989004266723, 0.6908978584436601, -0.6256194178153267
533  ).finished();
534  Point3 g2_r_vec(-0.8716573584227159, -0.9599539022706234, -0.08459652545144625);
535  Velocity3 g2_v_vec(0.7018395735425127, -0.4666685012479632, 0.07952068144433233);
536  double g2_t_val = -0.24958604725524136;
537  Gal3 g2(Rot3(g2_R_mat), g2_r_vec, g2_v_vec, g2_t_val);
538 
539  // Expected Jacobians
540  Matrix10 expected_H1 = (Matrix10() <<
541  -0.5204974727334908, 0.773189425449982, 0.3622989004266723, 0.12990890682589473, -0.19297729247761214, -0.09042475048241341, -0.2823811043440715, 0.3598327802048799, -1.1736098322206205, 0.6973186192002845,
542  0.7067813015326174, 0.15205374379417114, 0.6908978584436601, -0.17640275132344085, -0.03795049288394836, -0.17243846554606443, -0.650366876876537, 0.542434959867202, 0.5459387038042347, -0.4800290630417764,
543  0.4791060140322894, 0.6156766776243058, -0.6256194178153267, -0.11957817625853331, -0.15366430835548997, 0.15614587757865273, 0.652649909196605, -0.5858564732208887, -0.07673941868885611, 0.0008110342596663322,
544  0.0, 0.0, 0.0, -0.5204974727334908, 0.773189425449982, 0.3622989004266723, -0.23055803486323456, -0.29566601949219695, 0.29975516112150496, 0.0,
545  0.0, 0.0, 0.0, 0.7067813015326174, 0.15205374379417114, 0.6908978584436601, -0.3345116854380048, -0.42869572760154795, 0.4365499053963549, 0.0,
546  0.0, 0.0, 0.0, 0.4791060140322894, 0.6156766776243058, -0.6256194178153267, 0.24299784710943456, 0.47718330211934956, 0.6556899423712481, 0.0,
547  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5204974727334908, 0.773189425449982, 0.3622989004266723, 0.0,
548  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.7067813015326174, 0.15205374379417114, 0.6908978584436601, 0.0,
549  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.4791060140322894, 0.6156766776243058, -0.6256194178153267, 0.0,
550  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0
551  ).finished();
552  Matrix10 expected_H2 = Matrix10::Identity();
553 
554  Matrix10 H1, H2;
555  g1.compose(g2, H1, H2);
556 
557  EXPECT(assert_equal(expected_H1, H1, kTol));
558  EXPECT(assert_equal(expected_H2, H2, kTol));
559 }
560 
561 /* ************************************************************************* */
562 TEST(Gal3, Jacobian_Inverse) {
563  // Test data
564  Matrix3 g_R_mat = (Matrix3() <<
565  0.6680516673568877, 0.2740542884848495, -0.6918101016209183,
566  0.6729369985913887, -0.6193062871756463, 0.4044941514923666,
567  -0.31758898858193396, -0.7357676057205693, -0.5981498680963873
568  ).finished();
569  Point3 g_r_vec(0.06321286832132045, -0.9214393132931736, -0.12472480681013542);
570  Velocity3 g_v_vec(0.4770686298036335, 0.2799576331302327, -0.29190264050471715);
571  double g_t_val = 0.3757227805330059;
572  Gal3 g(Rot3(g_R_mat), g_r_vec, g_v_vec, g_t_val);
573 
574  // Expected Jacobian
575  Matrix10 expected_H = (Matrix10() <<
576  -0.6680516673568877, -0.2740542884848495, 0.6918101016209183, 0.2510022299990406, 0.10296843928652219, -0.2599288149818328, -0.33617296841685484, -0.7460372203093872, -0.6201638436054394, -0.4770686298036335,
577  -0.6729369985913887, 0.6193062871756463, -0.4044941514923666, 0.252837760234292, -0.23268748021920607, 0.1519776673080509, 0.04690510412308051, 0.0894976987957895, 0.05899296065652178, -0.2799576331302327,
578  0.31758898858193396, 0.7357676057205693, 0.5981498680963873, -0.1193254178566693, -0.27644465064744467, -0.22473853161662533, -0.6077563738775408, -0.3532109665151345, 0.7571646227598928, 0.29190264050471715,
579  -0.0, -0.0, -0.0, -0.6680516673568877, -0.2740542884848495, 0.6918101016209183, -0.10752062523052273, 0.3867608979391727, 0.049383710440088574, -0.0,
580  -0.0, -0.0, -0.0, -0.6729369985913887, 0.6193062871756463, -0.4044941514923666, 0.04349430207154942, -0.271014473064643, -0.48729973338095034, -0.0,
581  -0.0, -0.0, -0.0, 0.31758898858193396, 0.7357676057205693, 0.5981498680963873, -0.1340109682602236, 0.3721751918050696, -0.38664898924142477, -0.0,
582  -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.6680516673568877, -0.2740542884848495, 0.6918101016209183, -0.0,
583  -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.6729369985913887, 0.6193062871756463, -0.4044941514923666, -0.0,
584  -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, 0.31758898858193396, 0.7357676057205693, 0.5981498680963873, -0.0,
585  -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -1.0
586  ).finished();
587 
588  Matrix10 H;
589  g.inverse(H);
590 
591  EXPECT(assert_equal(expected_H, H, kTol));
592 }
593 
594 /* ************************************************************************* */
595 TEST(Gal3, Jacobian_Logmap) {
596  const double jac_tol = 1e-5; // Tolerance for Jacobian checks
597 
598  // Test Case 1
599  const Matrix3 R1_mat = (Matrix3() <<
600  -0.5204974727334908, 0.7067813015326174, 0.4791060140322894,
601  0.773189425449982, 0.15205374379417114, 0.6156766776243058,
602  0.3622989004266723, 0.6908978584436601, -0.6256194178153267
603  ).finished();
604  const Point3 r1_vec(-0.8716573584227159, -0.9599539022706234, -0.08459652545144625);
605  const Velocity3 v1_vec(0.7018395735425127, -0.4666685012479632, 0.07952068144433233);
606  const double t1_val = -0.24958604725524136;
607  const Gal3 g1(Rot3(R1_mat), r1_vec, v1_vec, t1_val);
608 
609  const Vector10 expected_log_tau1 = (Vector10() <<
610  -1.2604528322799349, -0.3898722924179116, -0.6402392791385879,
611  -0.34870126525214656, -0.4153032457886797, 1.1791315551702946,
612  1.4969846781977756, 2.324590726540746, 1.321595100333433,
613  -0.24958604725524136
614  ).finished();
615 
616  Matrix10 Hg1_gtsam;
617  Vector10 log1_gtsam = Gal3::Logmap(g1, Hg1_gtsam);
618  EXPECT(assert_equal(expected_log_tau1, log1_gtsam, kTol));
619 
620  // Verify Jacobian against numerical derivative
621  std::function<Vector10(const Gal3&)> logmap_func1 =
622  [](const Gal3& g_in) { return Gal3::Logmap(g_in); };
623  Matrix H_numerical1 = numericalDerivative11<Vector10, Gal3>(logmap_func1, g1, jac_tol);
624  EXPECT(assert_equal(H_numerical1, Hg1_gtsam, jac_tol));
625 
626  // Test Case 2
627  const Matrix3 R2_mat = (Matrix3() <<
628  0.6680516673568877, 0.2740542884848495, -0.6918101016209183,
629  0.6729369985913887,-0.6193062871756463, 0.4044941514923666,
630  -0.31758898858193396,-0.7357676057205693, -0.5981498680963873
631  ).finished();
632  const Point3 r2_vec(0.06321286832132045, -0.9214393132931736, -0.12472480681013542);
633  const Velocity3 v2_vec(0.4770686298036335, 0.2799576331302327, -0.29190264050471715);
634  const double t2_val = 0.3757227805330059;
635  const Gal3 g2(Rot3(R2_mat), r2_vec, v2_vec, t2_val);
636 
637  const Vector10 expected_log_tau2 = (Vector10() <<
638  -0.5687147057967125, -0.3805406510759017, -1.063343079044753,
639  0.5179342682694047, 0.3616924279678234, -0.0984011207117694,
640  -2.215366977027571, -0.72705858167113, 0.7749725693135466,
641  0.3757227805330059
642  ).finished();
643 
644  Matrix10 Hg2_gtsam;
645  Vector10 log2_gtsam = Gal3::Logmap(g2, Hg2_gtsam);
646  EXPECT(assert_equal(expected_log_tau2, log2_gtsam, kTol));
647 
648  // Verify Jacobian against numerical derivative
649  std::function<Vector10(const Gal3&)> logmap_func2 =
650  [](const Gal3& g_in) { return Gal3::Logmap(g_in); };
651  Matrix H_numerical2 = numericalDerivative11<Vector10, Gal3>(logmap_func2, g2, jac_tol);
652  EXPECT(assert_equal(H_numerical2, Hg2_gtsam, jac_tol));
653 }
654 
655 /* ************************************************************************* */
656 TEST(Gal3, Jacobian_Expmap) {
657  // Test data
658  Vector10 tau_vec = (Vector10() <<
659  0.1644755309744135, -0.212580759622502, 0.027598787765563664,
660  0.06314401798217141, -0.07707725418679535, -0.26078036994807674,
661  0.3779854061644677, -0.09638288751073966, -0.2917351793587256,
662  -0.49338105141355293
663  ).finished();
664 
665  // Expected Jacobian
666  Matrix10 expected_H = (Matrix10() <<
667  0.9844524218735122, -0.1490063714302354, 0.02908427677999133, -0.24094497482047258, 0.04906744369191897, -0.008766606502586993, 0.0010755746403492512, 0.020896120374367614, 0.09422195803906698, -0.032194210151797825,
668  0.13700585416694203, 0.9624511801109918, 0.18991633864490795, -0.04463269623239319, -0.23281449603592955, -0.06241249224896669, -0.05013517822202011, -0.011608679508659724, 0.08214064896800377, 0.05141115662809599,
669  -0.06540787266535304, -0.1806541475679301, 0.9749387339968734, 0.0221898591040537, 0.05898968326106501, -0.23742922610598202, -0.09935687017740953, -0.06570748233856251, -0.025136525844073204, 0.1253312320983055,
670  0.0, 0.0, 0.0, 0.9844524218735122, -0.1490063714302354, 0.02908427677999133, -0.02734050131352483, -0.1309992318097018, 0.01786013841817754, 0.0,
671  0.0, 0.0, 0.0, 0.13700585416694203, 0.9624511801109918, 0.18991633864490795, 0.1195266279722227, -0.032519018758919625, 0.035417068913109986, 0.0,
672  0.0, 0.0, 0.0, -0.06540787266535304, -0.1806541475679301, 0.9749387339968734, -0.0560073503522914, -0.019830198590275447, -0.010039835763395311, 0.0,
673  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.9844524218735122, -0.1490063714302354, 0.02908427677999133, 0.0,
674  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.13700585416694203, 0.9624511801109918, 0.18991633864490795, 0.0,
675  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.06540787266535304, -0.1806541475679301, 0.9749387339968734, 0.0,
676  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0
677  ).finished();
678 
679  Matrix10 H;
680  Gal3::Expmap(tau_vec, H);
681 
682  EXPECT(assert_equal(expected_H, H, kTol));
683 }
684 
685 /* ************************************************************************* */
686 // Test Between Jacobian against numerical derivatives
687 TEST(Gal3, Jacobian_Between) {
688  // Test data
689  Matrix3 g1_R_mat = (Matrix3() <<
690  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
691  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
692  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
693  ).finished();
694  Point3 g1_r_vec(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
695  Velocity3 g1_v_vec(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
696  double g1_t_val = -0.6866418214918308;
697  Gal3 g1(Rot3(g1_R_mat), g1_r_vec, g1_v_vec, g1_t_val);
698 
699  Matrix3 g2_R_mat = (Matrix3() <<
700  -0.5427153955878299, 0.8391431164114453, 0.03603927817303032,
701  0.8040805715986894, 0.5314810596281534, -0.2664250694549225,
702  -0.24272295682417533, -0.11561450357036887, -0.963181630220753
703  ).finished();
704  Point3 g2_r_vec(0.9978490360071179, -0.5634861893781862, 0.025864788808796835);
705  Velocity3 g2_v_vec(0.04857438013356852, -0.012834026018545996, 0.945550047767139);
706  double g2_t_val = -0.41496643117394594;
707  Gal3 g2(Rot3(g2_R_mat), g2_r_vec, g2_v_vec, g2_t_val);
708 
709  Matrix10 H1_analytical, H2_analytical;
710  g1.between(g2, H1_analytical, H2_analytical);
711 
712  std::function<Gal3(const Gal3&, const Gal3&)> between_func =
713  [](const Gal3& g1_in, const Gal3& g2_in) { return g1_in.between(g2_in); };
714 
715  // Verify H1
716  Matrix H1_numerical = numericalDerivative21(between_func, g1, g2, 1e-6);
717  EXPECT(assert_equal(H1_numerical, H1_analytical, 1e-5)); // Tolerance for numerical comparison
718 
719  // Verify H2
720  Matrix H2_numerical = numericalDerivative22(between_func, g1, g2, 1e-6);
721  EXPECT(assert_equal(H2_numerical, H2_analytical, 1e-5)); // Tolerance for numerical comparison
722 }
723 
724 
725 /* ************************************************************************* */
726 TEST(Gal3, Jacobian_AdjointMap) {
727  // Test data
728  Matrix3 g1_R_mat = (Matrix3() <<
729  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
730  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
731  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
732  ).finished();
733  Point3 g1_r_vec(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
734  Velocity3 g1_v_vec(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
735  double g1_t_val = -0.6866418214918308;
736  Gal3 g = Gal3(Rot3(g1_R_mat), g1_r_vec, g1_v_vec, g1_t_val);
737 
738  Vector10 xi = (Vector10() << 0.1, -0.2, 0.3, 0.4, -0.5, 0.6, -0.1, 0.15, -0.25, 0.9).finished();
739 
740  // Analytical Adjoint Map
741  Matrix10 Ad_analytical = g.AdjointMap();
742 
743  // Numerical derivative of Adjoint action Ad_g(xi) w.r.t xi should equal Adjoint Map
744  std::function<Vector10(const Gal3&, const Vector10&)> adjoint_action =
745  [](const Gal3& g_in, const Vector10& xi_in) {
746  return g_in.Adjoint(xi_in);
747  };
748  Matrix H_xi_numerical = numericalDerivative22(adjoint_action, g, xi);
749  EXPECT(assert_equal(Ad_analytical, H_xi_numerical, 1e-7)); // Tolerance for numerical diff
750 
751  // Verify derivative of Adjoint action Ad_g(xi) w.r.t g
752  Matrix10 H_g_analytical;
753  g.Adjoint(xi, H_g_analytical); // Calculate analytical H_g
754 
755  // Need wrapper that only returns value for numericalDerivative21
756  std::function<Vector10(const Gal3&, const Vector10&)> adjoint_action_wrt_g_val =
757  [](const Gal3& g_in, const Vector10& xi_in) {
758  return g_in.Adjoint(xi_in); // Return only value
759  };
760  Matrix H_g_numerical = numericalDerivative21(adjoint_action_wrt_g_val, g, xi);
761  EXPECT(assert_equal(H_g_analytical, H_g_numerical, 1e-7));
762 }
763 
764 /* ************************************************************************* */
765 TEST(Gal3, Jacobian_Inverse2) {
766  // Test data
767  Matrix3 g1_R_mat = (Matrix3() <<
768  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
769  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
770  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
771  ).finished();
772  Point3 g1_r_vec(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
773  Velocity3 g1_v_vec(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
774  double g1_t_val = -0.6866418214918308;
775  Gal3 g = Gal3(Rot3(g1_R_mat), g1_r_vec, g1_v_vec, g1_t_val);
776 
777  // Analytical Jacobian H_inv = d(g.inverse()) / d(g)
778  Matrix10 H_inv_analytical;
779  g.inverse(H_inv_analytical);
780 
781  // Numerical Jacobian
782  std::function<Gal3(const Gal3&)> inverse_func =
783  [](const Gal3& g_in) { return g_in.inverse(); };
784  Matrix H_inv_numerical = numericalDerivative11(inverse_func, g);
785 
786  EXPECT(assert_equal(H_inv_numerical, H_inv_analytical, 1e-5));
787 
788  Matrix10 expected_adjoint = -g.AdjointMap(); // Check against -Ad(g) for right perturbations
789  EXPECT(assert_equal(expected_adjoint, H_inv_analytical, 1e-8));
790 
791 }
792 
793 /* ************************************************************************* */
794 TEST(Gal3, Jacobian_Compose2) {
795  // Test data
796  Matrix3 g1_R_mat = (Matrix3() <<
797  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
798  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
799  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
800  ).finished();
801  Point3 g1_r_vec(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
802  Velocity3 g1_v_vec(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
803  double g1_t_val = -0.6866418214918308;
804  Gal3 g1(Rot3(g1_R_mat), g1_r_vec, g1_v_vec, g1_t_val);
805 
806  Matrix3 g2_R_mat = (Matrix3() <<
807  -0.5427153955878299, 0.8391431164114453, 0.03603927817303032,
808  0.8040805715986894, 0.5314810596281534, -0.2664250694549225,
809  -0.24272295682417533, -0.11561450357036887, -0.963181630220753
810  ).finished();
811  Point3 g2_r_vec(0.9978490360071179, -0.5634861893781862, 0.025864788808796835);
812  Velocity3 g2_v_vec(0.04857438013356852, -0.012834026018545996, 0.945550047767139);
813  double g2_t_val = -0.41496643117394594;
814  Gal3 g2(Rot3(g2_R_mat), g2_r_vec, g2_v_vec, g2_t_val);
815 
816  // Analytical Jacobians
817  Matrix10 H1_analytical, H2_analytical;
818  g1.compose(g2, H1_analytical, H2_analytical);
819 
820  // Numerical Jacobians
821  std::function<Gal3(const Gal3&, const Gal3&)> compose_func =
822  [](const Gal3& g1_in, const Gal3& g2_in) { return g1_in.compose(g2_in); };
823  Matrix H1_numerical = numericalDerivative21(compose_func, g1, g2);
824  Matrix H2_numerical = numericalDerivative22(compose_func, g1, g2);
825 
826  EXPECT(assert_equal(H1_numerical, H1_analytical, 1e-5));
827  EXPECT(assert_equal(H2_numerical, H2_analytical, 1e-5));
828 
829  // Check analytical Jacobians against theoretical formulas
830  EXPECT(assert_equal(g2.inverse().AdjointMap(), H1_analytical, 1e-8));
831  EXPECT(assert_equal(gtsam::Matrix10(Matrix10::Identity()), H2_analytical, 1e-8));
832 }
833 
834 /* ************************************************************************* */
835 TEST(Gal3, Act) {
836  const double kTol = 1e-9; // Tolerance for value checks
837  const double jac_tol = 1e-6; // Tolerance for Jacobian checks
838 
839  // Test Case 1 Data
840  const Matrix3 R1_mat = (Matrix3() <<
841  -0.2577418495238488, 0.7767168385303765, 0.5747000015202739,
842  -0.6694062876067332, -0.572463082520484, 0.47347781496466923,
843  0.6967527259484512, -0.26267274676776586, 0.6674868290752107
844  ).finished();
845  const Point3 r1_vec(0.680375434309419, -0.21123414636181392, 0.5661984475172117);
846  const Velocity3 v1_vec(0.536459189623808, -0.44445057839362445, 0.10793991159086103);
847  const double t1_val = -0.0452058962756795;
848  const Gal3 g1(Rot3(R1_mat), r1_vec, v1_vec, t1_val);
849  const Point3 point_in1(4.967141530112327, -1.3826430117118464, 6.476885381006925);
850  const double time_in1 = 0.0;
851  const Event e_in1(time_in1, point_in1);
852  const Point3 expected_p_out1 = g1.rotation().rotate(point_in1) + g1.velocity() * time_in1 + g1.translation();
853  const double expected_t_out1 = time_in1 + t1_val;
854 
855  Matrix H1g_gtsam = Matrix::Zero(4, 10);
856  Matrix H1e_gtsam = Matrix::Zero(4, 4);
857  Event e_out1_gtsam = g1.act(e_in1, H1g_gtsam, H1e_gtsam);
858 
859  EXPECT(assert_equal(expected_p_out1, e_out1_gtsam.location(), kTol));
860  EXPECT_DOUBLES_EQUAL(expected_t_out1, e_out1_gtsam.time(), kTol);
861 
862  // Verify H1g: Derivative of output Event wrt Gal3 g1
863  std::function<Point3(const Gal3&, const Event&)> act_func1_loc_wrt_g =
864  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).location(); };
865  Matrix H1g_loc_numerical = numericalDerivative21<Point3, Gal3, Event>(act_func1_loc_wrt_g, g1, e_in1, jac_tol);
866  EXPECT(assert_equal(H1g_loc_numerical, H1g_gtsam.block<3, 10>(1, 0), jac_tol));
867 
868  std::function<double(const Gal3&, const Event&)> act_func1_time_wrt_g =
869  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).time(); };
870  Matrix H1g_time_numerical = numericalDerivative21<double, Gal3, Event>(act_func1_time_wrt_g, g1, e_in1, jac_tol);
871  EXPECT(assert_equal(H1g_time_numerical, H1g_gtsam.row(0), jac_tol));
872 
873  // Verify H1e: Derivative of output Event wrt Event e1
874  std::function<Point3(const Gal3&, const Event&)> act_func1_loc_wrt_e =
875  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).location(); };
876  Matrix H1e_loc_numerical = numericalDerivative22<Point3, Gal3, Event>(act_func1_loc_wrt_e, g1, e_in1, jac_tol);
877  EXPECT(assert_equal(H1e_loc_numerical, H1e_gtsam.block<3, 4>(1, 0), jac_tol));
878 
879  std::function<double(const Gal3&, const Event&)> act_func1_time_wrt_e =
880  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).time(); };
881  Matrix H1e_time_numerical = numericalDerivative22<double, Gal3, Event>(act_func1_time_wrt_e, g1, e_in1, jac_tol);
882  EXPECT(assert_equal(H1e_time_numerical, H1e_gtsam.row(0), jac_tol));
883 
884  // Test Case 2 Data
885  const Matrix3 R2_mat = (Matrix3() <<
886  0.1981112115076329, -0.12884463237051902, 0.9716743325745948,
887  0.9776658305457298, -0.04497580389201028, -0.20529661674659028,
888  0.0701532013404006, 0.9906443548385938, 0.11705678352030657
889  ).finished();
890  const Point3 r2_vec(0.9044594503494257, 0.8323901360074013, 0.2714234559198019);
891  const Velocity3 v2_vec(-0.5142264587405261, -0.7255368464279626, 0.6083535084539808);
892  const double t2_val = -0.6866418214918308;
893  const Gal3 g2(Rot3(R2_mat), r2_vec, v2_vec, t2_val);
894  const Point3 point_in2(15.230298564080254, -2.3415337472333597, -2.3413695694918055);
895  const double time_in2 = 0.0;
896  const Event e_in2(time_in2, point_in2);
897  const Point3 expected_p_out2 = g2.rotation().rotate(point_in2) + g2.velocity() * time_in2 + g2.translation();
898  const double expected_t_out2 = time_in2 + t2_val;
899 
900  Matrix H2g_gtsam = Matrix::Zero(4, 10);
901  Matrix H2e_gtsam = Matrix::Zero(4, 4);
902  Event e_out2_gtsam = g2.act(e_in2, H2g_gtsam, H2e_gtsam);
903 
904  EXPECT(assert_equal(expected_p_out2, e_out2_gtsam.location(), kTol));
905  EXPECT_DOUBLES_EQUAL(expected_t_out2, e_out2_gtsam.time(), kTol);
906 
907  // Verify H2g: Derivative of output Event wrt Gal3 g2
908  std::function<Point3(const Gal3&, const Event&)> act_func2_loc_wrt_g =
909  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).location(); };
910  Matrix H2g_loc_numerical = numericalDerivative21<Point3, Gal3, Event>(act_func2_loc_wrt_g, g2, e_in2, jac_tol);
911  EXPECT(assert_equal(H2g_loc_numerical, H2g_gtsam.block<3, 10>(1, 0), jac_tol));
912 
913  std::function<double(const Gal3&, const Event&)> act_func2_time_wrt_g =
914  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).time(); };
915  Matrix H2g_time_numerical = numericalDerivative21<double, Gal3, Event>(act_func2_time_wrt_g, g2, e_in2, jac_tol);
916  EXPECT(assert_equal(H2g_time_numerical, H2g_gtsam.row(0), jac_tol));
917 
918  // Verify H2e: Derivative of output Event wrt Event e2
919  std::function<Point3(const Gal3&, const Event&)> act_func2_loc_wrt_e =
920  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).location(); };
921  Matrix H2e_loc_numerical = numericalDerivative22<Point3, Gal3, Event>(act_func2_loc_wrt_e, g2, e_in2, jac_tol);
922  EXPECT(assert_equal(H2e_loc_numerical, H2e_gtsam.block<3, 4>(1, 0), jac_tol));
923 
924  std::function<double(const Gal3&, const Event&)> act_func2_time_wrt_e =
925  [](const Gal3& g_in, const Event& e_in) { return g_in.act(e_in).time(); };
926  Matrix H2e_time_numerical = numericalDerivative22<double, Gal3, Event>(act_func2_time_wrt_e, g2, e_in2, jac_tol);
927  EXPECT(assert_equal(H2e_time_numerical, H2e_gtsam.row(0), jac_tol));
928 }
929 
930 /* ************************************************************************* */
931 TEST(Gal3, Interpolate) {
932  const double interp_tol = 1e-6; // Tolerance for interpolation value comparison
933 
934  // Test data
935  const Matrix3 R1_mat = (Matrix3() <<
936  -0.5427153955878299, 0.8391431164114453, 0.03603927817303032,
937  0.8040805715986894, 0.5314810596281534, -0.2664250694549225,
938  -0.24272295682417533,-0.11561450357036887,-0.963181630220753
939  ).finished();
940  const Point3 r1_vec(0.9978490360071179, -0.5634861893781862, 0.025864788808796835);
941  const Velocity3 v1_vec(0.04857438013356852, -0.012834026018545996, 0.945550047767139);
942  const double t1_val = -0.41496643117394594;
943  const Gal3 g1(Rot3(R1_mat), r1_vec, v1_vec, t1_val);
944 
945  const Matrix3 R2_mat = (Matrix3() <<
946  -0.3264538540162394, 0.24276278793202133, -0.9135064914894779,
947  0.9430076454867458, 0.1496317101600385, -0.2972321178273404,
948  0.06453264097716288,-0.9584761760784951, -0.27777501352435885
949  ).finished();
950  const Point3 r2_vec(-0.1995427558196442, 0.7830589040103644, -0.433370507989717);
951  const Velocity3 v2_vec(0.8986541507293722, 0.051990700444202176, -0.8278883042875157);
952  const double t2_val = -0.6155723080111539;
953  const Gal3 g2(Rot3(R2_mat), r2_vec, v2_vec, t2_val);
954 
955  // Expected results for different alphas
956  const Gal3 expected_alpha0_00 = g1;
957  const Gal3 expected_alpha0_25(Rot3(-0.5305293740379828, 0.8049951577356123, -0.26555861745588893,
958  0.8357380608208966, 0.444360967494815, -0.32262241748272774,
959  -0.14170559967126867, -0.39309811318459514,-0.9085116380281089),
960  Point3(0.7319725410358775, -0.24509083842031143, -0.20526665070473993),
961  Velocity3(0.447233815335834, 0.08156238532481315, 0.6212732810121263),
962  -0.46511790038324796);
963  const Gal3 expected_alpha0_50(Rot3(-0.4871812472793253, 0.6852678695634308, -0.5413523614461815,
964  0.8717937932763143, 0.34522257149684665,-0.34755856791913387,
965  -0.051283665082120816,-0.6412716453057169, -0.7655982383878919),
966  Point3(0.4275876127256323, 0.0806397132393819, -0.3622648631703127),
967  Velocity3(0.7397753319939113, 0.12027591889377548, 0.19009330402180313),
968  -0.5152693695925499);
969  const Gal3 expected_alpha0_75(Rot3(-0.416880477991759, 0.49158776471130083,-0.7645600935541361,
970  0.9087464582621175, 0.24369303223618222,-0.338812013712018,
971  0.019762127046961175,-0.8360353913714909, -0.5483195078682666),
972  Point3(0.10860773480095642, 0.42140693978775756, -0.4380637787537704),
973  Velocity3(0.895925123398753, 0.10738792759782673, -0.3083508669060544),
974  -0.5654208388018519);
975  const Gal3 expected_alpha1_00 = g2;
976 
977  // Compare values (requires Gal3::interpolate implementation)
978  EXPECT(assert_equal(expected_alpha0_00, gtsam::interpolate(g1, g2, 0.0), interp_tol));
979  EXPECT(assert_equal(expected_alpha0_25, gtsam::interpolate(g1, g2, 0.25), interp_tol));
980  EXPECT(assert_equal(expected_alpha0_50, gtsam::interpolate(g1, g2, 0.5), interp_tol));
981  EXPECT(assert_equal(expected_alpha0_75, gtsam::interpolate(g1, g2, 0.75), interp_tol));
982  EXPECT(assert_equal(expected_alpha1_00, gtsam::interpolate(g1, g2, 1.0), interp_tol));
983 }
984 
985 /* ************************************************************************* */
986 TEST(Gal3, Jacobian_StaticConstructors) {
987  // Verify analytical Jacobians of constructors against numerical derivatives.
988  // Assumes Gal3::Create and Gal3::FromPoseVelocityTime implement these Jacobians.
989  const double jac_tol = 1e-7; // Tolerance for Jacobian checks
990 
991  // Test Gal3::Create
992  gtsam::Matrix H1_ana, H2_ana, H3_ana, H4_ana;
993  Gal3::Create(kTestRot, kTestPos, kTestVel, kTestTime, H1_ana, H2_ana, H3_ana, H4_ana);
994 
995  std::function<Gal3(const Rot3&, const Point3&, const Velocity3&, const double&)> create_func =
996  [](const Rot3& R, const Point3& r, const Velocity3& v, const double& t){
997  return Gal3::Create(R, r, v, t); // Call without Jacobians for numerical diff
998  };
999 
1000  const double& time_ref = kTestTime; // Needed for lambda capture if using C++11/14
1001  Matrix H1_num = numericalDerivative41(create_func, kTestRot, kTestPos, kTestVel, time_ref, jac_tol);
1002  Matrix H2_num = numericalDerivative42(create_func, kTestRot, kTestPos, kTestVel, time_ref, jac_tol);
1003  Matrix H3_num = numericalDerivative43(create_func, kTestRot, kTestPos, kTestVel, time_ref, jac_tol);
1004  Matrix H4_num = numericalDerivative44(create_func, kTestRot, kTestPos, kTestVel, time_ref, jac_tol);
1005 
1006  EXPECT(assert_equal(H1_num, H1_ana, jac_tol));
1007  EXPECT(assert_equal(H2_num, H2_ana, jac_tol));
1008  EXPECT(assert_equal(H3_num, H3_ana, jac_tol));
1009  EXPECT(assert_equal(H4_num, H4_ana, jac_tol));
1010 
1011  // Test Gal3::FromPoseVelocityTime
1012  gtsam::Matrix Hpv1_ana, Hpv2_ana, Hpv3_ana;
1013  Gal3::FromPoseVelocityTime(kTestPose, kTestVel, kTestTime, Hpv1_ana, Hpv2_ana, Hpv3_ana);
1014 
1015  std::function<Gal3(const Pose3&, const Velocity3&, const double&)> fromPoseVelTime_func =
1016  [](const Pose3& pose, const Velocity3& v, const double& t){
1017  return Gal3::FromPoseVelocityTime(pose, v, t); // Call without Jacobians
1018  };
1019 
1020  Matrix Hpv1_num = numericalDerivative31(fromPoseVelTime_func, kTestPose, kTestVel, time_ref, jac_tol);
1021  Matrix Hpv2_num = numericalDerivative32(fromPoseVelTime_func, kTestPose, kTestVel, time_ref, jac_tol);
1022  Matrix Hpv3_num = numericalDerivative33(fromPoseVelTime_func, kTestPose, kTestVel, time_ref, jac_tol);
1023 
1024  EXPECT(assert_equal(Hpv1_num, Hpv1_ana, jac_tol));
1025  EXPECT(assert_equal(Hpv2_num, Hpv2_ana, jac_tol));
1026  EXPECT(assert_equal(Hpv3_num, Hpv3_ana, jac_tol));
1027 }
1028 
1029 /* ************************************************************************* */
1030 TEST(Gal3, Jacobian_Accessors) {
1031  // Verify analytical Jacobians of accessors against numerical derivatives.
1032  // Assumes accessors implement these Jacobians.
1033  const double jac_tol = 1e-7;
1034 
1035  // Test rotation() / attitude() Jacobian
1036  gtsam::Matrix Hrot_ana;
1037  kTestGal3.rotation(Hrot_ana);
1038  std::function<Rot3(const Gal3&)> rot_func =
1039  [](const Gal3& g) { return g.rotation(); };
1040  Matrix Hrot_num = numericalDerivative11<Rot3, Gal3>(rot_func, kTestGal3, jac_tol);
1041  EXPECT(assert_equal(Hrot_num, Hrot_ana, jac_tol));
1042 
1043  // Test translation() / position() Jacobian
1044  gtsam::Matrix Hpos_ana;
1045  kTestGal3.translation(Hpos_ana);
1046  std::function<Point3(const Gal3&)> pos_func =
1047  [](const Gal3& g) { return g.translation(); };
1048  Matrix Hpos_num = numericalDerivative11<Point3, Gal3>(pos_func, kTestGal3, jac_tol);
1049  EXPECT(assert_equal(Hpos_num, Hpos_ana, jac_tol));
1050 
1051  // Test velocity() Jacobian
1052  gtsam::Matrix Hvel_ana;
1053  kTestGal3.velocity(Hvel_ana);
1054  std::function<Velocity3(const Gal3&)> vel_func =
1055  [](const Gal3& g) { return g.velocity(); };
1056  Matrix Hvel_num = numericalDerivative11<Velocity3, Gal3>(vel_func, kTestGal3, jac_tol);
1057  EXPECT(assert_equal(Hvel_num, Hvel_ana, jac_tol));
1058 
1059  // Test time() Jacobian
1060  gtsam::Matrix Htime_ana;
1061  kTestGal3.time(Htime_ana);
1062  std::function<double(const Gal3&)> time_func =
1063  [](const Gal3& g) { return g.time(); };
1064  Matrix Htime_num = numericalDerivative11<double, Gal3>(time_func, kTestGal3, jac_tol);
1065  EXPECT(assert_equal(Htime_num, Htime_ana, jac_tol));
1066 }
1067 
1068 /* ************************************************************************* */
1069 TEST(Gal3, Jacobian_Interpolate) {
1070  // *** CIRCULARITY WARNING ***
1071  // Gal3::interpolate computes its Jacobians using a chain rule involving
1072  // Logmap/Expmap Jacobians. Those are currently numerical, so this test verifies
1073  // the chain rule implementation assuming the underlying derivatives are correct.
1074  const double jac_tol = 1e-7;
1075  const Gal3 g1 = kTestGal3_Lie1;
1076  const Gal3 g2 = kTestGal3_Lie2;
1077  const double alpha = 0.3;
1078 
1079  gtsam::Matrix H1_ana, H2_ana, Ha_ana;
1080  gtsam::interpolate(g1, g2, alpha, H1_ana, H2_ana, Ha_ana);
1081 
1082  std::function<Gal3(const Gal3&, const Gal3&, const double&)> interp_func =
1083  [](const Gal3& g1_in, const Gal3& g2_in, const double& a){
1084  return gtsam::interpolate(g1_in, g2_in, a); // Call without Jacobians
1085  };
1086 
1087  const double& alpha_ref = alpha; // Needed for lambda capture if using C++11/14
1088  Matrix H1_num = numericalDerivative31(interp_func, g1, g2, alpha_ref, jac_tol);
1089  Matrix H2_num = numericalDerivative32(interp_func, g1, g2, alpha_ref, jac_tol);
1090  Matrix Ha_num = numericalDerivative33(interp_func, g1, g2, alpha_ref, jac_tol);
1091 
1092  EXPECT(assert_equal(H1_num, H1_ana, jac_tol));
1093  EXPECT(assert_equal(H2_num, H2_ana, jac_tol));
1094  EXPECT(assert_equal(Ha_num, Ha_ana, jac_tol));
1095 }
1096 
1097 /* ************************************************************************* */
1098 TEST(Gal3, StaticAdjoint) {
1099  // Verify static adjointMap and adjoint Jacobians against numerical derivatives
1100  // and analytical properties. Assumes static adjoint provides analytical Jacobians.
1101  const double jac_tol = 1e-7;
1102  Vector10 xi = (Vector10() << 0.1, -0.2, 0.3, 0.4, -0.5, 0.6, -0.1, 0.15, -0.25, 0.9).finished();
1103  Vector10 y = (Vector10() << -0.5, 0.4, -0.3, 0.2, -0.1, 0.0, 0.3, -0.35, 0.45, -0.1).finished();
1104 
1105  // Test static adjointMap
1106  Matrix10 ad_xi_map = Gal3::adjointMap(xi);
1107  Vector10 ad_xi_map_times_y = ad_xi_map * y;
1108  Vector10 ad_xi_y_direct = Gal3::adjoint(xi, y);
1109  EXPECT(assert_equal(ad_xi_map_times_y, ad_xi_y_direct, kTol)); // Check ad(xi)*y == [xi,y]
1110 
1111  // Verify d(adjoint(xi,y))/dy == adjointMap(xi) numerically
1112  std::function<Vector10(const Vector10&, const Vector10&)> static_adjoint_func =
1113  [](const Vector10& xi_in, const Vector10& y_in){
1114  return Gal3::adjoint(xi_in, y_in); // Call without Jacobians
1115  };
1116  Matrix Hy_num = numericalDerivative22(static_adjoint_func, xi, y, jac_tol);
1117  EXPECT(assert_equal(ad_xi_map, Hy_num, jac_tol));
1118 
1119  // Test static adjoint Jacobians
1120  gtsam::Matrix Hxi_ana, Hy_ana;
1121  Gal3::adjoint(xi, y, Hxi_ana, Hy_ana); // Get analytical Jacobians
1122 
1123  EXPECT(assert_equal(ad_xi_map, Hy_ana, kTol)); // Check analytical Hy vs ad(xi)
1124  EXPECT(assert_equal(-Gal3::adjointMap(y), Hxi_ana, kTol)); // Check analytical Hxi vs -ad(y)
1125 
1126  // Verify analytical Hxi against numerical derivative
1127  Matrix Hxi_num = numericalDerivative21(static_adjoint_func, xi, y, jac_tol);
1128  EXPECT(assert_equal(Hxi_num, Hxi_ana, jac_tol));
1129 
1130  // Verify Jacobi Identity: [x, [y, z]] + [y, [z, x]] + [z, [x, y]] = 0
1131  Vector10 z = (Vector10() << 0.7, 0.8, 0.9, -0.1, -0.2, -0.3, 0.5, 0.6, 0.7, 0.1).finished();
1132  Vector10 term1 = Gal3::adjoint(xi, Gal3::adjoint(y, z));
1133  Vector10 term2 = Gal3::adjoint(y, Gal3::adjoint(z, xi));
1134  Vector10 term3 = Gal3::adjoint(z, Gal3::adjoint(xi, y));
1135  Vector10 sum_terms = term1 + term2 + term3;
1136  EXPECT(assert_equal(Vector10(Vector10::Zero()), sum_terms, jac_tol));
1137 }
1138 
1139 /* ************************************************************************* */
1140 TEST(Gal3, ExpLog_NearZero) {
1141  const double kTolRoundtrip = kTol * 100; // Adjusted tolerance for round-trip
1142 
1143  // Small non-zero tangent vector 1
1144  Vector10 xi_small1;
1145  xi_small1 << 1e-5, -2e-5, 1.5e-5, -3e-5, 4e-5, -2.5e-5, 1e-7, -2e-7, 1.5e-7, -5e-5;
1146  Gal3 g_small1 = Gal3::Expmap(xi_small1);
1147  Vector10 xi_recovered1 = Gal3::Logmap(g_small1);
1148  EXPECT(assert_equal(xi_small1, xi_recovered1, kTolRoundtrip));
1149 
1150  // Small non-zero tangent vector 2
1151  Vector10 xi_small2;
1152  xi_small2 << -5e-6, 1e-6, -4e-6, 2e-6, -6e-6, 1e-6, -5e-8, 8e-8, -2e-8, 9e-6;
1153  Gal3 g_small2 = Gal3::Expmap(xi_small2);
1154  Vector10 xi_recovered2 = Gal3::Logmap(g_small2);
1155  EXPECT(assert_equal(xi_small2, xi_recovered2, kTolRoundtrip));
1156 
1157  // Even smaller theta magnitude
1158  Vector10 xi_small3;
1159  xi_small3 << 1e-9, 2e-9, 3e-9, -4e-9,-5e-9,-6e-9, 1e-10, 2e-10, 3e-10, 7e-9;
1160  Gal3 g_small3 = Gal3::Expmap(xi_small3);
1161  Vector10 xi_recovered3 = Gal3::Logmap(g_small3);
1162  EXPECT(assert_equal(xi_small3, xi_recovered3, kTol)); // Tighter tolerance near zero
1163 
1164  // Zero tangent vector (Strict Identity case)
1165  Vector10 xi_zero = Vector10::Zero();
1166  Gal3 g_identity = Gal3::Expmap(xi_zero);
1167  Vector10 xi_recovered_zero = Gal3::Logmap(g_identity);
1168  EXPECT(assert_equal(Gal3::Identity(), g_identity, kTol));
1169  EXPECT(assert_equal(xi_zero, xi_recovered_zero, kTol));
1170  EXPECT(assert_equal(xi_zero, Gal3::Logmap(Gal3::Expmap(xi_zero)), kTol));
1171 }
1172 
1173 /* ************************************************************************* */
1174 int main() {
1175  TestResult tr;
1176  return TestRegistry::runAllTests(tr);
1177 }
1178 /* ************************************************************************* */
kTestPos
const Point3 kTestPos(1.0, -2.0, 3.0)
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::LieGroup::between
Class between(const Class &g) const
Definition: Lie.h:52
gtsam::numericalDerivative33
internal::FixedSizeMatrix< Y, X3 >::type numericalDerivative33(std::function< Y(const X1 &, const X2 &, const X3 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, double delta=1e-5)
Definition: numericalDerivative.h:292
H
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
Definition: gnuplot_common_settings.hh:74
Gal3.h
3D Galilean Group SGal(3) state (attitude, position, velocity, time)
kTestGal3_Lie2
const Gal3 kTestGal3_Lie2(Rot3::RzRyRx(-0.2, 0.3, 0.1), Point3(-2.0, 3.0, 1.0), Velocity3(0.6, -0.7, 0.5), 2.0)
gtsam::numericalDerivative41
internal::FixedSizeMatrix< Y, X1 >::type numericalDerivative41(std::function< Y(const X1 &, const X2 &, const X3 &, const X4 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, const X4 &x4, double delta=1e-5)
Definition: numericalDerivative.h:325
gtsam::Gal3::time
const double & time(OptionalJacobian< 1, 10 > H={}) const
Access time component (double)
Definition: Gal3.cpp:157
pose
static const Pose3 pose(Rot3(Vector3(1, -1, -1).asDiagonal()), Point3(0, 0, 0.5))
gtsam::Gal3::R
Matrix3 R() const
Return rotation matrix (Matrix3)
Definition: Gal3.h:108
alpha
RealScalar alpha
Definition: level1_cplx_impl.h:147
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
GTSAM_CONCEPT_TESTABLE_INST
#define GTSAM_CONCEPT_TESTABLE_INST(T)
Definition: Testable.h:176
screwPose2::xi
Vector xi
Definition: testPose2.cpp:169
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
TestHarness.h
g1
Pose3 g1(Rot3(), Point3(100.0, 0.0, 300.0))
gtsam::Velocity3
Vector3 Velocity3
Velocity is currently typedef'd to Vector3.
Definition: Gal3.h:33
kIdentity_Lie
const Gal3 kIdentity_Lie
Definition: testGal3.cpp:59
gtsam::LieGroup::compose
Class compose(const Class &g) const
Definition: Lie.h:48
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
gtsam::Gal3::act
Event act(const Event &e, OptionalJacobian< 4, 10 > Hself={}, OptionalJacobian< 4, 4 > He={}) const
Definition: Gal3.cpp:463
gtsam::Matrix5
Eigen::Matrix< double, 5, 5 > Matrix5
Definition: Gal3.h:37
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
gtsam::Matrix
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
gtsam::Gal3::r
Vector3 r() const
Return position as Vector3.
Definition: Gal3.h:111
Point3.h
3D Point
gtsam::Vector3
Eigen::Vector3d Vector3
Definition: Vector.h:44
testLie.h
gtsam::IsGroup
Definition: Group.h:42
kTestPose
const Pose3 kTestPose(kTestRot, kTestPos)
gtsam::Vector10
Eigen::Matrix< double, 10, 1 > Vector10
Definition: Gal3.h:35
TestableAssertions.h
Provides additional testing facilities for common data structures.
Rot3.h
3D rotation represented as a rotation matrix or quaternion
c1
static double c1
Definition: airy.c:54
gtsam::Gal3::translation
const Point3 & translation(OptionalJacobian< 3, 10 > H={}) const
Access translation component (Point3)
Definition: Gal3.cpp:138
gtsam::Matrix10
Eigen::Matrix< double, 10, 10 > Matrix10
Definition: Gal3.h:39
Expmap
Pose2_ Expmap(const Vector3_ &xi)
Definition: InverseKinematicsExampleExpressions.cpp:47
numericalDerivative.h
Some functions to compute numerical derivatives.
gtsam::Gal3::AdjointMap
Matrix10 AdjointMap() const
Calculate Adjoint map Ad_g.
Definition: Gal3.cpp:312
gtsam::Gal3::position
const Point3 & position(OptionalJacobian< 3, 10 > H={}) const
Definition: Gal3.h:101
gtsam::Rot3::rotate
Point3 rotate(const Point3 &p, OptionalJacobian< 3, 3 > H1={}, OptionalJacobian< 3, 3 > H2={}) const
Definition: Rot3M.cpp:148
gtsam::Event::location
Point3 location() const
Definition: Event.h:55
gtsam::Rot3
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition: Rot3.h:58
gtsam::Event::time
double time() const
Definition: Event.h:54
gtsam::numericalDerivative32
internal::FixedSizeMatrix< Y, X2 >::type numericalDerivative32(std::function< Y(const X1 &, const X2 &, const X3 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, double delta=1e-5)
Definition: numericalDerivative.h:259
FAIL
#define FAIL(text)
Definition: Test.h:169
kTestGal3
const Gal3 kTestGal3(kTestRot, kTestPos, kTestVel, kTestTime)
gtsam::Pose3
Definition: Pose3.h:37
GTSAM_CONCEPT_LIE_INST
#define GTSAM_CONCEPT_LIE_INST(T)
Definition: Lie.h:423
g2
Pose3 g2(g1.expmap(h *V1_g1))
gtsam::Pose3::inverse
Pose3 inverse() const
inverse transformation with derivatives
Definition: Pose3.cpp:61
gtsam::Gal3::v
const Vector3 & v() const
Return velocity as Vector3.
Definition: Gal3.h:114
gtsam::IsLieGroup
Definition: Lie.h:287
kTol
static const double kTol
Definition: testGal3.cpp:33
gtsam::numericalDerivative44
internal::FixedSizeMatrix< Y, X4 >::type numericalDerivative44(std::function< Y(const X1 &, const X2 &, const X3 &, const X4 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, const X4 &x4, double delta=1e-5)
Definition: numericalDerivative.h:427
gtsam::numericalDerivative31
internal::FixedSizeMatrix< Y, X1 >::type numericalDerivative31(std::function< Y(const X1 &, const X2 &, const X3 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, double delta=1e-5)
Definition: numericalDerivative.h:226
gtsam::Gal3::matrix
Matrix5 matrix() const
Return 5x5 homogeneous matrix representation.
Definition: Gal3.cpp:168
gtsam::Gal3::velocity
const Velocity3 & velocity(OptionalJacobian< 3, 10 > H={}) const
Access velocity component (Vector3)
Definition: Gal3.cpp:148
gtsam::Pose3::translation
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
Definition: Pose3.cpp:342
main
int main()
Definition: testGal3.cpp:1174
kTestGal3_Lie1
const Gal3 kTestGal3_Lie1(Rot3::RzRyRx(0.1, -0.2, 0.3), Point3(1.0, -2.0, 3.0), Velocity3(0.5, 0.6, -0.7), 1.5)
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
pybind_wrapper_test_script.z
z
Definition: pybind_wrapper_test_script.py:61
gtsam::Gal3
Definition: Gal3.h:45
gtsam::Event
Definition: Event.h:37
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
g
void g(const string &key, int i)
Definition: testBTree.cpp:41
gtsam::numericalDerivative43
internal::FixedSizeMatrix< Y, X3 >::type numericalDerivative43(std::function< Y(const X1 &, const X2 &, const X3 &, const X4 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, const X4 &x4, double delta=1e-5)
Definition: numericalDerivative.h:393
TestResult
Definition: TestResult.h:26
y
Scalar * y
Definition: level1_cplx_impl.h:124
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:376
gtsam::Pose3::rotation
const Rot3 & rotation(OptionalJacobian< 3, 6 > Hself={}) const
get rotation
Definition: Pose3.cpp:348
a
ArrayXXi a
Definition: Array_initializer_list_23_cxx11.cpp:1
gtsam
traits
Definition: ABC.h:17
gtsam::numericalDerivative42
internal::FixedSizeMatrix< Y, X2 >::type numericalDerivative42(std::function< Y(const X1 &, const X2 &, const X3 &, const X4 &)> h, const X1 &x1, const X2 &x2, const X3 &x3, const X4 &x4, double delta=1e-5)
Definition: numericalDerivative.h:359
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
gtsam::Gal3::rotation
const Rot3 & rotation(OptionalJacobian< 3, 10 > H={}) const
Access rotation component (Rot3)
Definition: Gal3.cpp:129
std
Definition: BFloat16.h:88
kTestRot
const Rot3 kTestRot
Definition: testGal3.cpp:40
v
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
gtsam::Rot3::matrix
Matrix3 matrix() const
Definition: Rot3M.cpp:222
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:41
Inverse
Definition: Inverse.java:13
gtsam::Point3
Vector3 Point3
Definition: Point3.h:38
TEST
TEST(Gal3, Concept)
Definition: testGal3.cpp:49
Eigen::Matrix
The matrix class, also used for vectors and row-vectors.
Definition: 3rdparty/Eigen/Eigen/src/Core/Matrix.h:178
gtsam::Gal3::inverse
Gal3 inverse() const
Return the inverse of this element.
Definition: Gal3.cpp:210
gtsam::Gal3::Adjoint
Vector10 Adjoint(const Vector10 &xi_base, OptionalJacobian< 10, 10 > H_g={}, OptionalJacobian< 10, 10 > H_xi={}) const
Apply this element's AdjointMap Ad_g to a tangent vector xi_base at identity.
Definition: Gal3.cpp:336
align_3::t
Point2 t(10, 10)
kTestVel
const Velocity3 kTestVel(0.5, 0.6, -0.7)
GTSAM_CONCEPT_ASSERT
#define GTSAM_CONCEPT_ASSERT(concept)
Definition: base/concepts.h:25
adjoint
void adjoint(const MatrixType &m)
Definition: adjoint.cpp:67
CHECK_CHART_DERIVATIVES
#define CHECK_CHART_DERIVATIVES(t1, t2)
Definition: testLie.h:85
gtsam::Gal3::attitude
const Rot3 & attitude(OptionalJacobian< 3, 10 > H={}) const
Definition: Gal3.h:100
kTestTime
const double kTestTime
Definition: testGal3.cpp:43
R
Rot2 R(Rot2::fromAngle(0.1))
Pose3.h
3D Pose manifold SO(3) x R^3 and group SE(3)
gtsam::Gal3::t
const double & t() const
Return time scalar.
Definition: Gal3.h:117
gtsam::BetweenFactor
Definition: BetweenFactor.h:40


gtsam
Author(s):
autogenerated on Wed May 28 2025 03:06:22