@@ -41,9 +41,6 @@ namespace gtsam {
4141namespace { // Anonymous namespace for internal linkage
4242 constexpr double kSmallAngleThreshold = 1e-10 ;
4343
44- // The type of the Lie algebra (matrix representation)
45- using LieAlgebra = Matrix5;
46-
4744 // Helper functions for accessing tangent vector components
4845 Eigen::Block<Vector10, 3 , 1 > rho (Vector10& v) { return v.block <3 , 1 >(0 , 0 ); }
4946 Eigen::Block<Vector10, 3 , 1 > nu (Vector10& v) { return v.block <3 , 1 >(3 , 0 ); }
@@ -55,6 +52,45 @@ namespace { // Anonymous namespace for internal linkage
5552 Eigen::Block<const Vector10, 3 , 1 > theta (const Vector10& v) { return v.block <3 , 1 >(6 , 0 ); }
5653 Eigen::Block<const Vector10, 1 , 1 > t_tan (const Vector10& v) { return v.block <1 , 1 >(9 , 0 ); }
5754
55+ // The 25x10 matrix of vectorized generators for SGal(3).
56+ // The columns correspond to perturbations in [rho, nu, theta, t_tan].
57+ // The tangent vector is [rho(3), nu(3), theta(3), t_tan(1)].
58+ // P_gal3 = [vec(G_rho), vec(G_nu), vec(G_theta), vec(G_t)]
59+ static const Eigen::Matrix<double , 25 , 10 > P_gal3 =
60+ (Eigen::Matrix<double , 25 , 10 >() <<
61+ // rho(0-2), nu(3-5), theta(6-8), t_tan(9)
62+ // --- M(i,0) --- rows 0-4
63+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
64+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 ,
65+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 ,
66+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
67+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
68+ // --- M(i,1) --- rows 5-9
69+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 ,
70+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
71+ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 ,
72+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
73+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
74+ // --- M(i,2) --- rows 10-14
75+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 ,
76+ 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 , 0 ,
77+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
78+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
79+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
80+ // --- M(i,3) --- rows 15-19
81+ 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 ,
82+ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 ,
83+ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
84+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
85+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
86+ // --- M(i,4) --- rows 20-24
87+ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
88+ 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
89+ 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
90+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
91+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
92+ ).finished();
93+
5894} // end anonymous namespace
5995
6096// ------------------------------------------------------------------------------
@@ -162,8 +198,6 @@ const double& Gal3::time(OptionalJacobian<1, 10> H) const {
162198 return t_;
163199}
164200
165- // ------------------------------------------------------------------------------
166- // Matrix Representation
167201// ------------------------------------------------------------------------------
168202Matrix5 Gal3::matrix () const {
169203 // Returns 5x5 matrix representation as in Equation 9, Page 5
@@ -177,6 +211,20 @@ Matrix5 Gal3::matrix() const {
177211 return M;
178212}
179213
214+ // ------------------------------------------------------------------------------
215+ Vector25 Gal3::vec (OptionalJacobian<25 , 10 > H) const {
216+ const Matrix5 T = this ->matrix ();
217+ if (H) {
218+ // The Jacobian is given by the formula H = (I_5 ⊗ T) * P_gal3
219+ // where P_gal3 is the matrix of vectorized generators.
220+ // This can be implemented efficiently with block-wise multiplication.
221+ *H << T * P_gal3.block <5 , 10 >(0 , 0 ), T* P_gal3.block <5 , 10 >(5 , 0 ),
222+ T* P_gal3.block <5 , 10 >(10 , 0 ), T* P_gal3.block <5 , 10 >(15 , 0 ),
223+ T* P_gal3.block <5 , 10 >(20 , 0 );
224+ }
225+ return Eigen::Map<const Vector25>(T.data ());
226+ }
227+
180228// ------------------------------------------------------------------------------
181229// Stream operator
182230// ------------------------------------------------------------------------------
0 commit comments