diff --git a/src/shared/algorithms/ADA/ADA.h b/src/shared/algorithms/ADA/ADA.h index 26072b16ac3b9c09196a9993ca1dcc332f98917a..0aca225ab05894afec14c3736eca708e55e65515 100644 --- a/src/shared/algorithms/ADA/ADA.h +++ b/src/shared/algorithms/ADA/ADA.h @@ -33,7 +33,7 @@ namespace Boardcore class ADA { public: - using KalmanFilter = Kalman<float, 3, 1>; + using KalmanFilter = Kalman<float, 3, 1, 1>; explicit ADA(const KalmanFilter::KalmanConfig kalmanConfig); diff --git a/src/shared/algorithms/Kalman/Kalman.h b/src/shared/algorithms/Kalman/Kalman.h index 8673baf8eaa5de97e29bc29511fb9430408d7292..3f7d4e76f4d4d0a2411725d114e3f79404288ce2 100644 --- a/src/shared/algorithms/Kalman/Kalman.h +++ b/src/shared/algorithms/Kalman/Kalman.h @@ -32,8 +32,12 @@ namespace Boardcore * * This class uses templates in order to know the size of each matrix at * compile-time. This way we avoid Eigen to allocate memory dynamically. + * + * N_size: number of states + * P_size: number of measurements + * M_size: number of control inputs (optional) */ -template <typename T, int N_size, int P_size> +template <typename T, int N_size, int P_size, int M_size> class Kalman { public: @@ -41,8 +45,10 @@ public: using MatrixPN = Eigen::Matrix<T, P_size, N_size>; using MatrixNP = Eigen::Matrix<T, N_size, P_size>; using MatrixPP = Eigen::Matrix<T, P_size, P_size>; + using MatrixNM = Eigen::Matrix<T, N_size, M_size>; using CVectorN = Eigen::Vector<T, N_size>; using CVectorP = Eigen::Vector<T, P_size>; + using CVectorM = Eigen::Vector<T, M_size>; /** * @brief Configuration struct for the Kalman class. @@ -54,6 +60,7 @@ public: MatrixNN Q; MatrixPP R; MatrixNN P; + MatrixNM G; CVectorN x; }; @@ -64,8 +71,8 @@ public: */ Kalman(const KalmanConfig& config) : F(config.F), H(config.H), Q(config.Q), R(config.R), P(config.P), - S(MatrixPP::Zero(P_size, P_size)), K(MatrixNP::Zero(N_size, P_size)), - x(config.x) + G(config.G), S(MatrixPP::Zero(P_size, P_size)), + K(MatrixNP::Zero(N_size, P_size)), x(config.x) { I.setIdentity(); } @@ -84,10 +91,12 @@ public: /** * @brief Prediction step with previous F matrix. + * + * @param input Control inputs for the step (optional). */ - void predict() + void predict(const CVectorM& input = CVectorM::Zero()) { - x = F * x; + x = F * x + G * input; P = F * P * F.transpose() + Q; } @@ -95,11 +104,13 @@ public: * @brief Prediction step. * * @param F_new updated F matrix. + * @param input Control inputs for the step (optional). */ - void predict(const MatrixNN& F_new) + void predict(const MatrixNN& F_new, + const CVectorM& input = CVectorM::Zero()) { F = F_new; - predict(); + predict(input); } /** @@ -169,6 +180,7 @@ private: MatrixNN Q; /**< Model variance matrix (n x n) */ MatrixPP R; /**< Measurement variance (p x p) */ MatrixNN P; /**< Error covariance matrix (n x n) */ + MatrixNM G; /**< Input matrix (n x m) */ MatrixPP S; MatrixNP K; /**< kalman gain */ diff --git a/src/tests/algorithms/ADA/test-ada.cpp b/src/tests/algorithms/ADA/test-ada.cpp index 646604c672fe1a756e3c465bb1df550650289540..bc268e1334a90ddad6649f22dd34b4d9536efc3e 100644 --- a/src/tests/algorithms/ADA/test-ada.cpp +++ b/src/tests/algorithms/ADA/test-ada.cpp @@ -71,12 +71,14 @@ ADA::KalmanFilter::KalmanConfig getADAKalmanConfig() // cppcheck-suppress constStatement Q_INIT << 30.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 2.5f; ADA::KalmanFilter::MatrixPP R_INIT{4000.0f}; + ADA::KalmanFilter::MatrixNM G_INIT = ADA::KalmanFilter::MatrixNM::Zero(); return {F_INIT, H_INIT, Q_INIT, R_INIT, P_INIT, + G_INIT, ADA::KalmanFilter::CVectorN(DEFAULT_REFERENCE_PRESSURE, 0, KALMAN_INITIAL_ACCELERATION)}; } diff --git a/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp b/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp index 52ca7e81c5ea91644604209d62d87c177f02ca6f..34ff301cbd78174057da5de8a30dec3173c288a8 100644 --- a/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp +++ b/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp @@ -45,6 +45,7 @@ int main() const int n = 3; const int p = 1; + const int m = 1; Matrix<float, n, n> F = (Matrix<float, n, n>(n, n) << 1, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) @@ -67,15 +68,18 @@ int main() Matrix<float, p, 1> y(p); // vector with p elements (only one in this case) - Kalman<float, n, p>::KalmanConfig config; + Matrix<float, n, m> G = Matrix<float, n, m>::Zero(); + + Kalman<float, n, p, m>::KalmanConfig config; config.F = F; config.H = H; config.Q = Q; config.R = R; config.P = P; + config.G = G; config.x = x0; - Kalman<float, n, p> filter(config); + Kalman<float, n, p, m> filter(config); float lastTime = 0.0; // Variable to save the time of the last sample diff --git a/src/tests/catch/test-kalman.cpp b/src/tests/catch/test-kalman.cpp index 71974bebedf31ff6790e7cc7104c9c76b5fd2538..80f7959cf52ddd02acc9763cca1b510a36b18a0b 100644 --- a/src/tests/catch/test-kalman.cpp +++ b/src/tests/catch/test-kalman.cpp @@ -38,6 +38,8 @@ using namespace Eigen; static const uint8_t STATES_DIM = 3; static const uint8_t OUTPUTS_DIM = 1; +static const uint8_t INPUTS_DIM = + 1; // Actually zero, but we can't use 0 in the template static const Matrix<float, STATES_DIM, STATES_DIM> F = (Matrix<float, STATES_DIM, STATES_DIM>(STATES_DIM, STATES_DIM) << 1, 0.2, @@ -61,15 +63,19 @@ static const Matrix<float, OUTPUTS_DIM, OUTPUTS_DIM> R{10}; // State vector static const Matrix<float, STATES_DIM, 1> x0(INPUT[0], 0.0, 0.0); -static const Kalman<float, STATES_DIM, OUTPUTS_DIM>::KalmanConfig +static const Matrix<float, STATES_DIM, INPUTS_DIM> G = + Matrix<float, STATES_DIM, INPUTS_DIM>::Zero(); + +static const Kalman<float, STATES_DIM, OUTPUTS_DIM, INPUTS_DIM>::KalmanConfig getKalmanConfig() { - Kalman<float, STATES_DIM, OUTPUTS_DIM>::KalmanConfig config; + Kalman<float, STATES_DIM, OUTPUTS_DIM, INPUTS_DIM>::KalmanConfig config; config.F = F; config.H = H; config.Q = Q; config.R = R; config.P = P; + config.G = G; config.x = x0; return config; @@ -77,7 +83,8 @@ getKalmanConfig() TEST_CASE("Update test") { - Kalman<float, STATES_DIM, OUTPUTS_DIM> filter(getKalmanConfig()); + Kalman<float, STATES_DIM, OUTPUTS_DIM, INPUTS_DIM> filter( + getKalmanConfig()); Matrix<float, OUTPUTS_DIM, 1> y{}; float lastTime = TIME[0];