blob: 5442ec89b526218c423b8b4d1aba3f1d3f527619 [file] [log] [blame]
Austin Schuha647d602018-02-18 14:05:15 -08001#ifndef FRC971_CONTROL_LOOPS_JACOBIAN_H_
2#define FRC971_CONTROL_LOOPS_JACOBIAN_H_
3
4#include <Eigen/Dense>
5
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08006namespace frc971::control_loops {
Austin Schuha647d602018-02-18 14:05:15 -08007
8template <int num_states, int num_inputs, typename F>
9::Eigen::Matrix<double, num_states, num_inputs> NumericalJacobian(
10 const F &fn, ::Eigen::Matrix<double, num_inputs, 1> input) {
Austin Schuhcb091712018-02-21 20:01:55 -080011 constexpr double kEpsilon = 1e-5;
Austin Schuha647d602018-02-18 14:05:15 -080012 ::Eigen::Matrix<double, num_states, num_inputs> result =
13 ::Eigen::Matrix<double, num_states, num_inputs>::Zero();
14
15 // It's more expensive, but +- epsilon will be more accurate
16 for (int i = 0; i < num_inputs; ++i) {
17 ::Eigen::Matrix<double, num_inputs, 1> dX_plus = input;
18 dX_plus(i, 0) += kEpsilon;
19 ::Eigen::Matrix<double, num_inputs, 1> dX_minus = input;
20 dX_minus(i, 0) -= kEpsilon;
21 result.col(i) = (fn(dX_plus) - fn(dX_minus)) / (kEpsilon * 2.0);
22 }
23 return result;
24}
25
26// Implements a numerical jacobian with respect to X for f(X, U, ...).
27template <int num_states, int num_u, typename F, typename... Args>
28::Eigen::Matrix<double, num_states, num_states> NumericalJacobianX(
29 const F &fn, ::Eigen::Matrix<double, num_states, 1> X,
Philipp Schrader790cb542023-07-05 21:06:52 -070030 ::Eigen::Matrix<double, num_u, 1> U, Args &&...args) {
Austin Schuha647d602018-02-18 14:05:15 -080031 return NumericalJacobian<num_states, num_states>(
32 [&](::Eigen::Matrix<double, num_states, 1> X) {
33 return fn(X, U, args...);
34 },
35 X);
36}
37
38// Implements a numerical jacobian with respect to U for f(X, U, ...).
39template <int num_states, int num_u, typename F, typename... Args>
40::Eigen::Matrix<double, num_states, num_u> NumericalJacobianU(
41 const F &fn, ::Eigen::Matrix<double, num_states, 1> X,
Philipp Schrader790cb542023-07-05 21:06:52 -070042 ::Eigen::Matrix<double, num_u, 1> U, Args &&...args) {
Austin Schuha647d602018-02-18 14:05:15 -080043 return NumericalJacobian<num_states, num_u>(
44 [&](::Eigen::Matrix<double, num_u, 1> U) { return fn(X, U, args...); },
45 U);
46}
47
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080048} // namespace frc971::control_loops
Austin Schuha647d602018-02-18 14:05:15 -080049
50#endif // FRC971_CONTROL_LOOPS_JACOBIAN_H_