Implemented and tested Rot3.retract based on the Cayley Transform (about three times faster)
parent
dfa395529d
commit
dae02c387f
|
|
@ -227,10 +227,10 @@ namespace gtsam {
|
||||||
size_t dim() const { return dimension; }
|
size_t dim() const { return dimension; }
|
||||||
|
|
||||||
/// Retraction from R^3 to Pose2 manifold neighborhood around current pose
|
/// Retraction from R^3 to Pose2 manifold neighborhood around current pose
|
||||||
Rot3 retract(const Vector& v) const { return compose(Expmap(v)); }
|
Rot3 retract(const Vector& omega) const;
|
||||||
|
|
||||||
/// Returns inverse retraction
|
/// Returns inverse retraction
|
||||||
Vector localCoordinates(const Rot3& t2) const { return Logmap(between(t2)); }
|
Vector localCoordinates(const Rot3& t2) const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Lie Group
|
/// @name Lie Group
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,38 @@ Vector Rot3::Logmap(const Rot3& R) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Rot3 Rot3::retract(const Vector& omega) const {
|
||||||
|
#ifdef CORRECT_ROT3_EXMAP
|
||||||
|
return (*this)*Expmap(omega);
|
||||||
|
#else
|
||||||
|
#ifdef SLOW_CAYLEY
|
||||||
|
Matrix Omega = skewSymmetric(omega);
|
||||||
|
return (*this)*Cayley(-Omega/2);
|
||||||
|
#else
|
||||||
|
double x = omega(0), y = omega(1), z = omega(2);
|
||||||
|
double x2 = x*x, y2 = y*y, z2 = z*z;
|
||||||
|
double xy = x*y, xz = x*z, yz = y*z;
|
||||||
|
double f = 1.0 / (4.0 + x2 + y2 + z2), _2f = 2.0*f;
|
||||||
|
return (*this)* Rot3(
|
||||||
|
(4+x2-y2-z2)*f, (xy - 2*z)*_2f, (xz + 2*y)*_2f,
|
||||||
|
(xy + 2*z)*_2f, (4-x2+y2-z2)*f, (yz - 2*x)*_2f,
|
||||||
|
(xz - 2*y)*_2f, (yz + 2*x)*_2f, (4-x2-y2+z2)*f
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector Rot3::localCoordinates(const Rot3& T) const {
|
||||||
|
#ifdef CORRECT_ROT3_EXMAP
|
||||||
|
return Logmap(between(T));
|
||||||
|
#else
|
||||||
|
Matrix Omega = Cayley(between(T).matrix());
|
||||||
|
return -2*Vector_(3,Omega(2,1),Omega(0,2),Omega(1,0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix Rot3::matrix() const {
|
Matrix Rot3::matrix() const {
|
||||||
Matrix R(3,3);
|
Matrix R(3,3);
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,16 @@ namespace gtsam {
|
||||||
return angleAxis.axis() * angleAxis.angle();
|
return angleAxis.axis() * angleAxis.angle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Rot3 Rot3::retract(const Vector& omega) const {
|
||||||
|
return compose(Expmap(omega));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Vector Rot3::localCoordinates(const Rot3& t2) const {
|
||||||
|
return Logmap(between(t2));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix Rot3::matrix() const { return quaternion_.toRotationMatrix(); }
|
Matrix Rot3::matrix() const { return quaternion_.toRotationMatrix(); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,13 @@ TEST( Pose3, retract)
|
||||||
Pose3 id;
|
Pose3 id;
|
||||||
Vector v = zero(6);
|
Vector v = zero(6);
|
||||||
v(0) = 0.3;
|
v(0) = 0.3;
|
||||||
EXPECT(assert_equal(Pose3(R, Point3()), id.retract(v)));
|
EXPECT(assert_equal(Pose3(R, Point3()), id.retract(v),1e-2));
|
||||||
#ifdef CORRECT_POSE3_EXMAP
|
#ifdef CORRECT_POSE3_EXMAP
|
||||||
v(3)=0.2;v(4)=0.394742;v(5)=-2.08998;
|
v(3)=0.2;v(4)=0.394742;v(5)=-2.08998;
|
||||||
#else
|
#else
|
||||||
v(3)=0.2;v(4)=0.7;v(5)=-2;
|
v(3)=0.2;v(4)=0.7;v(5)=-2;
|
||||||
#endif
|
#endif
|
||||||
EXPECT(assert_equal(Pose3(R, P),id.retract(v),1e-5));
|
EXPECT(assert_equal(Pose3(R, P),id.retract(v),1e-2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
@ -86,7 +86,7 @@ TEST(Pose3, expmap_b)
|
||||||
Pose3 p1(Rot3(), Point3(100, 0, 0));
|
Pose3 p1(Rot3(), Point3(100, 0, 0));
|
||||||
Pose3 p2 = p1.retract(Vector_(6,0.0, 0.0, 0.1, 0.0, 0.0, 0.0));
|
Pose3 p2 = p1.retract(Vector_(6,0.0, 0.0, 0.1, 0.0, 0.0, 0.0));
|
||||||
Pose3 expected(Rot3::rodriguez(0.0, 0.0, 0.1), Point3(100.0, 0.0, 0.0));
|
Pose3 expected(Rot3::rodriguez(0.0, 0.0, 0.1), Point3(100.0, 0.0, 0.0));
|
||||||
EXPECT(assert_equal(expected, p2));
|
EXPECT(assert_equal(expected, p2,1e-2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,12 @@ using namespace gtsam;
|
||||||
Rot3 R = Rot3::rodriguez(0.1, 0.4, 0.2);
|
Rot3 R = Rot3::rodriguez(0.1, 0.4, 0.2);
|
||||||
Point3 P(0.2, 0.7, -2.0);
|
Point3 P(0.2, 0.7, -2.0);
|
||||||
double error = 1e-9, epsilon = 0.001;
|
double error = 1e-9, epsilon = 0.001;
|
||||||
|
static const Matrix I3 = eye(3);
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST( Rot3, constructor)
|
TEST( Rot3, constructor)
|
||||||
{
|
{
|
||||||
Rot3 expected(eye(3, 3));
|
Rot3 expected(I3);
|
||||||
Vector r1(3), r2(3), r3(3);
|
Vector r1(3), r2(3), r3(3);
|
||||||
r1(0) = 1;
|
r1(0) = 1;
|
||||||
r1(1) = 0;
|
r1(1) = 0;
|
||||||
|
|
@ -88,7 +89,7 @@ Rot3 slow_but_correct_rodriguez(const Vector& w) {
|
||||||
double t = norm_2(w);
|
double t = norm_2(w);
|
||||||
Matrix J = skewSymmetric(w / t);
|
Matrix J = skewSymmetric(w / t);
|
||||||
if (t < 1e-5) return Rot3();
|
if (t < 1e-5) return Rot3();
|
||||||
Matrix R = eye(3) + sin(t) * J + (1.0 - cos(t)) * (J * J);
|
Matrix R = I3 + sin(t) * J + (1.0 - cos(t)) * (J * J);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,10 +190,14 @@ TEST(Rot3, manifold)
|
||||||
// log behaves correctly
|
// log behaves correctly
|
||||||
Vector d12 = gR1.localCoordinates(gR2);
|
Vector d12 = gR1.localCoordinates(gR2);
|
||||||
CHECK(assert_equal(gR2, gR1.retract(d12)));
|
CHECK(assert_equal(gR2, gR1.retract(d12)));
|
||||||
CHECK(assert_equal(gR2, gR1*Rot3::Expmap(d12)));
|
|
||||||
Vector d21 = gR2.localCoordinates(gR1);
|
Vector d21 = gR2.localCoordinates(gR1);
|
||||||
CHECK(assert_equal(gR1, gR2.retract(d21)));
|
CHECK(assert_equal(gR1, gR2.retract(d21)));
|
||||||
|
|
||||||
|
#ifdef CORRECT_ROT3_EXMAP
|
||||||
|
// Check that it is expmap
|
||||||
|
CHECK(assert_equal(gR2, gR1*Rot3::Expmap(d12)));
|
||||||
CHECK(assert_equal(gR1, gR2*Rot3::Expmap(d21)));
|
CHECK(assert_equal(gR1, gR2*Rot3::Expmap(d21)));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check that log(t1,t2)=-log(t2,t1)
|
// Check that log(t1,t2)=-log(t2,t1)
|
||||||
CHECK(assert_equal(d12,-d21));
|
CHECK(assert_equal(d12,-d21));
|
||||||
|
|
@ -381,7 +386,7 @@ TEST( Rot3, RQ)
|
||||||
Vector actual;
|
Vector actual;
|
||||||
boost::tie(actualK, actual) = RQ(R.matrix());
|
boost::tie(actualK, actual) = RQ(R.matrix());
|
||||||
Vector expected = Vector_(3, 0.14715, 0.385821, 0.231671);
|
Vector expected = Vector_(3, 0.14715, 0.385821, 0.231671);
|
||||||
CHECK(assert_equal(eye(3),actualK));
|
CHECK(assert_equal(I3,actualK));
|
||||||
CHECK(assert_equal(expected,actual,1e-6));
|
CHECK(assert_equal(expected,actual,1e-6));
|
||||||
|
|
||||||
// Try using xyz call, asserting that Rot3::RzRyRx(x,y,z).xyz()==[x;y;z]
|
// Try using xyz call, asserting that Rot3::RzRyRx(x,y,z).xyz()==[x;y;z]
|
||||||
|
|
@ -415,7 +420,7 @@ TEST( Rot3, expmapStability ) {
|
||||||
w(2), 0.0, -w(0),
|
w(2), 0.0, -w(0),
|
||||||
-w(1), w(0), 0.0 );
|
-w(1), w(0), 0.0 );
|
||||||
Matrix W2 = W*W;
|
Matrix W2 = W*W;
|
||||||
Matrix Rmat = eye(3) + (1.0-theta2/6.0 + theta2*theta2/120.0
|
Matrix Rmat = I3 + (1.0-theta2/6.0 + theta2*theta2/120.0
|
||||||
- theta2*theta2*theta2/5040.0)*W + (0.5 - theta2/24.0 + theta2*theta2/720.0)*W2 ;
|
- theta2*theta2*theta2/5040.0)*W + (0.5 - theta2/24.0 + theta2*theta2/720.0)*W2 ;
|
||||||
Rot3 expectedR( Rmat );
|
Rot3 expectedR( Rmat );
|
||||||
CHECK(assert_equal(expectedR, actualR, 1e-10));
|
CHECK(assert_equal(expectedR, actualR, 1e-10));
|
||||||
|
|
@ -475,6 +480,14 @@ TEST(Rot3, quaternion) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( Rot3, Cayley ) {
|
||||||
|
Matrix A = skewSymmetric(1,2,-3);
|
||||||
|
Matrix Q = Cayley(A);
|
||||||
|
EXPECT(assert_equal(I3, trans(Q)*Q));
|
||||||
|
EXPECT(assert_equal(A, Cayley(Q)));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ int main()
|
||||||
{
|
{
|
||||||
int n = 300000;
|
int n = 300000;
|
||||||
Vector v = Vector_(3,1.,0.,0.);
|
Vector v = Vector_(3,1.,0.,0.);
|
||||||
|
Rot3 R = Rot3::rodriguez(0.1, 0.4, 0.2);
|
||||||
|
|
||||||
// Rodriguez formula given axis angle
|
cout << "Rodriguez formula given axis angle" << endl;
|
||||||
long timeLog = clock();
|
long timeLog = clock();
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
Rot3::rodriguez(v,0.001);
|
Rot3::rodriguez(v,0.001);
|
||||||
|
|
@ -37,7 +38,7 @@ int main()
|
||||||
cout << seconds << " seconds" << endl;
|
cout << seconds << " seconds" << endl;
|
||||||
cout << ((double)n/seconds) << " calls/second" << endl;
|
cout << ((double)n/seconds) << " calls/second" << endl;
|
||||||
|
|
||||||
// Rodriguez formula given canonical coordinates
|
cout << "Rodriguez formula given canonical coordinates" << endl;
|
||||||
timeLog = clock();
|
timeLog = clock();
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
Rot3::rodriguez(v);
|
Rot3::rodriguez(v);
|
||||||
|
|
@ -46,7 +47,25 @@ int main()
|
||||||
cout << seconds << " seconds" << endl;
|
cout << seconds << " seconds" << endl;
|
||||||
cout << ((double)n/seconds) << " calls/second" << endl;
|
cout << ((double)n/seconds) << " calls/second" << endl;
|
||||||
|
|
||||||
// Slow rotation matrix
|
cout << "Exmpap" << endl;
|
||||||
|
timeLog = clock();
|
||||||
|
for(int i = 0; i < n; i++)
|
||||||
|
R*Rot3::Expmap(v);
|
||||||
|
timeLog2 = clock();
|
||||||
|
seconds = (double)(timeLog2-timeLog)/CLOCKS_PER_SEC;
|
||||||
|
cout << seconds << " seconds" << endl;
|
||||||
|
cout << ((double)n/seconds) << " calls/second" << endl;
|
||||||
|
|
||||||
|
cout << "Retract" << endl;
|
||||||
|
timeLog = clock();
|
||||||
|
for(int i = 0; i < n; i++)
|
||||||
|
R.retract(v);
|
||||||
|
timeLog2 = clock();
|
||||||
|
seconds = (double)(timeLog2-timeLog)/CLOCKS_PER_SEC;
|
||||||
|
cout << seconds << " seconds" << endl;
|
||||||
|
cout << ((double)n/seconds) << " calls/second" << endl;
|
||||||
|
|
||||||
|
cout << "Slow rotation matrix" << endl;
|
||||||
timeLog = clock();
|
timeLog = clock();
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
Rot3::Rz(0.3)*Rot3::Ry(0.2)*Rot3::Rx(0.1);
|
Rot3::Rz(0.3)*Rot3::Ry(0.2)*Rot3::Rx(0.1);
|
||||||
|
|
@ -55,7 +74,7 @@ int main()
|
||||||
cout << seconds << " seconds" << endl;
|
cout << seconds << " seconds" << endl;
|
||||||
cout << ((double)n/seconds) << " calls/second" << endl;
|
cout << ((double)n/seconds) << " calls/second" << endl;
|
||||||
|
|
||||||
// Fast Rotation matrix
|
cout << "Fast Rotation matrix" << endl;
|
||||||
timeLog = clock();
|
timeLog = clock();
|
||||||
for(int i = 0; i < n; i++)
|
for(int i = 0; i < n; i++)
|
||||||
Rot3::RzRyRx(0.1,0.2,0.3);
|
Rot3::RzRyRx(0.1,0.2,0.3);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue