diff --git a/gtsam/base/Manifold.h b/gtsam/base/Manifold.h index 9dadaf9e6..fa509252d 100644 --- a/gtsam/base/Manifold.h +++ b/gtsam/base/Manifold.h @@ -242,21 +242,56 @@ struct DefaultChart { // Fixed size Eigen::Matrix type +namespace internal { + +template +struct Reshape { + //TODO replace this with Eigen's reshape function as soon as available. (There is a PR already pending : https://bitbucket.org/eigen/eigen/pull-request/41/reshape/diff) + typedef Eigen::Map > ReshapedType; + static inline ReshapedType reshape(const Eigen::Matrix & in) { + return in.data(); + } +}; + +template +struct Reshape { + typedef const Eigen::Matrix & ReshapedType; + static inline ReshapedType reshape(const Eigen::Matrix & in) { + return in; + } +}; + +template +struct Reshape { + typedef typename Eigen::Matrix::ConstTransposeReturnType ReshapedType; + static inline ReshapedType reshape(const Eigen::Matrix & in) { + return in.transpose(); + } +}; + +template +inline typename Reshape::ReshapedType reshape(const Eigen::Matrix & m){ + BOOST_STATIC_ASSERT(InM * InN == OutM * OutN); + return Reshape::reshape(m); +} + +} + template struct DefaultChart > { + /** + * This chart for the vector space of M x N matrices (represented by Eigen matrices) chooses as basis the one with respect to which the coordinates are exactly the matrix entries as laid out in memory (as determined by Options). + * Computing coordinates for a matrix is then simply a reshape to the row vector of appropriate size. + */ typedef Eigen::Matrix type; typedef type T; typedef Eigen::Matrix::value, 1> vector;BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic), "DefaultChart has not been implemented yet for dynamically sized matrices"); static vector local(const T& origin, const T& other) { - T diff = other - origin; - Eigen::Map map(diff.data()); - return vector(map); - // Why is this function not : return other - origin; ?? what is the Eigen::Map used for? + return internal::reshape(other) - internal::reshape(origin); } static T retract(const T& origin, const vector& d) { - Eigen::Map map(d.data()); - return origin + map; + return origin + internal::reshape(d); } static int getDimension(const T&origin) { return origin.rows() * origin.cols(); diff --git a/tests/testManifold.cpp b/tests/testManifold.cpp index c9451c6de..6e720757a 100644 --- a/tests/testManifold.cpp +++ b/tests/testManifold.cpp @@ -76,6 +76,26 @@ TEST(Manifold, DefaultChart) { EXPECT(assert_equal(v2, chart2.local(Vector2(0, 0), Vector2(1, 0)))); EXPECT(chart2.retract(Vector2(0, 0), v2) == Vector2(1, 0)); + { + typedef Matrix2 ManifoldPoint; + ManifoldPoint m; + DefaultChart chart; + m << 1, 3, + 2, 4; + // m as per default is in column-major storage mode. So this yields a linear representation of (1, 2, 3, 4)! + EXPECT(assert_equal(Vector(Vector4(1, 2, 3, 4)), Vector(chart.local(ManifoldPoint::Zero(), m)))); + EXPECT(chart.retract(m, Vector4(1, 2, 3, 4)) == 2 * m); + } + + { + typedef Eigen::Matrix ManifoldPoint; + ManifoldPoint m; + DefaultChart chart; + m << 1, 2; + EXPECT(assert_equal(Vector(Vector2(1, 2)), Vector(chart.local(ManifoldPoint::Zero(), m)))); + EXPECT(chart.retract(m, Vector2(1, 2)) == 2 * m); + } + DefaultChart chart3; Vector v1(1); v1 << 1;