H1 works for rot/translation, but not scale :-(

release/4.3a0
dellaert 2015-03-02 21:58:54 -08:00
parent 728991e31f
commit d8822e5b57
2 changed files with 74 additions and 24 deletions

View File

@ -65,9 +65,17 @@ bool Similarity3::equals(const Similarity3& sim, double tol) const {
Point3 Similarity3::transform_from(const Point3& p, // Point3 Similarity3::transform_from(const Point3& p, //
OptionalJacobian<3, 7> H1, OptionalJacobian<3, 3> H2) const { OptionalJacobian<3, 7> H1, OptionalJacobian<3, 3> H2) const {
if (H1) {
const Matrix3 R = R_.matrix();
Matrix3 DR = s_ * R * skewSymmetric(-p.x(), -p.y(), -p.z());
*H1 << DR, R, R * p.vector();
}
if (H2) if (H2)
*H2 = s_ * R_.matrix(); // just 3*3 sub-block of matrix() *H2 = s_ * R_.matrix(); // just 3*3 sub-block of matrix()
return R_ * (s_ * p) + t_; return R_ * (s_ * p) + t_;
// TODO: Effect of scale change is this, right?
// sR t * (1+v)I 0 * p = s(1+v)R t * p = s(1+v)Rp + t = sRp + vRp + t
// 0001 000 1 1 000 1 1
} }
const Matrix4 Similarity3::matrix() const { const Matrix4 Similarity3::matrix() const {
@ -82,9 +90,9 @@ Matrix7 Similarity3::AdjointMap() const {
const Vector3 t = t_.vector(); const Vector3 t = t_.vector();
Matrix3 A = s_ * skewSymmetric(t) * R; Matrix3 A = s_ * skewSymmetric(t) * R;
Matrix7 adj; Matrix7 adj;
adj << s_ * R, A, -s_ * t, Z_3x3, R, // adj << s_ * R, A, -s_ * t, // 3*7
Matrix31::Zero(), // Z_3x3, R, Matrix31::Zero(), // 3*7
Matrix16::Zero(), 1; Matrix16::Zero(), 1; // 1*7
return adj; return adj;
} }

View File

@ -19,6 +19,7 @@
#include <gtsam/slam/PriorFactor.h> #include <gtsam/slam/PriorFactor.h>
#include <gtsam/slam/BetweenFactor.h> #include <gtsam/slam/BetweenFactor.h>
#include <gtsam/nonlinear/NonlinearFactorGraph.h> #include <gtsam/nonlinear/NonlinearFactorGraph.h>
#include <gtsam/nonlinear/ExpressionFactorGraph.h>
#include <gtsam/nonlinear/Values.h> #include <gtsam/nonlinear/Values.h>
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <gtsam/geometry/Pose3.h> #include <gtsam/geometry/Pose3.h>
@ -68,6 +69,7 @@ TEST(Similarity3, Getters2) {
EXPECT_DOUBLES_EQUAL(7.0, test.scale(), 1e-9); EXPECT_DOUBLES_EQUAL(7.0, test.scale(), 1e-9);
} }
//******************************************************************************
TEST(Similarity3, AdjointMap) { TEST(Similarity3, AdjointMap) {
Similarity3 test(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7); Similarity3 test(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7);
Matrix7 result; Matrix7 result;
@ -75,6 +77,7 @@ TEST(Similarity3, AdjointMap) {
EXPECT(assert_equal(result, test.AdjointMap(), 1e-3)); EXPECT(assert_equal(result, test.AdjointMap(), 1e-3));
} }
//******************************************************************************
TEST(Similarity3, inverse) { TEST(Similarity3, inverse) {
Similarity3 test(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7); Similarity3 test(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7);
Matrix3 Re; Matrix3 Re;
@ -84,7 +87,8 @@ TEST(Similarity3, inverse) {
EXPECT(assert_equal(expected, test.inverse(), 1e-3)); EXPECT(assert_equal(expected, test.inverse(), 1e-3));
} }
TEST(Similarity3, multiplication) { //******************************************************************************
TEST(Similarity3, Multiplication) {
Similarity3 test1(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7); Similarity3 test1(Rot3::ypr(1, 2, 3).inverse(), Point3(4, 5, 6), 7);
Similarity3 test2(Rot3::ypr(1, 2, 3).inverse(), Point3(8, 9, 10), 11); Similarity3 test2(Rot3::ypr(1, 2, 3).inverse(), Point3(8, 9, 10), 11);
Matrix3 re; Matrix3 re;
@ -130,7 +134,7 @@ TEST(Similarity3, Manifold) {
// TODO add unit tests for retract and localCoordinates // TODO add unit tests for retract and localCoordinates
} }
/* ************************************************************************* */ //******************************************************************************
TEST( Similarity3, retract_first_order) { TEST( Similarity3, retract_first_order) {
Similarity3 id; Similarity3 id;
Vector v = zero(7); Vector v = zero(7);
@ -142,7 +146,7 @@ TEST( Similarity3, retract_first_order) {
EXPECT(assert_equal(Similarity3(R, P, 1), id.retract(v), 1e-2)); EXPECT(assert_equal(Similarity3(R, P, 1), id.retract(v), 1e-2));
} }
/* ************************************************************************* */ //******************************************************************************
TEST(Similarity3, localCoordinates_first_order) { TEST(Similarity3, localCoordinates_first_order) {
Vector d12 = repeat(7, 0.1); Vector d12 = repeat(7, 0.1);
d12(6) = 1.0; d12(6) = 1.0;
@ -150,7 +154,7 @@ TEST(Similarity3, localCoordinates_first_order) {
EXPECT(assert_equal(d12, t1.localCoordinates(t2))); EXPECT(assert_equal(d12, t1.localCoordinates(t2)));
} }
/* ************************************************************************* */ //******************************************************************************
TEST(Similarity3, manifold_first_order) { TEST(Similarity3, manifold_first_order) {
Similarity3 t1 = T; Similarity3 t1 = T;
Similarity3 t2 = T3; Similarity3 t2 = T3;
@ -165,11 +169,7 @@ TEST(Similarity3, manifold_first_order) {
// Return as a 4*4 Matrix // Return as a 4*4 Matrix
TEST(Similarity3, Matrix) { TEST(Similarity3, Matrix) {
Matrix4 expected; Matrix4 expected;
expected << expected << 2, 0, 0, 1, 0, 2, 0, 1, 0, 0, 2, 0, 0, 0, 0, 1;
2, 0, 0, 1,
0, 2, 0, 1,
0, 0, 2, 0,
0, 0, 0, 1;
Matrix4 actual = T4.matrix(); Matrix4 actual = T4.matrix();
EXPECT(assert_equal(expected, actual)); EXPECT(assert_equal(expected, actual));
} }
@ -177,23 +177,38 @@ TEST(Similarity3, Matrix) {
// Group action on Point3 (with simpler transform) // Group action on Point3 (with simpler transform)
TEST(Similarity3, GroupAction) { TEST(Similarity3, GroupAction) {
EXPECT(assert_equal(Point3(1, 1, 0), T4 * Point3(0, 0, 0))); EXPECT(assert_equal(Point3(1, 1, 0), T4 * Point3(0, 0, 0)));
EXPECT(assert_equal(Point3(3, 1, 0), T4 * Point3(1, 0, 0)));
// Test actual group action on R^4 // Test actual group action on R^4
Vector4 qh; qh << 1,0,0,1; Vector4 qh;
Vector4 ph; ph << 3,1,0,1; qh << 1, 0, 0, 1;
EXPECT(assert_equal((Vector)ph, T4.matrix()*qh)); Vector4 ph;
ph << 3, 1, 0, 1;
EXPECT(assert_equal((Vector )ph, T4.matrix() * qh));
// Test derivative // Test derivative
boost::function<Point3(Similarity3,Point3)> f = boost::bind( boost::function<Point3(Similarity3, Point3)> f = boost::bind(
&Similarity3::transform_from, _1, _2, boost::none, boost::none); &Similarity3::transform_from, _1, _2, boost::none, boost::none);
Point3 q(1, 0, 0);
Matrix expectedH1 = numericalDerivative21<Point3,Similarity3,Point3>(f,T4,q); { // T
Matrix expectedH2 = numericalDerivative22<Point3,Similarity3,Point3>(f,T4,q); Point3 q(1, 0, 0);
Matrix actualH1,actualH2; Matrix H1 = numericalDerivative21<Point3, Similarity3, Point3>(f, T, q);
Point3 p = T4.transform_from(q,actualH1,actualH2); Matrix H2 = numericalDerivative22<Point3, Similarity3, Point3>(f, T, q);
EXPECT(assert_equal(expectedH1, actualH1)); Matrix actualH1, actualH2;
EXPECT(assert_equal(expectedH2, actualH2)); T.transform_from(q, actualH1, actualH2);
EXPECT(assert_equal(H1, actualH1));
EXPECT(assert_equal(H2, actualH2));
}
{ // T4
Point3 q(1, 0, 0);
Matrix H1 = numericalDerivative21<Point3, Similarity3, Point3>(f, T4, q);
Matrix H2 = numericalDerivative22<Point3, Similarity3, Point3>(f, T4, q);
Matrix actualH1, actualH2;
Point3 p = T4.transform_from(q, actualH1, actualH2);
EXPECT(assert_equal(Point3(3, 1, 0), p));
EXPECT(assert_equal(Point3(3, 1, 0), T4 * q));
EXPECT(assert_equal(H1, actualH1));
EXPECT(assert_equal(H2, actualH2));
}
} }
//****************************************************************************** //******************************************************************************
@ -294,6 +309,33 @@ TEST(Similarity3, Optimization2) {
EXPECT(assert_equal(expected, result.at<Similarity3>(X(5)), 0.4)); EXPECT(assert_equal(expected, result.at<Similarity3>(X(5)), 0.4));
} }
//******************************************************************************
// Align points (p,q) assuming that p = T*q + noise
TEST(Similarity3, AlignScaledPointClouds) {
// Create ground truth
Point3 q1(0, 0, 0), q2(1, 0, 0), q3(0, 1, 0);
// Create transformed cloud (noiseless)
// Point3 p1 = T4 * q1, p2 = T4 * q2, p3 = T4 * q3;
// Create an unknown expression
Expression<Similarity3> unknownT(0); // use key 0
// Create constant expressions for the ground truth points
Expression<Point3> q1_(q1), q2_(q2), q3_(q3);
// Create prediction expressions
Expression<Point3> predict1(unknownT, &Similarity3::transform_from, q1_);
Expression<Point3> predict2(unknownT, &Similarity3::transform_from, q2_);
Expression<Point3> predict3(unknownT, &Similarity3::transform_from, q3_);
//// Create Expression factor graph
// ExpressionFactorGraph graph;
// graph.addExpressionFactor(predict1, p1, R); // |T*q1 - p1|
// graph.addExpressionFactor(predict2, p2, R); // |T*q2 - p2|
// graph.addExpressionFactor(predict3, p3, R); // |T*q3 - p3|
}
//****************************************************************************** //******************************************************************************
int main() { int main() {
TestResult tr; TestResult tr;