diff --git a/gtsam/base/Manifold.h b/gtsam/base/Manifold.h index 1eee71dfd..b8ec03402 100644 --- a/gtsam/base/Manifold.h +++ b/gtsam/base/Manifold.h @@ -53,9 +53,6 @@ struct is_manifold: public std::false_type { // dimension, can return Eigen::Dynamic (-1) if not known at compile time template struct dimension; -//: public std::integral_constant { -// BOOST_STATIC_ASSERT(is_manifold::value); -//}; // Chart is a map from T -> vector, retract is its inverse template @@ -82,7 +79,7 @@ struct is_manifold : public std::true_type { }; template<> -struct dimension : public std::integral_constant { +struct dimension : public std::integral_constant { }; template<> @@ -111,7 +108,7 @@ struct is_manifold > : public std::true_typ // TODO: Could be more sophisticated using Eigen traits and SFINAE? -typedef std::integral_constant Dynamic; +typedef std::integral_constant Dynamic; template struct dimension > : public Dynamic { @@ -129,7 +126,7 @@ struct dimension > : public Dy template struct dimension > : public std::integral_constant< - size_t, M * N> { + int, M * N> { BOOST_STATIC_ASSERT(M!=Eigen::Dynamic && N!=Eigen::Dynamic); }; diff --git a/gtsam/geometry/Cal3Bundler.h b/gtsam/geometry/Cal3Bundler.h index e508710cd..8f321d363 100644 --- a/gtsam/geometry/Cal3Bundler.h +++ b/gtsam/geometry/Cal3Bundler.h @@ -36,8 +36,6 @@ private: double u0_, v0_; ///< image center, not a parameter to be optimized but a constant public: - /// dimension of the variable - used to autodetect sizes - static const size_t dimension = 3; /// @name Standard Constructors /// @{ @@ -169,6 +167,14 @@ private: /// @} - }; +}; - } // namespace gtsam +template<> +struct is_manifold : public std::true_type { +}; + +template<> +struct dimension : public std::integral_constant { +}; + +} // namespace gtsam diff --git a/gtsam/geometry/Cal3_S2.h b/gtsam/geometry/Cal3_S2.h index 4e17c64f4..01cc0d916 100644 --- a/gtsam/geometry/Cal3_S2.h +++ b/gtsam/geometry/Cal3_S2.h @@ -36,8 +36,6 @@ private: double fx_, fy_, s_, u0_, v0_; public: - /// dimension of the variable - used to autodetect sizes - static const size_t dimension = 5; typedef boost::shared_ptr shared_ptr; ///< shared pointer to calibration object @@ -200,12 +198,12 @@ public: /// return DOF, dimensionality of tangent space inline size_t dim() const { - return dimension; + return 5; } /// return DOF, dimensionality of tangent space static size_t Dim() { - return dimension; + return 5; } /// Given 5-dim tangent vector, create new calibration @@ -242,4 +240,13 @@ private: }; +template<> +struct is_manifold : public std::true_type { +}; + +template<> +struct dimension : public std::integral_constant { +}; + + } // \ namespace gtsam diff --git a/gtsam/geometry/PinholeCamera.h b/gtsam/geometry/PinholeCamera.h index 86e6a9097..3df8bb97d 100644 --- a/gtsam/geometry/PinholeCamera.h +++ b/gtsam/geometry/PinholeCamera.h @@ -303,7 +303,7 @@ public: return K_.uncalibrate(pn); } - typedef Eigen::Matrix Matrix2K; + typedef Eigen::Matrix::value> Matrix2K; /** project a point from world coordinate to the image * @param pw is a point in world coordinates diff --git a/gtsam/geometry/Point2.h b/gtsam/geometry/Point2.h index ccab84233..d6c7e28a2 100644 --- a/gtsam/geometry/Point2.h +++ b/gtsam/geometry/Point2.h @@ -33,10 +33,9 @@ namespace gtsam { * \nosubgrouping */ class GTSAM_EXPORT Point2 : public DerivedValue { -public: - /// dimension of the variable - used to autodetect sizes - static const size_t dimension = 2; + private: + double x_, y_; public: @@ -153,10 +152,10 @@ public: /// @{ /// dimension of the variable - used to autodetect sizes - inline static size_t Dim() { return dimension; } + inline static size_t Dim() { return 2; } /// Dimensionality of tangent space = 2 DOF - inline size_t dim() const { return dimension; } + inline size_t dim() const { return 2; } /// Updates a with tangent space delta inline Point2 retract(const Vector& v) const { return *this + Point2(v); } @@ -251,5 +250,13 @@ private: /// multiply with scalar inline Point2 operator*(double s, const Point2& p) {return p*s;} +template<> +struct is_manifold : public std::true_type { +}; + +template<> +struct dimension : public std::integral_constant { +}; + } diff --git a/gtsam/geometry/Point3.h b/gtsam/geometry/Point3.h index 6e5b1ea8a..151958476 100644 --- a/gtsam/geometry/Point3.h +++ b/gtsam/geometry/Point3.h @@ -37,11 +37,9 @@ namespace gtsam { * \nosubgrouping */ class GTSAM_EXPORT Point3 : public DerivedValue { - public: - /// dimension of the variable - used to autodetect sizes - static const size_t dimension = 3; private: + double x_, y_, z_; public: @@ -122,10 +120,10 @@ namespace gtsam { /// @{ /// dimension of the variable - used to autodetect sizes - inline static size_t Dim() { return dimension; } + inline static size_t Dim() { return 3; } /// return dimensionality of tangent space, DOF = 3 - inline size_t dim() const { return dimension; } + inline size_t dim() const { return 3; } /// Updates a with tangent space delta inline Point3 retract(const Vector& v) const { return Point3(*this + v); } @@ -244,4 +242,12 @@ namespace gtsam { /// Syntactic sugar for multiplying coordinates by a scalar s*p inline Point3 operator*(double s, const Point3& p) { return p*s;} + template<> + struct is_manifold : public std::true_type { + }; + + template<> + struct dimension : public std::integral_constant { + }; + } diff --git a/gtsam/geometry/Pose2.h b/gtsam/geometry/Pose2.h index 13773ddb4..5be9f11dd 100644 --- a/gtsam/geometry/Pose2.h +++ b/gtsam/geometry/Pose2.h @@ -36,7 +36,6 @@ namespace gtsam { class GTSAM_EXPORT Pose2 : public DerivedValue { public: - static const size_t dimension = 3; /** Pose Concept requirements */ typedef Rot2 Rotation; @@ -142,10 +141,10 @@ public: /// @{ /// Dimensionality of tangent space = 3 DOF - used to autodetect sizes - inline static size_t Dim() { return dimension; } + inline static size_t Dim() { return 3; } /// Dimensionality of tangent space = 3 DOF - inline size_t dim() const { return dimension; } + inline size_t dim() const { return 3; } /// Retraction from R^3 \f$ [T_x,T_y,\theta] \f$ to Pose2 manifold neighborhood around current pose Pose2 retract(const Vector& v) const; @@ -294,6 +293,8 @@ public: */ static std::pair rotationInterval() { return std::make_pair(2, 2); } + /// @} + private: // Serialization function @@ -320,7 +321,13 @@ inline Matrix wedge(const Vector& xi) { typedef std::pair Point2Pair; GTSAM_EXPORT boost::optional align(const std::vector& pairs); -/// @} +template<> +struct is_manifold : public std::true_type { +}; + +template<> +struct dimension : public std::integral_constant { +}; } // namespace gtsam diff --git a/gtsam/geometry/Pose3.h b/gtsam/geometry/Pose3.h index 55cda05a8..d2ecee4c5 100644 --- a/gtsam/geometry/Pose3.h +++ b/gtsam/geometry/Pose3.h @@ -41,7 +41,6 @@ class Pose2; */ class GTSAM_EXPORT Pose3: public DerivedValue { public: - static const size_t dimension = 6; /** Pose Concept requirements */ typedef Rot3 Rotation; @@ -132,12 +131,12 @@ public: /// Dimensionality of tangent space = 6 DOF - used to autodetect sizes static size_t Dim() { - return dimension; + return 6; } /// Dimensionality of the tangent space = 6 DOF size_t dim() const { - return dimension; + return 6; } /// Retraction from R^6 \f$ [R_x,R_y,R_z,T_x,T_y,T_z] \f$ from R^ with fast first-order approximation to the exponential map @@ -355,4 +354,12 @@ inline Matrix wedge(const Vector& xi) { typedef std::pair Point3Pair; GTSAM_EXPORT boost::optional align(const std::vector& pairs); +template<> +struct is_manifold : public std::true_type { +}; + +template<> +struct dimension : public std::integral_constant { +}; + } // namespace gtsam diff --git a/gtsam/geometry/Rot3.h b/gtsam/geometry/Rot3.h index 59a09ba39..612c3c47c 100644 --- a/gtsam/geometry/Rot3.h +++ b/gtsam/geometry/Rot3.h @@ -59,10 +59,9 @@ namespace gtsam { * \nosubgrouping */ class GTSAM_EXPORT Rot3 : public DerivedValue { - public: - static const size_t dimension = 3; private: + #ifdef GTSAM_USE_QUATERNIONS /** Internal Eigen Quaternion */ Quaternion quaternion_; @@ -260,10 +259,10 @@ namespace gtsam { /// @{ /// dimension of the variable - used to autodetect sizes - static size_t Dim() { return dimension; } + static size_t Dim() { return 3; } /// return dimensionality of tangent space, DOF = 3 - size_t dim() const { return dimension; } + size_t dim() const { return 3; } /** * The method retract() is used to map from the tangent space back to the manifold. @@ -449,6 +448,8 @@ namespace gtsam { /// Output stream operator GTSAM_EXPORT friend std::ostream &operator<<(std::ostream &os, const Rot3& p); + /// @} + private: /** Serialization function */ @@ -478,8 +479,6 @@ namespace gtsam { }; - /// @} - /** * [RQ] receives a 3 by 3 matrix and returns an upper triangular matrix R * and 3 rotation angles corresponding to the rotation matrix Q=Qz'*Qy'*Qx' @@ -491,4 +490,14 @@ namespace gtsam { * @return a vector [thetax, thetay, thetaz] in radians. */ GTSAM_EXPORT std::pair RQ(const Matrix3& A); + + template<> + struct is_manifold : public std::true_type { + }; + + template<> + struct dimension : public std::integral_constant { + }; + + } diff --git a/gtsam_unstable/nonlinear/Expression-inl.h b/gtsam_unstable/nonlinear/Expression-inl.h index 6a5502fd1..0da5727c1 100644 --- a/gtsam_unstable/nonlinear/Expression-inl.h +++ b/gtsam_unstable/nonlinear/Expression-inl.h @@ -22,6 +22,8 @@ #include #include #include +#include + #include #include @@ -38,7 +40,6 @@ namespace MPL = boost::mpl::placeholders; #include // for placement new - class ExpressionFactorBinaryTest; // Forward declare for testing @@ -75,14 +76,15 @@ struct CallRecord { //----------------------------------------------------------------------------- /// Handle Leaf Case: reverseAD ends here, by writing a matrix into Jacobians template -void handleLeafCase(const Eigen::Matrix& dTdA, +void handleLeafCase(const Eigen::Matrix& dTdA, JacobianMap& jacobians, Key key) { JacobianMap::iterator it = jacobians.find(key); - it->second.block(0,0) += dTdA; // block makes HUGE difference + it->second.block(0, 0) += dTdA; // block makes HUGE difference } /// Handle Leaf Case for Dynamic Matrix type (slower) template<> -void handleLeafCase(const Eigen::Matrix& dTdA, +void handleLeafCase( + const Eigen::Matrix& dTdA, JacobianMap& jacobians, Key key) { JacobianMap::iterator it = jacobians.find(key); it->second += dTdA; @@ -98,12 +100,13 @@ void handleLeafCase(const Eigen::Matrix& d */ template class ExecutionTrace { + static const int Dim = dimension::value; enum { Constant, Leaf, Function } kind; union { Key key; - CallRecord* ptr; + CallRecord* ptr; } content; public: /// Pointer always starts out as a Constant @@ -116,7 +119,7 @@ public: content.key = key; } /// Take ownership of pointer to a Function Record - void setFunction(CallRecord* record) { + void setFunction(CallRecord* record) { kind = Function; content.ptr = record; } @@ -145,7 +148,7 @@ public: * *** This is the main entry point for reverseAD, called from Expression *** * Called only once, either inserts I into Jacobians (Leaf) or starts AD (Function) */ - typedef Eigen::Matrix JacobianTT; + typedef Eigen::Matrix JacobianTT; void startReverseAD(JacobianMap& jacobians) const { if (kind == Leaf) { // This branch will only be called on trivial Leaf expressions, i.e. Priors @@ -164,7 +167,7 @@ public: content.ptr->reverseAD(dTdA, jacobians); } // Either add to Jacobians (Leaf) or propagate (Function) - typedef Eigen::Matrix Jacobian2T; + typedef Eigen::Matrix Jacobian2T; void reverseAD2(const Jacobian2T& dTdA, JacobianMap& jacobians) const { if (kind == Leaf) handleLeafCase(dTdA, jacobians, content.key); @@ -179,7 +182,7 @@ public: /// Primary template calls the generic Matrix reverseAD pipeline template struct Select { - typedef Eigen::Matrix Jacobian; + typedef Eigen::Matrix::value> Jacobian; static void reverseAD(const ExecutionTrace& trace, const Jacobian& dTdA, JacobianMap& jacobians) { trace.reverseAD(dTdA, jacobians); @@ -189,7 +192,7 @@ struct Select { /// Partially specialized template calls the 2-dimensional output version template struct Select<2, A> { - typedef Eigen::Matrix Jacobian; + typedef Eigen::Matrix::value> Jacobian; static void reverseAD(const ExecutionTrace& trace, const Jacobian& dTdA, JacobianMap& jacobians) { trace.reverseAD2(dTdA, jacobians); @@ -300,7 +303,7 @@ public: /// Return dimensions for each argument virtual void dims(std::map& map) const { - map[key_] = T::dimension; + map[key_] = dimension::value; } /// Return value @@ -351,13 +354,13 @@ public: /// meta-function to generate fixed-size JacobianTA type template struct Jacobian { - typedef Eigen::Matrix type; + typedef Eigen::Matrix::value, dimension::value> type; }; /// meta-function to generate JacobianTA optional reference template struct Optional { - typedef Eigen::Matrix Jacobian; + typedef Eigen::Matrix::value, dimension::value> Jacobian; typedef boost::optional type; }; @@ -368,7 +371,7 @@ template struct FunctionalBase: ExpressionNode { static size_t const N = 0; // number of arguments - typedef CallRecord Record; + typedef CallRecord::value> Record; /// Construct an execution trace for reverse AD void trace(const Values& values, Record* record, char*& raw) const { @@ -437,7 +440,8 @@ struct GenerateFunctionalNode: Argument, Base { /// Start the reverse AD process virtual void startReverseAD(JacobianMap& jacobians) const { Base::Record::startReverseAD(jacobians); - Select::reverseAD(This::trace, This::dTdA, jacobians); + Select::value, A>::reverseAD(This::trace, This::dTdA, + jacobians); } /// Given df/dT, multiply in dT/dA and continue reverse AD process @@ -447,7 +451,7 @@ struct GenerateFunctionalNode: Argument, Base { } /// Version specialized to 2-dimensional output - typedef Eigen::Matrix Jacobian2T; + typedef Eigen::Matrix::value> Jacobian2T; virtual void reverseAD2(const Jacobian2T& dFdT, JacobianMap& jacobians) const { Base::Record::reverseAD2(dFdT, jacobians); diff --git a/gtsam_unstable/nonlinear/Expression.h b/gtsam_unstable/nonlinear/Expression.h index 1ab69880e..12e101f14 100644 --- a/gtsam_unstable/nonlinear/Expression.h +++ b/gtsam_unstable/nonlinear/Expression.h @@ -154,7 +154,8 @@ public: template struct apply_compose { typedef T result_type; - typedef Eigen::Matrix Jacobian; + static const int Dim = dimension::value; + typedef Eigen::Matrix Jacobian; T operator()(const T& x, const T& y, boost::optional H1, boost::optional H2) const { return x.compose(y, H1, H2); diff --git a/gtsam_unstable/nonlinear/ExpressionFactor.h b/gtsam_unstable/nonlinear/ExpressionFactor.h index 8030165b9..66ba025d2 100644 --- a/gtsam_unstable/nonlinear/ExpressionFactor.h +++ b/gtsam_unstable/nonlinear/ExpressionFactor.h @@ -45,7 +45,7 @@ public: measurement_(measurement), expression_(expression) { if (!noiseModel) throw std::invalid_argument("ExpressionFactor: no NoiseModel."); - if (noiseModel->dim() != T::dimension) + if (noiseModel->dim() != dimension::value) throw std::invalid_argument( "ExpressionFactor was created with a NoiseModel of incorrect dimension."); noiseModel_ = noiseModel; @@ -68,7 +68,7 @@ public: #ifdef DEBUG_ExpressionFactor BOOST_FOREACH(size_t d, dimensions_) std::cout << d << " "; - std::cout << " -> " << T::dimension << "x" << augmentedCols_ << std::endl; + std::cout << " -> " << dimension::value << "x" << augmentedCols_ << std::endl; #endif } @@ -87,9 +87,9 @@ public: JacobianMap blocks; for (DenseIndex i = 0; i < size(); i++) { Matrix& Hi = H->at(i); - Hi.resize(T::dimension, dimensions_[i]); + Hi.resize(dimension::value, dimensions_[i]); Hi.setZero(); // zero out - Eigen::Block block = Hi.block(0, 0, T::dimension, + Eigen::Block block = Hi.block(0, 0, dimension::value, dimensions_[i]); blocks.insert(std::make_pair(keys_[i], block)); } @@ -105,9 +105,9 @@ public: virtual boost::shared_ptr linearize(const Values& x) const { // Allocate memory on stack and create a view on it (saves a malloc) - double memory[T::dimension * augmentedCols_]; - Eigen::Map > // - matrix(memory, T::dimension, augmentedCols_); + double memory[dimension::value * augmentedCols_]; + Eigen::Map::value, Eigen::Dynamic> > // + matrix(memory, dimension::value, augmentedCols_); matrix.setZero(); // zero out // Construct block matrix, is of right size but un-initialized diff --git a/gtsam_unstable/nonlinear/tests/testExpression.cpp b/gtsam_unstable/nonlinear/tests/testExpression.cpp index 45f8f3284..b830613c3 100644 --- a/gtsam_unstable/nonlinear/tests/testExpression.cpp +++ b/gtsam_unstable/nonlinear/tests/testExpression.cpp @@ -324,19 +324,6 @@ struct SnavelyReprojectionError { /* ************************************************************************* */ -// Point2 -namespace gtsam { - -template<> -struct is_manifold : public true_type { -}; - -template<> -struct dimension : public integral_constant { -}; - -} - // is_manifold TEST(Expression, is_manifold) { EXPECT(!is_manifold::value); @@ -506,9 +493,9 @@ TEST(Expression, AutoDiff2) { /* ************************************************************************* */ // keys TEST(Expression, SnavelyKeys) { -// Expression expression(1); -// set expected = list_of(1)(2); -// EXPECT(expected == expression.keys()); + Expression expression(1); + set expected = list_of(1)(2); + EXPECT(expected == expression.keys()); } /* ************************************************************************* */ int main() {