Skip to content

Commit bb2c490

Browse files
committed
add analytical gal3 expmapderivative
1 parent 5b34831 commit bb2c490

File tree

1 file changed

+98
-8
lines changed

1 file changed

+98
-8
lines changed

gtsam/geometry/Gal3.cpp

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,15 +437,105 @@ Vector10 Gal3::adjoint(const Vector10& xi, const Vector10& y, OptionalJacobian<1
437437
}
438438

439439
//------------------------------------------------------------------------------
440+
static Matrix3 computeQMatrix(const so3::DexpFunctor& dexp, const Vector3& vec) {
441+
Matrix3 vec_hat = skewSymmetric(vec);
442+
Vector4 coeffs;
443+
if (dexp.nearZero) {
444+
coeffs << 0.5, 1.0 / 6.0, 0.0, 0.0;
445+
} else {
446+
coeffs << 0.5,
447+
dexp.C,
448+
(1.0 - 2.0 * dexp.B) / (2.0 * dexp.theta2),
449+
(2.0 * dexp.theta - 3.0 * std::sin(dexp.theta) + dexp.theta * std::cos(dexp.theta)) / (2.0 * dexp.theta2 * dexp.theta2 * dexp.theta);
450+
}
451+
452+
Matrix3 T1 = vec_hat;
453+
Matrix3 T2 = dexp.W * vec_hat + vec_hat * dexp.W + dexp.W * vec_hat * dexp.W;
454+
Matrix3 T3 = dexp.WW * vec_hat + vec_hat * dexp.WW - 3.0 * (dexp.W * vec_hat * dexp.W);
455+
Matrix3 T4 = dexp.WW * vec_hat * dexp.W + dexp.W * vec_hat * dexp.WW;
456+
457+
return coeffs(0) * T1 + coeffs(1) * T2 + coeffs(2) * T3 + coeffs(3) * T4;
458+
}
459+
460+
static Matrix3 computeGal3LeftJacobianU1(const gtsam::so3::DexpFunctor& dexp) {
461+
// move into dexpfunctor?
462+
if (dexp.nearZero) {
463+
return 0.5 * Matrix3::Identity() + (1.0 / 3.0) * dexp.W;
464+
} else {
465+
return 0.5 * Matrix3::Identity() + (dexp.B - dexp.C) * dexp.W +
466+
((0.5 - dexp.A + dexp.B) / dexp.theta2) * dexp.WW;
467+
}
468+
}
469+
470+
static Matrix3 computeGamma1ThetaNuThetaTau(const so3::DexpFunctor& dexp, const Vector3& nu_vec) {
471+
Matrix3 nu_hat = skewSymmetric(nu_vec);
472+
Vector7 coeffs;
473+
if (dexp.nearZero) {
474+
coeffs << 1.0 / 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
475+
} else {
476+
const double tn3 = dexp.theta * dexp.theta2;
477+
const double tn4 = dexp.theta2 * dexp.theta2;
478+
const double tn5 = dexp.theta * tn4;
479+
const double tn6 = dexp.theta2 * tn4;
480+
const double s = std::sin(dexp.theta);
481+
const double c = std::cos(dexp.theta);
482+
483+
coeffs << 1.0 / 6.0,
484+
dexp.E,
485+
(1.0 - 2.0 * dexp.B) / (2.0 * dexp.theta2),
486+
(tn3 + 6.0 * dexp.theta + 6.0 * dexp.theta * c - 12.0 * s) / (6.0 * tn5),
487+
(12.0 * s - 12.0 * dexp.theta * c - 3.0 * dexp.theta2 * s - tn3) / (6.0 * tn5),
488+
(tn3 - 6.0 * dexp.theta + 6.0 * s) / (6.0 * tn5),
489+
(4.0 + dexp.theta2 + dexp.theta2 * c - 4.0 * dexp.theta * s - 4.0 * c) / (4.0 * tn6);
490+
}
491+
492+
Matrix3 T0 = nu_hat;
493+
Matrix3 T1 = dexp.W * nu_hat;
494+
Matrix3 T2 = nu_hat * dexp.W;
495+
Matrix3 T3 = dexp.WW * nu_hat;
496+
Matrix3 T4 = dexp.W * nu_hat * dexp.W;
497+
Matrix3 T5 = nu_hat * dexp.WW;
498+
Matrix3 T6 = dexp.WW * nu_hat * dexp.W + dexp.W * nu_hat * dexp.WW;
499+
500+
Matrix3 result = coeffs(0) * T0 + coeffs(1) * T1 + coeffs(2) * T2 + coeffs(3) * T3;
501+
result += coeffs(4) * T4 + coeffs(5) * T5 + coeffs(6) * T6;
502+
503+
return result;
504+
}
505+
440506
Matrix10 Gal3::ExpmapDerivative(const Vector10& xi) {
441-
// Related to the left Jacobian in Equations 31-36, Pages 10-11
442-
// NOTE: Using numerical approximation instead of implementing the analytical
443-
// expression for the Jacobian. Future work to replace this
444-
// with analytical derivative.
445-
if (xi.norm() < kSmallAngleThreshold) return Matrix10::Identity();
446-
std::function<Gal3(const Vector10&)> fn =
447-
[](const Vector10& v) { return Gal3::Expmap(v); };
448-
return numericalDerivative11<Gal3, Vector10>(fn, xi, 1e-5);
507+
Vector minus_xi = -xi;
508+
Vector3 rho_vec = minus_xi.segment<3>(0);
509+
Vector3 nu_vec = minus_xi.segment<3>(3);
510+
Vector3 theta_vec = minus_xi.segment<3>(6);
511+
double t_val = minus_xi(9);
512+
513+
so3::DexpFunctor dexp(theta_vec);
514+
515+
Matrix10 Jl_minus_xi = Matrix10::Zero();
516+
517+
// Note: Because dexp is constructed on -theta, dexp.leftJacobian() returns Jr(theta)
518+
Matrix3 right_jacobian = dexp.leftJacobian();
519+
Jl_minus_xi.block<3,3>(0,0) = right_jacobian; // ∂ρ/∂ρ block
520+
Jl_minus_xi.block<3,3>(3,3) = right_jacobian; // ∂ν/∂ν block
521+
Jl_minus_xi.block<3,3>(6,6) = right_jacobian; // ∂ϕ/∂ϕ block
522+
523+
Jl_minus_xi.block<3,3>(0,3) = -computeGal3LeftJacobianU1(dexp) * t_val;
524+
Jl_minus_xi.block<3,3>(3,6) = computeQMatrix(dexp, nu_vec);
525+
Jl_minus_xi.block<3,3>(0,6) = computeQMatrix(dexp, rho_vec) - computeGamma1ThetaNuThetaTau(dexp, nu_vec)*t_val;
526+
527+
Matrix3 gamma2;
528+
if (dexp.nearZero) {
529+
gamma2 = 0.5 * Matrix3::Identity() + 1.0 / 6.0 * dexp.W + (1.0/24.0) * dexp.WW;
530+
} else {
531+
gamma2 = 0.5 * Matrix3::Identity() + dexp.C * dexp.W + (1.0 - 2.0 * dexp.B) / (2.0 * dexp.theta2) * dexp.WW;
532+
}
533+
534+
Jl_minus_xi.block<3,1>(0,9) = gamma2 * nu_vec;
535+
536+
Jl_minus_xi(9,9) = 1.0;
537+
538+
return Jl_minus_xi;
449539
}
450540

451541
//------------------------------------------------------------------------------

0 commit comments

Comments
 (0)