diff --git a/gtsam/base/Matrix.cpp b/gtsam/base/Matrix.cpp index 2b72a55e4..ad0c7c9f4 100644 --- a/gtsam/base/Matrix.cpp +++ b/gtsam/base/Matrix.cpp @@ -72,6 +72,11 @@ Matrix zeros( size_t m, size_t n ) { return Matrix::Zero(m,n); } +/* ************************************************************************* */ +Matrix ones( size_t m, size_t n ) { + return Matrix::Ones(m,n); +} + /* ************************************************************************* */ Matrix eye( size_t m, size_t n) { return Matrix::Identity(m, n); @@ -280,6 +285,23 @@ void insertSub(Matrix& fullMatrix, const Matrix& subMatrix, size_t i, size_t j) fullMatrix.block(i, j, subMatrix.rows(), subMatrix.cols()) = subMatrix; } +/* ************************************************************************* */ +Matrix diag(const std::vector& Hs) { + size_t rows = 0, cols = 0; + for (size_t i = 0; i sub(const MATRIX& A, size_t i1, size_t i2, size_t j1, */ GTSAM_EXPORT void insertSub(Matrix& fullMatrix, const Matrix& subMatrix, size_t i, size_t j); +/** + * Create a matrix with submatrices along its diagonal + */ +GTSAM_EXPORT Matrix diag(const std::vector& Hs); + /** * Extracts a column view from a matrix that avoids a copy * @param A matrix to extract column from diff --git a/gtsam/base/tests/testMatrix.cpp b/gtsam/base/tests/testMatrix.cpp index 4f57a6b6b..196f139a9 100644 --- a/gtsam/base/tests/testMatrix.cpp +++ b/gtsam/base/tests/testMatrix.cpp @@ -262,6 +262,30 @@ TEST( matrix, insert_sub ) EXPECT(assert_equal(expected, big)); } +/* ************************************************************************* */ +TEST( matrix, diagMatrices ) +{ + std::vector Hs; + Hs.push_back(ones(3,3)); + Hs.push_back(ones(4,4)*2); + Hs.push_back(ones(2,2)*3); + + Matrix actual = diag(Hs); + + Matrix expected = Matrix_(9, 9, + 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0); + + EXPECT(assert_equal(expected, actual)); +} + /* ************************************************************************* */ TEST( matrix, stream_read ) { Matrix expected = Matrix_(3,4, diff --git a/gtsam/geometry/Point3.h b/gtsam/geometry/Point3.h index 5930d0e94..752caec73 100644 --- a/gtsam/geometry/Point3.h +++ b/gtsam/geometry/Point3.h @@ -143,6 +143,11 @@ namespace gtsam { /** Log map at identity - return the x,y,z of this point */ static inline Vector3 Logmap(const Point3& dp) { return Vector3(dp.x(), dp.y(), dp.z()); } + /// Left-trivialized derivative of the exponential map + static Matrix dexpL(const Vector& v) { + return eye(3); + } + /// @} /// @name Vector Space /// @{ diff --git a/gtsam/geometry/Rot3.h b/gtsam/geometry/Rot3.h index f4a25ff94..fc632f8d6 100644 --- a/gtsam/geometry/Rot3.h +++ b/gtsam/geometry/Rot3.h @@ -268,6 +268,9 @@ namespace gtsam { */ static Vector3 Logmap(const Rot3& R); + /// Left-trivialized derivative of the exponential map + static Matrix3 dexpL(const Vector3& v); + /// @} /// @name Group Action on Point3 /// @{ diff --git a/gtsam/geometry/Rot3M.cpp b/gtsam/geometry/Rot3M.cpp index cb6660dae..9f8ef1960 100644 --- a/gtsam/geometry/Rot3M.cpp +++ b/gtsam/geometry/Rot3M.cpp @@ -303,6 +303,19 @@ Vector3 Rot3::localCoordinates(const Rot3& T, Rot3::CoordinatesMode mode) const } } +/* ************************************************************************* */ +/// Follow Iserles05an, B10, pg 147, with a sign change in the second term (left version) +Matrix3 Rot3::dexpL(const Vector3& v) { + if(zero(v)) return eye(3); + Matrix x = skewSymmetric(v); + Matrix x2 = x*x; + double theta = v.norm(), vi = theta/2.0; + double s1 = sin(vi)/vi; + double s2 = (theta - sin(theta))/(theta*theta*theta); + Matrix res = eye(3) - 0.5*s1*s1*x + s2*x2; + return res; +} + /* ************************************************************************* */ Matrix3 Rot3::matrix() const { return rot_; diff --git a/gtsam/geometry/tests/testRot3M.cpp b/gtsam/geometry/tests/testRot3M.cpp index b50ad1253..56e1a7cce 100644 --- a/gtsam/geometry/tests/testRot3M.cpp +++ b/gtsam/geometry/tests/testRot3M.cpp @@ -402,6 +402,25 @@ TEST( Rot3, between ) CHECK(assert_equal(numericalH2,actualH2)); } +/* ************************************************************************* */ +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 = Rot3::Logmap(Rot3::Expmap(-w) * Rot3::Expmap(w + dw)); + return y; +} + +TEST( Rot3, dexpL) { + Matrix actualDexpL = Rot3::dexpL(w); + Matrix expectedDexpL = numericalDerivative11( + boost::function( + boost::bind(testDexpL, _1)), LieVector(zero(3)), 1e-2); + EXPECT(assert_equal(expectedDexpL, actualDexpL, 1e-5)); +} + /* ************************************************************************* */ TEST( Rot3, xyz ) {