diff --git a/.cproject b/.cproject
index 7223156ff..895e2667a 100644
--- a/.cproject
+++ b/.cproject
@@ -600,6 +600,7 @@
make
+
tests/testBayesTree.run
true
false
@@ -607,6 +608,7 @@
make
+
testBinaryBayesNet.run
true
false
@@ -654,6 +656,7 @@
make
+
testSymbolicBayesNet.run
true
false
@@ -661,6 +664,7 @@
make
+
tests/testSymbolicFactor.run
true
false
@@ -668,6 +672,7 @@
make
+
testSymbolicFactorGraph.run
true
false
@@ -683,6 +688,7 @@
make
+
tests/testBayesTree
true
false
@@ -800,6 +806,54 @@
true
true
+
+ make
+ -j5
+ testInertialNavFactor_GlobalVelocity.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testInvDepthFactorVariant3.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testInvDepthFactorVariant1.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testEquivInertialNavFactor_GlobalVel.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testInvDepthFactorVariant2.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testRelativeElevationFactor.run
+ true
+ true
+ true
+
make
-j5
@@ -896,6 +950,14 @@
true
true
+
+ make
+ -j5
+ testGaussianBayesTree.run
+ true
+ true
+ true
+
make
-j5
@@ -1042,6 +1104,7 @@
make
+
testErrors.run
true
false
@@ -1271,6 +1334,46 @@
true
true
+
+ make
+ -j5
+ testBTree.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSF.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSFMap.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testDSFVector.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testFixedVector.run
+ true
+ true
+ true
+
make
-j2
@@ -1353,7 +1456,6 @@
make
-
testSimulated2DOriented.run
true
false
@@ -1393,7 +1495,6 @@
make
-
testSimulated2D.run
true
false
@@ -1401,7 +1502,6 @@
make
-
testSimulated3D.run
true
false
@@ -1415,46 +1515,6 @@
true
true
-
- make
- -j5
- testBTree.run
- true
- true
- true
-
-
- make
- -j5
- testDSF.run
- true
- true
- true
-
-
- make
- -j5
- testDSFMap.run
- true
- true
- true
-
-
- make
- -j5
- testDSFVector.run
- true
- true
- true
-
-
- make
- -j5
- testFixedVector.run
- true
- true
- true
-
make
-j5
@@ -1712,6 +1772,7 @@
cpack
+
-G DEB
true
false
@@ -1719,6 +1780,7 @@
cpack
+
-G RPM
true
false
@@ -1726,6 +1788,7 @@
cpack
+
-G TGZ
true
false
@@ -1733,6 +1796,7 @@
cpack
+
--config CPackSourceConfig.cmake
true
false
@@ -2065,6 +2129,22 @@
true
true
+
+ make
+ -j5
+ testRot2.run
+ true
+ true
+ true
+
+
+ make
+ -j5
+ testRot3Q.run
+ true
+ true
+ true
+
make
-j2
@@ -2161,6 +2241,14 @@
true
true
+
+ make
+ -j5
+ testVelocityConstraint.run
+ true
+ true
+ true
+
make
-j1
@@ -2321,6 +2409,14 @@
true
true
+
+ make
+ -j5
+ testNumericalDerivative.run
+ true
+ true
+ true
+
make
-j5
@@ -2459,6 +2555,7 @@
make
+
testGraph.run
true
false
@@ -2466,6 +2563,7 @@
make
+
testJunctionTree.run
true
false
@@ -2473,6 +2571,7 @@
make
+
testSymbolicBayesNetB.run
true
false
@@ -2534,6 +2633,14 @@
true
true
+
+ make
+ -j5
+ testManifold.run
+ true
+ true
+ true
+
make
-j5
@@ -2566,6 +2673,14 @@
true
true
+
+ make
+ -j5
+ testAdaptAutoDiff.run
+ true
+ true
+ true
+
make
-j2
@@ -2968,7 +3083,6 @@
make
-
tests/testGaussianISAM2
true
false
diff --git a/gtsam/base/LieMatrix.h b/gtsam/base/LieMatrix.h
index 23e5fd023..2a8d4bc41 100644
--- a/gtsam/base/LieMatrix.h
+++ b/gtsam/base/LieMatrix.h
@@ -174,4 +174,18 @@ private:
}
};
+
+// Define GTSAM traits
+namespace traits {
+
+template<>
+struct is_manifold : public std::true_type {
+};
+
+template<>
+struct dimension : public Dynamic {
+};
+
+}
+
} // \namespace gtsam
diff --git a/gtsam/base/LieScalar.h b/gtsam/base/LieScalar.h
index 21a2e10ad..750a8a21f 100644
--- a/gtsam/base/LieScalar.h
+++ b/gtsam/base/LieScalar.h
@@ -111,4 +111,22 @@ namespace gtsam {
private:
double d_;
};
+
+ // Define GTSAM traits
+ namespace traits {
+
+ template<>
+ struct is_group : public std::true_type {
+ };
+
+ template<>
+ struct is_manifold : public std::true_type {
+ };
+
+ template<>
+ struct dimension : public std::integral_constant {
+ };
+
+ }
+
} // \namespace gtsam
diff --git a/gtsam/base/LieVector.h b/gtsam/base/LieVector.h
index a8bfe3007..8286c95a6 100644
--- a/gtsam/base/LieVector.h
+++ b/gtsam/base/LieVector.h
@@ -128,6 +128,19 @@ private:
ar & boost::serialization::make_nvp("Vector",
boost::serialization::base_object(*this));
}
-
};
+
+// Define GTSAM traits
+namespace traits {
+
+template<>
+struct is_manifold : public std::true_type {
+};
+
+template<>
+struct dimension : public Dynamic {
+};
+
+}
+
} // \namespace gtsam
diff --git a/gtsam/base/Manifold.h b/gtsam/base/Manifold.h
index ceebf6bad..63390ec1f 100644
--- a/gtsam/base/Manifold.h
+++ b/gtsam/base/Manifold.h
@@ -13,25 +13,19 @@
* @file Manifold.h
* @brief Base class and basic functions for Manifold types
* @author Alex Cunningham
+ * @author Frank Dellaert
*/
#pragma once
-#include
#include
+#include
+#include
+#include
namespace gtsam {
/**
- * Concept check class for Manifold types
- * Requires a mapping between a linear tangent space and the underlying
- * manifold, of which Lie is a specialization.
- *
- * The necessary functions to implement for Manifold are defined
- * below with additional details as to the interface. The
- * concept checking function in class Manifold will check whether or not
- * the function exists and throw compile-time errors.
- *
* A manifold defines a space in which there is a notion of a linear tangent space
* that can be centered around a given point on the manifold. These nonlinear
* spaces may have such properties as wrapping around (as is the case with rotations),
@@ -45,7 +39,216 @@ namespace gtsam {
* There may be multiple possible retractions for a given manifold, which can be chosen
* between depending on the computational complexity. The important criteria for
* the creation for the retract and localCoordinates functions is that they be
- * inverse operations.
+ * inverse operations. The new notion of a Chart guarantees that.
+ *
+ */
+
+// Traits, same style as Boost.TypeTraits
+// All meta-functions below ever only declare a single type
+// or a type/value/value_type
+namespace traits {
+
+// is group, by default this is false
+template
+struct is_group: public std::false_type {
+};
+
+// identity, no default provided, by default given by default constructor
+template
+struct identity {
+ static T value() {
+ return T();
+ }
+};
+
+// is manifold, by default this is false
+template
+struct is_manifold: public std::false_type {
+};
+
+// dimension, can return Eigen::Dynamic (-1) if not known at compile time
+template
+struct dimension;
+
+/**
+ * zero::value is intended to be the origin of a canonical coordinate system
+ * with canonical(t) == DefaultChart(zero::value).apply(t)
+ * Below we provide the group identity as zero *in case* it is a group
+ */
+template struct zero: public identity {
+ BOOST_STATIC_ASSERT(is_group::value);
+};
+
+// double
+
+template<>
+struct is_group : public std::true_type {
+};
+
+template<>
+struct is_manifold : public std::true_type {
+};
+
+template<>
+struct dimension : public std::integral_constant {
+};
+
+template<>
+struct zero {
+ static double value() {
+ return 0;
+ }
+};
+
+// Fixed size Eigen::Matrix type
+
+template
+struct is_group > : public std::true_type {
+};
+
+template
+struct is_manifold > : public std::true_type {
+};
+
+// TODO: Could be more sophisticated using Eigen traits and SFINAE?
+
+typedef std::integral_constant Dynamic;
+
+template
+struct dimension > : public Dynamic {
+};
+
+template
+struct dimension > : public Dynamic {
+};
+
+template
+struct dimension > : public Dynamic {
+};
+
+template
+struct dimension > : public std::integral_constant<
+ int, M * N> {
+};
+
+template
+struct zero > : public std::integral_constant<
+ int, M * N> {
+ BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic),
+ "traits::zero is only supported for fixed-size matrices");
+ static Eigen::Matrix value() {
+ return Eigen::Matrix::Zero();
+ }
+};
+
+} // \ namespace traits
+
+// Chart is a map from T -> vector, retract is its inverse
+template
+struct DefaultChart {
+ BOOST_STATIC_ASSERT(traits::is_manifold::value);
+ typedef Eigen::Matrix::value, 1> vector;
+ T t_;
+ DefaultChart(const T& t) :
+ t_(t) {
+ }
+ vector apply(const T& other) {
+ return t_.localCoordinates(other);
+ }
+ T retract(const vector& d) {
+ return t_.retract(d);
+ }
+};
+
+/**
+ * Canonical::value is a chart around zero::value
+ * An example is Canonical
+ */
+template struct Canonical {
+ typedef T type;
+ typedef typename DefaultChart::vector vector;
+ DefaultChart chart;
+ Canonical() :
+ chart(traits::zero::value()) {
+ }
+ // Convert t of type T into canonical coordinates
+ vector apply(const T& t) {
+ return chart.apply(t);
+ }
+ // Convert back from canonical coordinates to T
+ T retract(const vector& v) {
+ return chart.retract(v);
+ }
+};
+
+// double
+
+template<>
+struct DefaultChart {
+ typedef Eigen::Matrix vector;
+ double t_;
+ DefaultChart(double t) :
+ t_(t) {
+ }
+ vector apply(double other) {
+ vector d;
+ d << other - t_;
+ return d;
+ }
+ double retract(const vector& d) {
+ return t_ + d[0];
+ }
+};
+
+// Fixed size Eigen::Matrix type
+
+template
+struct DefaultChart > {
+ typedef Eigen::Matrix 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");
+ T t_;
+ DefaultChart(const T& t) :
+ t_(t) {
+ }
+ vector apply(const T& other) {
+ T diff = other - t_;
+ Eigen::Map map(diff.data());
+ return vector(map);
+ }
+ T retract(const vector& d) {
+ Eigen::Map map(d.data());
+ return t_ + map;
+ }
+};
+
+// Dynamically sized Vector
+template<>
+struct DefaultChart {
+ typedef Vector T;
+ typedef T vector;
+ T t_;
+ DefaultChart(const T& t) :
+ t_(t) {
+ }
+ vector apply(const T& other) {
+ return other - t_;
+ }
+ T retract(const vector& d) {
+ return t_ + d;
+ }
+};
+
+/**
+ * Old Concept check class for Manifold types
+ * Requires a mapping between a linear tangent space and the underlying
+ * manifold, of which Lie is a specialization.
+ *
+ * The necessary functions to implement for Manifold are defined
+ * below with additional details as to the interface. The
+ * concept checking function in class Manifold will check whether or not
+ * the function exists and throw compile-time errors.
*
* Returns dimensionality of the tangent space, which may be smaller than the number
* of nonlinear parameters.
@@ -61,7 +264,7 @@ namespace gtsam {
* By convention, we use capital letters to designate a static function
* @tparam T is a Lie type, like Point2, Pose3, etc.
*/
-template
+template
class ManifoldConcept {
private:
/** concept checking function - implement the functions this demands */
@@ -89,7 +292,7 @@ private:
}
};
-} // namespace gtsam
+} // \ namespace gtsam
/**
* Macros for using the ManifoldConcept
diff --git a/gtsam/base/numericalDerivative.h b/gtsam/base/numericalDerivative.h
index 036f23f68..87c912e57 100644
--- a/gtsam/base/numericalDerivative.h
+++ b/gtsam/base/numericalDerivative.h
@@ -16,7 +16,6 @@
*/
// \callgraph
-
#pragma once
#include
@@ -29,597 +28,492 @@
#pragma GCC diagnostic pop
#endif
-#include
#include
+#include
namespace gtsam {
- /*
- * Note that all of these functions have two versions, a boost.function version and a
- * standard C++ function pointer version. This allows reformulating the arguments of
- * a function to fit the correct structure, which is useful for situations like
- * member functions and functions with arguments not involved in the derivative:
- *
- * Usage of the boost bind version to rearrange arguments:
- * for a function with one relevant param and an optional derivative:
- * Foo bar(const Obj& a, boost::optional H1)
- * Use boost.bind to restructure:
- * boost::bind(bar, _1, boost::none)
- * This syntax will fix the optional argument to boost::none, while using the first argument provided
- *
- * For member functions, such as below, with an instantiated copy instanceOfSomeClass
- * Foo SomeClass::bar(const Obj& a)
- * Use boost bind as follows to create a function pointer that uses the member function:
- * boost::bind(&SomeClass::bar, ref(instanceOfSomeClass), _1)
- *
- * For additional details, see the documentation:
- * http://www.boost.org/doc/libs/release/libs/bind/bind.html
- */
+/*
+ * Note that all of these functions have two versions, a boost.function version and a
+ * standard C++ function pointer version. This allows reformulating the arguments of
+ * a function to fit the correct structure, which is useful for situations like
+ * member functions and functions with arguments not involved in the derivative:
+ *
+ * Usage of the boost bind version to rearrange arguments:
+ * for a function with one relevant param and an optional derivative:
+ * Foo bar(const Obj& a, boost::optional H1)
+ * Use boost.bind to restructure:
+ * boost::bind(bar, _1, boost::none)
+ * This syntax will fix the optional argument to boost::none, while using the first argument provided
+ *
+ * For member functions, such as below, with an instantiated copy instanceOfSomeClass
+ * Foo SomeClass::bar(const Obj& a)
+ * Use boost bind as follows to create a function pointer that uses the member function:
+ * boost::bind(&SomeClass::bar, ref(instanceOfSomeClass), _1)
+ *
+ * For additional details, see the documentation:
+ * http://www.boost.org/doc/libs/release/libs/bind/bind.html
+ */
+/**
+ * Numerically compute gradient of scalar function
+ * Class X is the input argument
+ * The class X needs to have dim, expmap, logmap
+ */
+template
+Vector numericalGradient(boost::function h, const X& x,
+ double delta = 1e-5) {
+ double factor = 1.0 / (2.0 * delta);
- /** global functions for converting to a LieVector for use with numericalDerivative */
- inline LieVector makeLieVector(const Vector& v) { return LieVector(v); }
- inline LieVector makeLieVectorD(double d) { return LieVector((Vector) (Vector(1) << d)); }
+ BOOST_STATIC_ASSERT_MSG(traits::is_manifold::value,
+ "Template argument X must be a manifold type.");
+ static const int N = traits::dimension::value;
+ BOOST_STATIC_ASSERT_MSG(N>0, "Template argument X must be fixed-size type.");
+ typedef DefaultChart ChartX;
+ typedef typename ChartX::vector TangentX;
- /**
- * Numerically compute gradient of scalar function
- * Class X is the input argument
- * The class X needs to have dim, expmap, logmap
- */
- template
- Vector numericalGradient(boost::function h, const X& x, double delta=1e-5) {
- double factor = 1.0/(2.0*delta);
- const size_t n = x.dim();
- Vector d = zero(n), g = zero(n);
- for (size_t j=0;j
- Vector numericalGradient(double (*h)(const X&), const X& x, double delta=1e-5) {
- return numericalGradient(boost::bind(h, _1), x, delta);
- }
-
- /**
- * Compute numerical derivative in argument 1 of unary function
- * @param h unary function yielding m-vector
- * @param x n-dimensional value at which to evaluate h
- * @param delta increment for numerical derivative
- * Class Y is the output argument
- * Class X is the input argument
- * @return m*n Jacobian computed via central differencing
- * Both classes X,Y need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative11(boost::function h, const X& x, double delta=1e-5) {
- Y hx = h(x);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- Matrix numericalDerivative11(Y (*h)(const X&), const X& x, double delta=1e-5) {
- return numericalDerivative11(boost::bind(h, _1), x, delta);
- }
-
-// /** remapping for double valued functions */
-// template
-// Matrix numericalDerivative11(boost::function h, const X& x, double delta=1e-5) {
-// return numericalDerivative11(boost::bind(makeLieVectorD, boost::bind(h, _1)), x, delta);
-// }
-
- template
- Matrix numericalDerivative11(double (*h)(const X&), const X& x, double delta=1e-5) {
- return numericalDerivative11(boost::bind(makeLieVectorD, boost::bind(h, _1)), x, delta);
- }
-
- /** remapping for vector valued functions */
- template
- Matrix numericalDerivative11(boost::function h, const X& x, double delta=1e-5) {
- return numericalDerivative11(boost::bind(makeLieVector, boost::bind(h, _1)), x, delta);
- }
-
- template
- Matrix numericalDerivative11(Vector (*h)(const X&), const X& x, double delta=1e-5) {
- return numericalDerivative11(boost::bind(makeLieVector, boost::bind(h, _1)), x, delta);
- }
-
- /**
- * Compute numerical derivative in argument 1 of binary function
- * @param h binary function yielding m-vector
- * @param x1 n-dimensional first argument value
- * @param x2 second argument value
- * @param delta increment for numerical derivative
- * @return m*n Jacobian computed via central differencing
- * All classes Y,X1,X2 need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative21(boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- Y hx = h(x1,x2);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x1.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- inline Matrix numericalDerivative21(Y (*h)(const X1&, const X2&),
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative21(boost::bind(h, _1, _2), x1, x2, delta);
- }
-
- /** pseudo-partial template specialization for double return values */
- template
- Matrix numericalDerivative21(boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative21(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- template
- Matrix numericalDerivative21(double (*h)(const X1&, const X2&),
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative21(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- /** pseudo-partial template specialization for vector return values */
- template
- Matrix numericalDerivative21(boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative21(
- boost::bind(makeLieVector, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- template
- inline Matrix numericalDerivative21(Vector (*h)(const X1&, const X2&),
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative21(
- boost::bind(makeLieVector, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- /**
- * Compute numerical derivative in argument 2 of binary function
- * @param h binary function yielding m-vector
- * @param x1 first argument value
- * @param x2 n-dimensional second argument value
- * @param delta increment for numerical derivative
- * @return m*n Jacobian computed via central differencing
- * All classes Y,X1,X2 need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative22
- (boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- Y hx = h(x1,x2);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x2.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- inline Matrix numericalDerivative22
- (Y (*h)(const X1&, const X2&), const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative22(boost::bind(h, _1, _2), x1, x2, delta);
- }
-
- /** pseudo-partial template specialization for double return values */
- template
- Matrix numericalDerivative22(boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative22(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- template
- inline Matrix numericalDerivative22(double (*h)(const X1&, const X2&),
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative22(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- /** pseudo-partial template specialization for vector return values */
- template
- Matrix numericalDerivative22(boost::function h,
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative22(
- boost::bind(makeLieVector, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- template
- inline Matrix numericalDerivative22(Vector (*h)(const X1&, const X2&),
- const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalDerivative22(
- boost::bind(makeLieVector, boost::bind(h, _1, _2)), x1, x2, delta);
- }
-
- /**
- * Compute numerical derivative in argument 1 of ternary function
- * @param h ternary function yielding m-vector
- * @param x1 n-dimensional first argument value
- * @param x2 second argument value
- * @param x3 third argument value
- * @param delta increment for numerical derivative
- * @return m*n Jacobian computed via central differencing
- * All classes Y,X1,X2,X3 need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative31
- (boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5)
- {
- Y hx = h(x1,x2,x3);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x1.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- inline Matrix numericalDerivative31
- (Y (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative31(boost::bind(h, _1, _2, _3), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for double return values */
- template
- Matrix numericalDerivative31(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative31(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative31(double (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative31(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for vector return values */
- template
- Matrix numericalDerivative31(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative31(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative31(Vector (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative31(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /**
- * Compute numerical derivative in argument 2 of ternary function
- * @param h ternary function yielding m-vector
- * @param x1 n-dimensional first argument value
- * @param x2 second argument value
- * @param x3 third argument value
- * @param delta increment for numerical derivative
- * @return m*n Jacobian computed via central differencing
- * All classes Y,X1,X2,X3 need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative32
- (boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5)
- {
- Y hx = h(x1,x2,x3);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x2.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- inline Matrix numericalDerivative32
- (Y (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative32(boost::bind(h, _1, _2, _3), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for double return values */
- template
- Matrix numericalDerivative32(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative32(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative32(double (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative32(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for vector return values */
- template
- Matrix numericalDerivative32(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative32(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative32(Vector (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative32(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /**
- * Compute numerical derivative in argument 3 of ternary function
- * @param h ternary function yielding m-vector
- * @param x1 n-dimensional first argument value
- * @param x2 second argument value
- * @param x3 third argument value
- * @param delta increment for numerical derivative
- * @return m*n Jacobian computed via central differencing
- * All classes Y,X1,X2,X3 need dim, expmap, logmap
- */
- template
- Matrix numericalDerivative33
- (boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5)
- {
- Y hx = h(x1,x2,x3);
- double factor = 1.0/(2.0*delta);
- const size_t m = hx.dim(), n = x3.dim();
- Vector d = zero(n);
- Matrix H = zeros(m,n);
- for (size_t j=0;j
- inline Matrix numericalDerivative33
- (Y (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative33(boost::bind(h, _1, _2, _3), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for double return values */
- template
- Matrix numericalDerivative33(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative33(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative33(double (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative33(
- boost::bind(makeLieVectorD, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /** pseudo-partial template specialization for vector return values */
- template
- Matrix numericalDerivative33(boost::function h,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative33(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalDerivative33(Vector (*h)(const X1&, const X2&, const X3&),
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalDerivative33(
- boost::bind(makeLieVector, boost::bind(h, _1, _2, _3)), x1, x2, x3, delta);
- }
-
- /**
- * Compute numerical Hessian matrix. Requires a single-argument Lie->scalar
- * function. This is implemented simply as the derivative of the gradient.
- * @param f A function taking a Lie object as input and returning a scalar
- * @param x The center point for computing the Hessian
- * @param delta The numerical derivative step size
- * @return n*n Hessian matrix computed via central differencing
- */
- template
- inline Matrix numericalHessian(boost::function f, const X& x, double delta=1e-5) {
- return numericalDerivative11(boost::function(boost::bind(
- static_cast,const X&, double)>(&numericalGradient),
- f, _1, delta)), x, delta);
- }
-
- template
- inline Matrix numericalHessian(double (*f)(const X&), const X& x, double delta=1e-5) {
- return numericalHessian(boost::function(f), x, delta);
- }
-
-
- /** Helper class that computes the derivative of f w.r.t. x1, centered about
- * x1_, as a function of x2
- */
- template
- class G_x1 {
- const boost::function& f_;
- const X1& x1_;
- double delta_;
- public:
- G_x1(const boost::function& f, const X1& x1, double delta) : f_(f), x1_(x1), delta_(delta) {}
- Vector operator()(const X2& x2) {
- return numericalGradient(boost::function(boost::bind(f_, _1, x2)), x1_, delta_);
- }
- };
-
- template
- inline Matrix numericalHessian212(boost::function f, const X1& x1, const X2& x2, double delta=1e-5) {
- G_x1 g_x1(f, x1, delta);
- return numericalDerivative11(boost::function(boost::bind(boost::ref(g_x1), _1)), x2, delta);
- }
-
-
- template
- inline Matrix numericalHessian212(double (*f)(const X1&, const X2&), const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalHessian212(boost::function(f), x1, x2, delta);
- }
-
-
- template
- inline Matrix numericalHessian211(boost::function f, const X1& x1, const X2& x2, double delta=1e-5) {
-
- Vector (*numGrad)(boost::function, const X1&, double) = &numericalGradient;
- boost::function f2(boost::bind(f, _1, x2));
-
- return numericalDerivative11(boost::function(boost::bind(numGrad, f2, _1, delta)), x1, delta);
- }
-
-
- template
- inline Matrix numericalHessian211(double (*f)(const X1&, const X2&), const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalHessian211(boost::function(f), x1, x2, delta);
- }
-
-
- template
- inline Matrix numericalHessian222(boost::function f, const X1& x1, const X2& x2, double delta=1e-5) {
-
- Vector (*numGrad)(boost::function, const X2&, double) = &numericalGradient;
- boost::function f2(boost::bind(f, x1, _1));
-
- return numericalDerivative11(boost::function(boost::bind(numGrad, f2, _1, delta)), x2, delta);
- }
-
-
- template
- inline Matrix numericalHessian222(double (*f)(const X1&, const X2&), const X1& x1, const X2& x2, double delta=1e-5) {
- return numericalHessian222(boost::function(f), x1, x2, delta);
- }
-
- /**
- * Numerical Hessian for tenary functions
- */
- /* **************************************************************** */
- template
- inline Matrix numericalHessian311(boost::function f,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
-
- Vector (*numGrad)(boost::function, const X1&, double) = &numericalGradient;
- boost::function f2(boost::bind(f, _1, x2, x3));
-
- return numericalDerivative11(boost::function(boost::bind(numGrad, f2, _1, delta)), x1, delta);
- }
-
- template
- inline Matrix numericalHessian311(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian311(boost::function(f), x1, x2, x3, delta);
- }
-
- /* **************************************************************** */
- template
- inline Matrix numericalHessian322(boost::function f,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
-
- Vector (*numGrad)(boost::function, const X2&, double) = &numericalGradient;
- boost::function f2(boost::bind(f, x1, _1, x3));
-
- return numericalDerivative11(boost::function(boost::bind(numGrad, f2, _1, delta)), x2, delta);
- }
-
- template
- inline Matrix numericalHessian322(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian322(boost::function(f), x1, x2, x3, delta);
- }
-
- /* **************************************************************** */
- template
- inline Matrix numericalHessian333(boost::function f,
- const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
-
- Vector (*numGrad)(boost::function, const X3&, double) = &numericalGradient;
- boost::function f2(boost::bind(f, x1, x2, _1));
-
- return numericalDerivative11(boost::function(boost::bind(numGrad, f2, _1, delta)), x3, delta);
- }
-
- template
- inline Matrix numericalHessian333(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian333(boost::function(f), x1, x2, x3, delta);
- }
-
- /* **************************************************************** */
- template
- inline Matrix numericalHessian312(boost::function f, const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian212(boost::function(boost::bind(f, _1, _2, x3)), x1, x2, delta );
- }
-
- template
- inline Matrix numericalHessian313(boost::function f, const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian212(boost::function(boost::bind(f, _1, x2, _2)), x1, x3, delta );
- }
-
- template
- inline Matrix numericalHessian323(boost::function f, const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian212(boost::function(boost::bind(f, x1, _1, _2)), x2, x3, delta );
- }
-
- /* **************************************************************** */
- template
- inline Matrix numericalHessian312(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian312(boost::function(f), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalHessian313(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian313(boost::function(f), x1, x2, x3, delta);
- }
-
- template
- inline Matrix numericalHessian323(double (*f)(const X1&, const X2&, const X3&), const X1& x1, const X2& x2, const X3& x3, double delta=1e-5) {
- return numericalHessian323(boost::function(f), x1, x2, x3, delta);
+ // get chart at x
+ ChartX chartX(x);
+
+ // Prepare a tangent vector to perturb x with, only works for fixed size
+ TangentX d;
+ d.setZero();
+
+ Vector g = zero(N); // Can be fixed size
+ for (int j = 0; j < N; j++) {
+ d(j) = delta;
+ double hxplus = h(chartX.retract(d));
+ d(j) = -delta;
+ double hxmin = h(chartX.retract(d));
+ d(j) = 0;
+ g(j) = (hxplus - hxmin) * factor;
}
+ return g;
+}
+
+/**
+ * @brief New-style numerical derivatives using manifold_traits
+ * @brief Computes numerical derivative in argument 1 of unary function
+ * @param h unary function yielding m-vector
+ * @param x n-dimensional value at which to evaluate h
+ * @param delta increment for numerical derivative
+ * Class Y is the output argument
+ * Class X is the input argument
+ * @return m*n Jacobian computed via central differencing
+ */
+template
+// TODO Should compute fixed-size matrix
+Matrix numericalDerivative11(boost::function h, const X& x,
+ double delta = 1e-5) {
+ using namespace traits;
+
+ BOOST_STATIC_ASSERT_MSG(traits::is_manifold::value,
+ "Template argument Y must be a manifold type.");
+ typedef DefaultChart