add adjointMap and expmap/logmap derivatives for Pose2
parent
8722c9cf68
commit
4be24f4f70
|
@ -125,6 +125,61 @@ Vector Pose2::Adjoint(const Vector& xi) const {
|
||||||
return AdjointMap()*xi;
|
return AdjointMap()*xi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Matrix3 Pose2::adjointMap(const Vector& v) {
|
||||||
|
// See Chirikjian12book2, vol.2, pg. 36
|
||||||
|
Matrix3 ad = zeros(3,3);
|
||||||
|
ad(0,1) = -v[2];
|
||||||
|
ad(1,0) = v[2];
|
||||||
|
ad(0,2) = v[1];
|
||||||
|
ad(1,2) = -v[0];
|
||||||
|
return ad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Matrix3 Pose2::dexpL(const Vector3& v) {
|
||||||
|
// See Iserles05an, pg. 33.
|
||||||
|
// TODO: Duplicated code. Maybe unify them at higher Lie level?
|
||||||
|
static const int N = 10; // order of approximation
|
||||||
|
Matrix res = I3;
|
||||||
|
Matrix3 ad_i = I3;
|
||||||
|
Matrix3 ad = adjointMap(v);
|
||||||
|
double fac = 1.0;
|
||||||
|
for (int i = 1; i < N; ++i) {
|
||||||
|
ad_i = ad * ad_i;
|
||||||
|
fac = fac * (i+1);
|
||||||
|
// Since this is the left-trivialized version, we flip the signs of the odd terms
|
||||||
|
if (i%2 != 0)
|
||||||
|
res = res - 1.0 / fac * ad_i;
|
||||||
|
else
|
||||||
|
res = res + 1.0 / fac * ad_i;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Matrix3 Pose2::dexpInvL(const Vector3& v) {
|
||||||
|
// TODO: Duplicated code with Pose3. Maybe unify them at higher Lie level?
|
||||||
|
// Bernoulli numbers, from Wikipedia
|
||||||
|
static const Vector B = (Vector(9) << 1.0, -1.0 / 2.0, 1. / 6., 0.0, -1.0 / 30.0,
|
||||||
|
0.0, 1.0 / 42.0, 0.0, -1.0 / 30);
|
||||||
|
static const int N = 5; // order of approximation
|
||||||
|
Matrix res = I3;
|
||||||
|
Matrix3 ad_i = I3;
|
||||||
|
Matrix3 ad = adjointMap(v);
|
||||||
|
double fac = 1.0;
|
||||||
|
for (int i = 1; i < N; ++i) {
|
||||||
|
ad_i = ad * ad_i;
|
||||||
|
fac = fac * i;
|
||||||
|
// Since this is the left-trivialized version, we flip the signs of the odd terms
|
||||||
|
// Note that all Bernoulli odd numbers are 0, except 1.
|
||||||
|
if (i==1)
|
||||||
|
res = res - B(i) / fac * ad_i;
|
||||||
|
else
|
||||||
|
res = res + B(i) / fac * ad_i;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Pose2 Pose2::inverse(boost::optional<Matrix&> H1) const {
|
Pose2 Pose2::inverse(boost::optional<Matrix&> H1) const {
|
||||||
|
|
|
@ -161,6 +161,11 @@ public:
|
||||||
Matrix AdjointMap() const;
|
Matrix AdjointMap() const;
|
||||||
Vector Adjoint(const Vector& xi) const;
|
Vector Adjoint(const Vector& xi) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the [ad(w,v)] operator for SE2 as in [Kobilarov09siggraph], pg 19
|
||||||
|
*/
|
||||||
|
static Matrix3 adjointMap(const Vector& v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wedge for SE(2):
|
* wedge for SE(2):
|
||||||
* @param xi 3-dim twist (v,omega) where
|
* @param xi 3-dim twist (v,omega) where
|
||||||
|
@ -175,6 +180,13 @@ public:
|
||||||
0., 0., 0.);
|
0., 0., 0.);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Left-trivialized derivative of the exponential map
|
||||||
|
static Matrix3 dexpL(const Vector3& v);
|
||||||
|
|
||||||
|
/// Left-trivialized derivative inverse of the exponential map
|
||||||
|
static Matrix3 dexpInvL(const Vector3& v);
|
||||||
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Group Action on Point2
|
/// @name Group Action on Point2
|
||||||
/// @{
|
/// @{
|
||||||
|
|
|
@ -32,7 +32,7 @@ using namespace boost::assign;
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// #define SLOW_BUT_CORRECT_EXPMAP
|
#define SLOW_BUT_CORRECT_EXPMAP
|
||||||
|
|
||||||
GTSAM_CONCEPT_TESTABLE_INST(Pose2)
|
GTSAM_CONCEPT_TESTABLE_INST(Pose2)
|
||||||
GTSAM_CONCEPT_LIE_INST(Pose2)
|
GTSAM_CONCEPT_LIE_INST(Pose2)
|
||||||
|
@ -192,6 +192,28 @@ TEST(Pose2, logmap_full) {
|
||||||
EXPECT(assert_equal(expected, actual, 1e-5));
|
EXPECT(assert_equal(expected, actual, 1e-5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector w = (Vector(3) << 0.1, 0.27, -0.2);
|
||||||
|
|
||||||
|
// Left trivialization Derivative of exp(w) over w: How exp(w) changes when w changes?
|
||||||
|
// We find y such that: exp(w) exp(y) = exp(w + dw) for dw --> 0
|
||||||
|
// => y = log (exp(-w) * exp(w+dw))
|
||||||
|
Vector testDexpL(const LieVector& dw) {
|
||||||
|
Vector y = Pose2::Logmap(Pose2::Expmap(-w) * Pose2::Expmap(w + dw));
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST( Pose2, dexpL) {
|
||||||
|
Matrix actualDexpL = Pose2::dexpL(w);
|
||||||
|
Matrix expectedDexpL = numericalDerivative11(
|
||||||
|
boost::function<Vector(const LieVector&)>(
|
||||||
|
boost::bind(testDexpL, _1)), LieVector(zero(3)), 1e-2);
|
||||||
|
EXPECT(assert_equal(expectedDexpL, actualDexpL, 1e-5));
|
||||||
|
|
||||||
|
Matrix actualDexpInvL = Pose2::dexpInvL(w);
|
||||||
|
EXPECT(assert_equal(expectedDexpL.inverse(), actualDexpInvL, 1e-5));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
static Point2 transform_to_proxy(const Pose2& pose, const Point2& point) {
|
static Point2 transform_to_proxy(const Pose2& pose, const Point2& point) {
|
||||||
return pose.transform_to(point);
|
return pose.transform_to(point);
|
||||||
|
|
Loading…
Reference in New Issue