applyLeftJacobianInverse

release/4.3a0
Frank Dellaert 2024-12-16 12:57:27 -05:00
parent 6c84a2b539
commit 98697251bd
3 changed files with 54 additions and 13 deletions

View File

@ -142,14 +142,14 @@ Vector3 DexpFunctor::applyDexp(const Vector3& v, OptionalJacobian<3, 3> H1,
Vector3 DexpFunctor::applyInvDexp(const Vector3& v, OptionalJacobian<3, 3> H1, Vector3 DexpFunctor::applyInvDexp(const Vector3& v, OptionalJacobian<3, 3> H1,
OptionalJacobian<3, 3> H2) const { OptionalJacobian<3, 3> H2) const {
const Matrix3 invDexp = rightJacobian().inverse(); const Matrix3 invJr = rightJacobianInverse();
const Vector3 c = invDexp * v; const Vector3 c = invJr * v;
if (H1) { if (H1) {
Matrix3 D_dexpv_w; Matrix3 H;
applyDexp(c, D_dexpv_w); // get derivative H of forward mapping applyDexp(c, H); // get derivative H of forward mapping
*H1 = -invDexp * D_dexpv_w; *H1 = -invJr * H;
} }
if (H2) *H2 = invDexp; if (H2) *H2 = invJr;
return c; return c;
} }
@ -164,6 +164,20 @@ Vector3 DexpFunctor::applyLeftJacobian(const Vector3& v,
return v + BWv + CWWv; return v + BWv + CWWv;
} }
Vector3 DexpFunctor::applyLeftJacobianInverse(const Vector3& v,
OptionalJacobian<3, 3> H1,
OptionalJacobian<3, 3> H2) const {
const Matrix3 invJl = leftJacobianInverse();
const Vector3 c = invJl * v;
if (H1) {
Matrix3 H;
applyLeftJacobian(c, H); // get derivative H of forward mapping
*H1 = -invJl * H;
}
if (H2) *H2 = invJl;
return c;
}
} // namespace so3 } // namespace so3
//****************************************************************************** //******************************************************************************

View File

@ -162,7 +162,7 @@ struct GTSAM_EXPORT DexpFunctor : public ExpmapFunctor {
double C; // (1 - A) / theta^2 or 1/6 for theta->0 double C; // (1 - A) / theta^2 or 1/6 for theta->0
// Constant used in inverse Jacobians // Constant used in inverse Jacobians
double D; // 1.0 - A / (2.0 * B)) / theta2 or 1/12 for theta->0 double D; // (1 - A/2B) / theta2 or 1/12 for theta->0
// Constants used in cross and doubleCross // Constants used in cross and doubleCross
double E; // (A - 2.0 * B) / theta2 or -1/12 for theta->0 double E; // (A - 2.0 * B) / theta2 or -1/12 for theta->0
@ -212,6 +212,11 @@ struct GTSAM_EXPORT DexpFunctor : public ExpmapFunctor {
Vector3 applyLeftJacobian(const Vector3& v, OptionalJacobian<3, 3> H1 = {}, Vector3 applyLeftJacobian(const Vector3& v, OptionalJacobian<3, 3> H1 = {},
OptionalJacobian<3, 3> H2 = {}) const; OptionalJacobian<3, 3> H2 = {}) const;
/// Multiplies with leftJacobianInverse(), with optional derivatives
Vector3 applyLeftJacobianInverse(const Vector3& v,
OptionalJacobian<3, 3> H1 = {},
OptionalJacobian<3, 3> H2 = {}) const;
static constexpr double one_sixth = 1.0 / 6.0; static constexpr double one_sixth = 1.0 / 6.0;
static constexpr double one_twelfth = 1.0 / 12.0; static constexpr double one_twelfth = 1.0 / 12.0;
static constexpr double one_sixtieth = 1.0 / 60.0; static constexpr double one_sixtieth = 1.0 / 60.0;

View File

@ -385,6 +385,28 @@ TEST(SO3, ApplyDexp) {
} }
} }
//******************************************************************************
TEST(SO3, ApplyInvDexp) {
Matrix aH1, aH2;
for (bool nearZero : {true, false}) {
std::function<Vector3(const Vector3&, const Vector3&)> f =
[=](const Vector3& omega, const Vector3& v) {
return so3::DexpFunctor(omega, nearZero).applyInvDexp(v);
};
for (const Vector3& omega : test_cases::omegas(nearZero)) {
so3::DexpFunctor local(omega, nearZero);
Matrix invJr = local.rightJacobianInverse();
for (const Vector3& v : test_cases::vs) {
EXPECT(
assert_equal(Vector3(invJr * v), local.applyInvDexp(v, aH1, aH2)));
EXPECT(assert_equal(numericalDerivative21(f, omega, v), aH1));
EXPECT(assert_equal(numericalDerivative22(f, omega, v), aH2));
EXPECT(assert_equal(invJr, aH2));
}
}
}
}
//****************************************************************************** //******************************************************************************
TEST(SO3, ApplyLeftJacobian) { TEST(SO3, ApplyLeftJacobian) {
Matrix aH1, aH2; Matrix aH1, aH2;
@ -407,22 +429,22 @@ TEST(SO3, ApplyLeftJacobian) {
} }
//****************************************************************************** //******************************************************************************
TEST(SO3, ApplyInvDexp) { TEST(SO3, ApplyLeftJacobianInverse) {
Matrix aH1, aH2; Matrix aH1, aH2;
for (bool nearZero : {true, false}) { for (bool nearZero : {true, false}) {
std::function<Vector3(const Vector3&, const Vector3&)> f = std::function<Vector3(const Vector3&, const Vector3&)> f =
[=](const Vector3& omega, const Vector3& v) { [=](const Vector3& omega, const Vector3& v) {
return so3::DexpFunctor(omega, nearZero).applyInvDexp(v); return so3::DexpFunctor(omega, nearZero).applyLeftJacobianInverse(v);
}; };
for (const Vector3& omega : test_cases::omegas(nearZero)) { for (const Vector3& omega : test_cases::omegas(nearZero)) {
so3::DexpFunctor local(omega, nearZero); so3::DexpFunctor local(omega, nearZero);
Matrix invDexp = local.dexp().inverse(); Matrix invJl = local.leftJacobianInverse();
for (const Vector3& v : test_cases::vs) { for (const Vector3& v : test_cases::vs) {
EXPECT(assert_equal(Vector3(invDexp * v), EXPECT(assert_equal(Vector3(invJl * v),
local.applyInvDexp(v, aH1, aH2))); local.applyLeftJacobianInverse(v, aH1, aH2)));
EXPECT(assert_equal(numericalDerivative21(f, omega, v), aH1)); EXPECT(assert_equal(numericalDerivative21(f, omega, v), aH1));
EXPECT(assert_equal(numericalDerivative22(f, omega, v), aH2)); EXPECT(assert_equal(numericalDerivative22(f, omega, v), aH2));
EXPECT(assert_equal(invDexp, aH2)); EXPECT(assert_equal(invJl, aH2));
} }
} }
} }