Moved rotate(Rot3,Sphere2) to Rot3, makes more sense

git-svn-id: https://svn.cc.gatech.edu/borg/gtsam/trunk@20415 898a188c-9671-0410-8e00-e3fd810bbb7f
release/4.3a0
Frank Dellaert 2013-12-21 01:42:58 +00:00 committed by Richard Roberts
parent 848f992b98
commit d109c981ed
7 changed files with 58 additions and 41 deletions

View File

@ -42,6 +42,7 @@
#include <gtsam/base/DerivedValue.h> #include <gtsam/base/DerivedValue.h>
#include <gtsam/base/Matrix.h> #include <gtsam/base/Matrix.h>
#include <gtsam/geometry/Point3.h> #include <gtsam/geometry/Point3.h>
#include <gtsam/geometry/Sphere2.h>
namespace gtsam { namespace gtsam {
@ -293,6 +294,17 @@ namespace gtsam {
Point3 unrotate(const Point3& p, boost::optional<Matrix&> H1 = boost::none, Point3 unrotate(const Point3& p, boost::optional<Matrix&> H1 = boost::none,
boost::optional<Matrix&> H2 = boost::none) const; boost::optional<Matrix&> H2 = boost::none) const;
/// @}
/// @name Group Action on Sphere2
/// @{
/// rotate 3D direction from rotated coordinate frame to world frame
Sphere2 rotate(const Sphere2& p, boost::optional<Matrix&> HR = boost::none,
boost::optional<Matrix&> Hp = boost::none) const;
/// rotate 3D direction from rotated coordinate frame to world frame
Sphere2 operator*(const Sphere2& p) const;
/// @} /// @}
/// @name Standard Interface /// @name Standard Interface
/// @{ /// @{
@ -303,11 +315,12 @@ namespace gtsam {
/** return 3*3 transpose (inverse) rotation matrix */ /** return 3*3 transpose (inverse) rotation matrix */
Matrix3 transpose() const; Matrix3 transpose() const;
/** returns column vector specified by index */ /// @deprecated, this is base 1, and was just confusing
Point3 column(int index) const; Point3 column(int index) const;
Point3 r1() const;
Point3 r2() const; Point3 r1() const; ///< first column
Point3 r3() const; Point3 r2() const; ///< second column
Point3 r3() const; ///< third column
/** /**
* Use RQ to calculate xyz angle representation * Use RQ to calculate xyz angle representation

View File

@ -201,6 +201,22 @@ Point3 Rot3::rotate(const Point3& p,
return Point3(rot_ * p.vector()); return Point3(rot_ * p.vector());
} }
/* ************************************************************************* */
Sphere2 Rot3::rotate(const Sphere2& p,
boost::optional<Matrix&> HR, boost::optional<Matrix&> Hp) const {
Sphere2 q(rotate(p.point3(Hp)));
if (Hp)
(*Hp) = q.basis().transpose() * matrix() * (*Hp);
if (HR)
(*HR) = -q.basis().transpose() * matrix() * p.skew();
return q;
}
/* ************************************************************************* */
Sphere2 Rot3::operator*(const Sphere2& p) const {
return rotate(p);
}
/* ************************************************************************* */ /* ************************************************************************* */
// see doc/math.lyx, SO(3) section // see doc/math.lyx, SO(3) section
Point3 Rot3::unrotate(const Point3& p, Point3 Rot3::unrotate(const Point3& p,
@ -346,7 +362,14 @@ Matrix3 Rot3::transpose() const {
/* ************************************************************************* */ /* ************************************************************************* */
Point3 Rot3::column(int index) const{ Point3 Rot3::column(int index) const{
return Point3(rot_.col(index)); if(index == 3)
return r3();
else if(index == 2)
return r2();
else if(index == 1)
return r1(); // default returns r1
else
throw invalid_argument("Argument to Rot3::column must be 1, 2, or 3");
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -67,22 +67,6 @@ Matrix Sphere2::skew() const {
return skewSymmetric(p_.x(), p_.y(), p_.z()); return skewSymmetric(p_.x(), p_.y(), p_.z());
} }
/* ************************************************************************* */
Sphere2 Sphere2::Rotate(const Rot3& R, const Sphere2& p,
boost::optional<Matrix&> HR, boost::optional<Matrix&> Hp) {
Sphere2 q(R * p.p_);
if (Hp)
(*Hp) = q.basis().transpose() * R.matrix() * p.basis();
if (HR)
(*HR) = -q.basis().transpose() * R.matrix() * p.skew();
return q;
}
/* ************************************************************************* */
Sphere2 operator*(const Rot3& R, const Sphere2& p) {
return Sphere2::Rotate(R, p);
}
/* ************************************************************************* */ /* ************************************************************************* */
Vector Sphere2::error(const Sphere2& q, boost::optional<Matrix&> H) const { Vector Sphere2::error(const Sphere2& q, boost::optional<Matrix&> H) const {
Matrix Bt = basis().transpose(); Matrix Bt = basis().transpose();

View File

@ -19,7 +19,7 @@
#pragma once #pragma once
#include <gtsam/geometry/Rot3.h> #include <gtsam/geometry/Point3.h>
#include <gtsam/base/DerivedValue.h> #include <gtsam/base/DerivedValue.h>
namespace gtsam { namespace gtsam {
@ -83,14 +83,6 @@ public:
return p_; return p_;
} }
/// Rotate
static Sphere2 Rotate(const Rot3& R, const Sphere2& p,
boost::optional<Matrix&> HR = boost::none, boost::optional<Matrix&> Hp =
boost::none);
/// Rotate sugar
friend Sphere2 operator*(const Rot3& R, const Sphere2& p);
/// Signed, vector-valued error between two directions /// Signed, vector-valued error between two directions
Vector error(const Sphere2& q, Vector error(const Sphere2& q,
boost::optional<Matrix&> H = boost::none) const; boost::optional<Matrix&> H = boost::none) const;

View File

@ -17,6 +17,7 @@
*/ */
#include <gtsam/geometry/Sphere2.h> #include <gtsam/geometry/Sphere2.h>
#include <gtsam/geometry/Rot3.h>
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <gtsam/base/numericalDerivative.h> #include <gtsam/base/numericalDerivative.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -37,7 +38,8 @@ Point3 point3_(const Sphere2& p) {
} }
TEST(Sphere2, point3) { TEST(Sphere2, point3) {
vector<Point3> ps; vector<Point3> ps;
ps += Point3(1, 0, 0), Point3(0, 1, 0), Point3(0, 0, 1), Point3(1, 1, 0)/sqrt(2); ps += Point3(1, 0, 0), Point3(0, 1, 0), Point3(0, 0, 1), Point3(1, 1, 0)
/ sqrt(2);
Matrix actualH, expectedH; Matrix actualH, expectedH;
BOOST_FOREACH(Point3 p,ps) { BOOST_FOREACH(Point3 p,ps) {
Sphere2 s(p); Sphere2 s(p);
@ -48,6 +50,10 @@ TEST(Sphere2, point3) {
} }
//******************************************************************************* //*******************************************************************************
static Sphere2 rotate_(const Rot3& R, const Sphere2& p) {
return R * p;
}
TEST(Sphere2, rotate) { TEST(Sphere2, rotate) {
Rot3 R = Rot3::yaw(0.5); Rot3 R = Rot3::yaw(0.5);
Sphere2 p(1, 0, 0); Sphere2 p(1, 0, 0);
@ -57,15 +63,13 @@ TEST(Sphere2, rotate) {
Matrix actualH, expectedH; Matrix actualH, expectedH;
// Use numerical derivatives to calculate the expected Jacobian // Use numerical derivatives to calculate the expected Jacobian
{ {
expectedH = numericalDerivative11<Sphere2, Rot3>( expectedH = numericalDerivative21(rotate_,R,p);
boost::bind(&Sphere2::Rotate, _1, p, boost::none, boost::none), R); R.rotate(p, actualH, boost::none);
Sphere2::Rotate(R, p, actualH, boost::none);
EXPECT(assert_equal(expectedH, actualH, 1e-9)); EXPECT(assert_equal(expectedH, actualH, 1e-9));
} }
{ {
expectedH = numericalDerivative11<Sphere2, Sphere2>( expectedH = numericalDerivative22(rotate_,R,p);
boost::bind(&Sphere2::Rotate, R, _1, boost::none, boost::none), p); R.rotate(p, boost::none, actualH);
Sphere2::Rotate(R, p, boost::none, actualH);
EXPECT(assert_equal(expectedH, actualH, 1e-9)); EXPECT(assert_equal(expectedH, actualH, 1e-9));
} }
} }

View File

@ -8,7 +8,7 @@
#pragma once #pragma once
#include <gtsam/nonlinear/NonlinearFactor.h> #include <gtsam/nonlinear/NonlinearFactor.h>
#include <gtsam/geometry/Sphere2.h> #include <gtsam/geometry/Rot3.h>
namespace gtsam { namespace gtsam {
@ -44,7 +44,7 @@ public:
Vector e = p_.error(q, H); Vector e = p_.error(q, H);
if (H) { if (H) {
Matrix DR; Matrix DR;
Sphere2::Rotate(R, z_, DR); R.rotate(z_, DR);
*H = (*H) * DR; *H = (*H) * DR;
} }
return e; return e;
@ -57,7 +57,7 @@ public:
double e = p_.distance(q, H); double e = p_.distance(q, H);
if (H) { if (H) {
Matrix DR; Matrix DR;
Sphere2::Rotate(R, z_, DR); R.rotate(z_, DR);
*H = (*H) * DR; *H = (*H) * DR;
} }
return (Vector(1) << e); return (Vector(1) << e);

View File

@ -28,6 +28,7 @@ Point3 cameraX(0, 1, 0), cameraY(0, 0, 1), cameraZ(1, 0, 0);
Rot3 iRc(cameraX, cameraY, cameraZ); Rot3 iRc(cameraX, cameraY, cameraZ);
// Now, let's create some rotations around IMU frame // Now, let's create some rotations around IMU frame
Sphere2 p1(1, 0, 0), p2(0, 1, 0), p3(0, 0, 1); Sphere2 p1(1, 0, 0), p2(0, 1, 0), p3(0, 0, 1);
Rot3 gRi1 = Rot3::Expmap(Vector3(1, 0, 0));
// The corresponding rotations in the camera frame // The corresponding rotations in the camera frame
Sphere2 z1 = iRc.inverse() * p1, z2 = iRc.inverse() * p2, // Sphere2 z1 = iRc.inverse() * p1, z2 = iRc.inverse() * p2, //
z3 = iRc.inverse() * p3; z3 = iRc.inverse() * p3;