Skip to content

Commit dc00a13

Browse files
authored
[wpimath] Make cost and covariance matrix functions constexpr (#6444)
1 parent bdc7344 commit dc00a13

File tree

2 files changed

+61
-30
lines changed

2 files changed

+61
-30
lines changed

wpimath/src/main/native/include/frc/StateSpaceUtil.h

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,28 @@ namespace frc {
3434
* @return State excursion or control effort cost matrix.
3535
*/
3636
template <std::same_as<double>... Ts>
37-
Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCostMatrix(Ts... tolerances) {
38-
Eigen::DiagonalMatrix<double, sizeof...(Ts)> result;
39-
auto& diag = result.diagonal();
37+
constexpr Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCostMatrix(
38+
Ts... tolerances) {
39+
Matrixd<sizeof...(Ts), sizeof...(Ts)> result;
40+
41+
for (int row = 0; row < result.rows(); ++row) {
42+
for (int col = 0; col < result.cols(); ++col) {
43+
if (row != col) {
44+
result.coeffRef(row, col) = 0.0;
45+
}
46+
}
47+
}
48+
4049
wpi::for_each(
4150
[&](int i, double tolerance) {
4251
if (tolerance == std::numeric_limits<double>::infinity()) {
43-
diag(i) = 0.0;
52+
result.coeffRef(i, i) = 0.0;
4453
} else {
45-
diag(i) = 1.0 / std::pow(tolerance, 2);
54+
result.coeffRef(i, i) = 1.0 / (tolerance * tolerance);
4655
}
4756
},
4857
tolerances...);
58+
4959
return result;
5060
}
5161

@@ -62,11 +72,21 @@ Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCostMatrix(Ts... tolerances) {
6272
* @return Process noise or measurement noise covariance matrix.
6373
*/
6474
template <std::same_as<double>... Ts>
65-
Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCovMatrix(Ts... stdDevs) {
66-
Eigen::DiagonalMatrix<double, sizeof...(Ts)> result;
67-
auto& diag = result.diagonal();
68-
wpi::for_each([&](int i, double stdDev) { diag(i) = std::pow(stdDev, 2); },
69-
stdDevs...);
75+
constexpr Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCovMatrix(Ts... stdDevs) {
76+
Matrixd<sizeof...(Ts), sizeof...(Ts)> result;
77+
78+
for (int row = 0; row < result.rows(); ++row) {
79+
for (int col = 0; col < result.cols(); ++col) {
80+
if (row != col) {
81+
result.coeffRef(row, col) = 0.0;
82+
}
83+
}
84+
}
85+
86+
wpi::for_each(
87+
[&](int i, double stdDev) { result.coeffRef(i, i) = stdDev * stdDev; },
88+
stdDevs...);
89+
7090
return result;
7191
}
7292

@@ -84,16 +104,23 @@ Matrixd<sizeof...(Ts), sizeof...(Ts)> MakeCovMatrix(Ts... stdDevs) {
84104
* @return State excursion or control effort cost matrix.
85105
*/
86106
template <size_t N>
87-
Matrixd<N, N> MakeCostMatrix(const std::array<double, N>& costs) {
88-
Eigen::DiagonalMatrix<double, N> result;
89-
auto& diag = result.diagonal();
90-
for (size_t i = 0; i < costs.size(); ++i) {
91-
if (costs[i] == std::numeric_limits<double>::infinity()) {
92-
diag(i) = 0.0;
93-
} else {
94-
diag(i) = 1.0 / std::pow(costs[i], 2);
107+
constexpr Matrixd<N, N> MakeCostMatrix(const std::array<double, N>& costs) {
108+
Matrixd<N, N> result;
109+
110+
for (int row = 0; row < result.rows(); ++row) {
111+
for (int col = 0; col < result.cols(); ++col) {
112+
if (row == col) {
113+
if (costs[row] == std::numeric_limits<double>::infinity()) {
114+
result.coeffRef(row, col) = 0.0;
115+
} else {
116+
result.coeffRef(row, col) = 1.0 / (costs[row] * costs[row]);
117+
}
118+
} else {
119+
result.coeffRef(row, col) = 0.0;
120+
}
95121
}
96122
}
123+
97124
return result;
98125
}
99126

@@ -110,12 +137,19 @@ Matrixd<N, N> MakeCostMatrix(const std::array<double, N>& costs) {
110137
* @return Process noise or measurement noise covariance matrix.
111138
*/
112139
template <size_t N>
113-
Matrixd<N, N> MakeCovMatrix(const std::array<double, N>& stdDevs) {
114-
Eigen::DiagonalMatrix<double, N> result;
115-
auto& diag = result.diagonal();
116-
for (size_t i = 0; i < N; ++i) {
117-
diag(i) = std::pow(stdDevs[i], 2);
140+
constexpr Matrixd<N, N> MakeCovMatrix(const std::array<double, N>& stdDevs) {
141+
Matrixd<N, N> result;
142+
143+
for (int row = 0; row < result.rows(); ++row) {
144+
for (int col = 0; col < result.cols(); ++col) {
145+
if (row == col) {
146+
result.coeffRef(row, col) = stdDevs[row] * stdDevs[row];
147+
} else {
148+
result.coeffRef(row, col) = 0.0;
149+
}
150+
}
118151
}
152+
119153
return result;
120154
}
121155

wpimath/src/test/native/cpp/StateSpaceUtilTest.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22
// Open Source Software; you can modify and/or share it under the terms of
33
// the WPILib BSD license file in the root directory of this project.
44

5-
#include <array>
6-
75
#include <gtest/gtest.h>
86

97
#include "frc/EigenCore.h"
108
#include "frc/StateSpaceUtil.h"
11-
#include "frc/system/NumericalIntegration.h"
129

1310
TEST(StateSpaceUtilTest, CostParameterPack) {
14-
frc::Matrixd<3, 3> mat = frc::MakeCostMatrix(1.0, 2.0, 3.0);
11+
constexpr frc::Matrixd<3, 3> mat = frc::MakeCostMatrix(1.0, 2.0, 3.0);
1512
EXPECT_NEAR(mat(0, 0), 1.0, 1e-3);
1613
EXPECT_NEAR(mat(0, 1), 0.0, 1e-3);
1714
EXPECT_NEAR(mat(0, 2), 0.0, 1e-3);
@@ -24,7 +21,7 @@ TEST(StateSpaceUtilTest, CostParameterPack) {
2421
}
2522

2623
TEST(StateSpaceUtilTest, CostArray) {
27-
frc::Matrixd<3, 3> mat = frc::MakeCostMatrix<3>({1.0, 2.0, 3.0});
24+
constexpr frc::Matrixd<3, 3> mat = frc::MakeCostMatrix<3>({1.0, 2.0, 3.0});
2825
EXPECT_NEAR(mat(0, 0), 1.0, 1e-3);
2926
EXPECT_NEAR(mat(0, 1), 0.0, 1e-3);
3027
EXPECT_NEAR(mat(0, 2), 0.0, 1e-3);
@@ -37,7 +34,7 @@ TEST(StateSpaceUtilTest, CostArray) {
3734
}
3835

3936
TEST(StateSpaceUtilTest, CovParameterPack) {
40-
frc::Matrixd<3, 3> mat = frc::MakeCovMatrix(1.0, 2.0, 3.0);
37+
constexpr frc::Matrixd<3, 3> mat = frc::MakeCovMatrix(1.0, 2.0, 3.0);
4138
EXPECT_NEAR(mat(0, 0), 1.0, 1e-3);
4239
EXPECT_NEAR(mat(0, 1), 0.0, 1e-3);
4340
EXPECT_NEAR(mat(0, 2), 0.0, 1e-3);
@@ -50,7 +47,7 @@ TEST(StateSpaceUtilTest, CovParameterPack) {
5047
}
5148

5249
TEST(StateSpaceUtilTest, CovArray) {
53-
frc::Matrixd<3, 3> mat = frc::MakeCovMatrix<3>({1.0, 2.0, 3.0});
50+
constexpr frc::Matrixd<3, 3> mat = frc::MakeCovMatrix<3>({1.0, 2.0, 3.0});
5451
EXPECT_NEAR(mat(0, 0), 1.0, 1e-3);
5552
EXPECT_NEAR(mat(0, 1), 0.0, 1e-3);
5653
EXPECT_NEAR(mat(0, 2), 0.0, 1e-3);

0 commit comments

Comments
 (0)