Template jacobian.h on Scalar type
This makes it so that we can run numerical Jacobian calculations on
single-precision floats when we want to.
Change-Id: If45ea95366a772883872321c99c14acc8eec7eca
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/frc971/control_loops/jacobian.h b/frc971/control_loops/jacobian.h
index 5442ec8..e82c668 100644
--- a/frc971/control_loops/jacobian.h
+++ b/frc971/control_loops/jacobian.h
@@ -5,18 +5,18 @@
namespace frc971::control_loops {
-template <int num_states, int num_inputs, typename F>
-::Eigen::Matrix<double, num_states, num_inputs> NumericalJacobian(
- const F &fn, ::Eigen::Matrix<double, num_inputs, 1> input) {
- constexpr double kEpsilon = 1e-5;
- ::Eigen::Matrix<double, num_states, num_inputs> result =
- ::Eigen::Matrix<double, num_states, num_inputs>::Zero();
+template <int num_states, int num_inputs, typename Scalar, typename F>
+::Eigen::Matrix<Scalar, num_states, num_inputs> NumericalJacobian(
+ const F &fn, ::Eigen::Matrix<Scalar, num_inputs, 1> input) {
+ constexpr Scalar kEpsilon = 1e-5;
+ ::Eigen::Matrix<Scalar, num_states, num_inputs> result =
+ ::Eigen::Matrix<Scalar, num_states, num_inputs>::Zero();
// It's more expensive, but +- epsilon will be more accurate
for (int i = 0; i < num_inputs; ++i) {
- ::Eigen::Matrix<double, num_inputs, 1> dX_plus = input;
+ ::Eigen::Matrix<Scalar, num_inputs, 1> dX_plus = input;
dX_plus(i, 0) += kEpsilon;
- ::Eigen::Matrix<double, num_inputs, 1> dX_minus = input;
+ ::Eigen::Matrix<Scalar, num_inputs, 1> dX_minus = input;
dX_minus(i, 0) -= kEpsilon;
result.col(i) = (fn(dX_plus) - fn(dX_minus)) / (kEpsilon * 2.0);
}
@@ -24,24 +24,26 @@
}
// Implements a numerical jacobian with respect to X for f(X, U, ...).
-template <int num_states, int num_u, typename F, typename... Args>
-::Eigen::Matrix<double, num_states, num_states> NumericalJacobianX(
- const F &fn, ::Eigen::Matrix<double, num_states, 1> X,
- ::Eigen::Matrix<double, num_u, 1> U, Args &&...args) {
+template <int num_states, int num_u, typename Scalar, typename F,
+ typename... Args>
+::Eigen::Matrix<Scalar, num_states, num_states> NumericalJacobianX(
+ const F &fn, ::Eigen::Matrix<Scalar, num_states, 1> X,
+ ::Eigen::Matrix<Scalar, num_u, 1> U, Args &&...args) {
return NumericalJacobian<num_states, num_states>(
- [&](::Eigen::Matrix<double, num_states, 1> X) {
+ [&](::Eigen::Matrix<Scalar, num_states, 1> X) {
return fn(X, U, args...);
},
X);
}
// Implements a numerical jacobian with respect to U for f(X, U, ...).
-template <int num_states, int num_u, typename F, typename... Args>
-::Eigen::Matrix<double, num_states, num_u> NumericalJacobianU(
- const F &fn, ::Eigen::Matrix<double, num_states, 1> X,
- ::Eigen::Matrix<double, num_u, 1> U, Args &&...args) {
+template <int num_states, int num_u, typename Scalar, typename F,
+ typename... Args>
+::Eigen::Matrix<Scalar, num_states, num_u> NumericalJacobianU(
+ const F &fn, ::Eigen::Matrix<Scalar, num_states, 1> X,
+ ::Eigen::Matrix<Scalar, num_u, 1> U, Args &&...args) {
return NumericalJacobian<num_states, num_u>(
- [&](::Eigen::Matrix<double, num_u, 1> U) { return fn(X, U, args...); },
+ [&](::Eigen::Matrix<Scalar, num_u, 1> U) { return fn(X, U, args...); },
U);
}