diff --git a/wpimath/src/main/java/edu/wpi/first/math/estimator/ExtendedKalmanFilter.java b/wpimath/src/main/java/edu/wpi/first/math/estimator/ExtendedKalmanFilter.java index 055bf9939a..fa8f9245e9 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/estimator/ExtendedKalmanFilter.java +++ b/wpimath/src/main/java/edu/wpi/first/math/estimator/ExtendedKalmanFilter.java @@ -372,7 +372,11 @@ public class ExtendedKalmanFilter K = S.transpose().solve(C.times(m_P.transpose())).transpose(); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + final Matrix K = S.solve(C.times(m_P)).transpose(); // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − h(x̂ₖ₊₁⁻, uₖ₊₁)) m_xHat = addFuncX.apply(m_xHat, K.times(residualFuncY.apply(y, h.apply(m_xHat, u)))); diff --git a/wpimath/src/main/java/edu/wpi/first/math/estimator/KalmanFilter.java b/wpimath/src/main/java/edu/wpi/first/math/estimator/KalmanFilter.java index 40e6c96c7a..2d76cabfee 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/estimator/KalmanFilter.java +++ b/wpimath/src/main/java/edu/wpi/first/math/estimator/KalmanFilter.java @@ -230,7 +230,11 @@ public class KalmanFilter K = S.transpose().solve(C.times(m_P.transpose())).transpose(); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + final Matrix K = S.solve(C.times(m_P)).transpose(); // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) m_xHat = m_xHat.plus(K.times(y.minus(C.times(m_xHat).plus(D.times(u))))); diff --git a/wpimath/src/main/java/edu/wpi/first/math/estimator/SteadyStateKalmanFilter.java b/wpimath/src/main/java/edu/wpi/first/math/estimator/SteadyStateKalmanFilter.java index 31649728e2..4b5ca7bc65 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/estimator/SteadyStateKalmanFilter.java +++ b/wpimath/src/main/java/edu/wpi/first/math/estimator/SteadyStateKalmanFilter.java @@ -100,9 +100,11 @@ public class SteadyStateKalmanFilter( - S.transpose().getStorage().solve(C.times(P.transpose()).getStorage()).transpose()); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + m_K = new Matrix<>(S.getStorage().solve(C.times(P).getStorage()).transpose()); reset(); } diff --git a/wpimath/src/main/native/include/frc/DARE.h b/wpimath/src/main/native/include/frc/DARE.h index fba06ccb0a..feca99a1fd 100644 --- a/wpimath/src/main/native/include/frc/DARE.h +++ b/wpimath/src/main/native/include/frc/DARE.h @@ -128,7 +128,11 @@ Eigen::Matrix DARE( // // V₂ᵀ = W.solve(Gₖᵀ) // V₂ = W.solve(Gₖᵀ)ᵀ - StateMatrix V_2 = W_solver.solve(G_k.transpose()).transpose(); + // + // Since W, Gₖ, and Hₖ are symmetric, drop the transposes on Gₖ and V₂. + // + // V₂ = W.solve(Gₖ) + StateMatrix V_2 = W_solver.solve(G_k); // Gₖ₊₁ = Gₖ + AₖV₂Aₖᵀ // Hₖ₊₁ = Hₖ + V₁ᵀHₖAₖ diff --git a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h index ccf8f935c4..22eddbc281 100644 --- a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h @@ -397,8 +397,11 @@ class ExtendedKalmanFilter { // // Kᵀ = Sᵀ.solve(CPᵀ) // K = (Sᵀ.solve(CPᵀ))ᵀ - Matrixd K = - S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + Matrixd K = S.ldlt().solve(C * m_P).transpose(); // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + Kₖ₊₁(y − h(x̂ₖ₊₁⁻, uₖ₊₁)) m_xHat = addFuncX(m_xHat, K * residualFuncY(y, h(m_xHat, u))); diff --git a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h index 5f52c810ac..aa169368bb 100644 --- a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h @@ -235,8 +235,11 @@ class KalmanFilter { // // Kᵀ = Sᵀ.solve(CPᵀ) // K = (Sᵀ.solve(CPᵀ))ᵀ - Matrixd K = - S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + Matrixd K = S.ldlt().solve(C * m_P).transpose(); // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) m_xHat += K * (y - (C * m_xHat + D * u)); diff --git a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h index a705de92bf..734c70c7e0 100644 --- a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h @@ -114,7 +114,11 @@ class SteadyStateKalmanFilter { // // Kᵀ = Sᵀ.solve(CPᵀ) // K = (Sᵀ.solve(CPᵀ))ᵀ - m_K = S.transpose().ldlt().solve(C * P.value().transpose()).transpose(); + // + // Drop the transposes on symmetric matrices S and P. + // + // K = (S.solve(CP))ᵀ + m_K = S.ldlt().solve(C * P.value()).transpose(); } else if (P.error() == DAREError::QNotSymmetric || P.error() == DAREError::QNotPositiveSemidefinite) { std::string msg =