blob: acdee9fed719e48f71143dd04f017108d28c5d3a [file] [log] [blame]
Lee Mracek65686142020-01-10 22:21:39 -05001#include "frc971/control_loops/coerce_goal.h"
2
3#include <unistd.h>
4
James Kuszmaul61750662021-06-21 21:32:33 -07005#include "frc971/control_loops/polytope.h"
Lee Mracek65686142020-01-10 22:21:39 -05006#include "gtest/gtest.h"
7
8namespace frc971 {
9namespace control_loops {
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080010
Lee Mracek65686142020-01-10 22:21:39 -050011namespace {
12
James Kuszmaul61750662021-06-21 21:32:33 -070013frc971::controls::HVPolytope<2, 4, 4> MakeBox(double x1_min, double x1_max,
14 double x2_min, double x2_max) {
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080015 Eigen::Matrix<double, 4, 2> box_H;
16 box_H << /*[[*/ 1.0, 0.0 /*]*/,
17 /*[*/ -1.0, 0.0 /*]*/,
18 /*[*/ 0.0, 1.0 /*]*/,
19 /*[*/ 0.0, -1.0 /*]]*/;
20 Eigen::Matrix<double, 4, 1> box_k;
21 box_k << /*[[*/ x1_max /*]*/,
22 /*[*/ -x1_min /*]*/,
23 /*[*/ x2_max /*]*/,
24 /*[*/ -x2_min /*]]*/;
James Kuszmaul61750662021-06-21 21:32:33 -070025 frc971::controls::HPolytope<2> t_poly(box_H, box_k);
26 return frc971::controls::HVPolytope<2, 4, 4>(t_poly.H(), t_poly.k(),
27 t_poly.Vertices());
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080028}
29} // namespace
30
31class CoerceGoalTest : public ::testing::Test {
32 public:
James Kuszmaul61750662021-06-21 21:32:33 -070033 void SetUp() override { frc971::controls::HPolytope<2>::Init(); }
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080034 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
35};
36
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080037TEST_F(CoerceGoalTest, Inside) {
James Kuszmaul61750662021-06-21 21:32:33 -070038 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080039
40 Eigen::Matrix<double, 1, 2> K;
41 K << /*[[*/ 1, -1 /*]]*/;
42
43 Eigen::Matrix<double, 2, 1> R;
44 R << /*[[*/ 1.5, 1.5 /*]]*/;
45
46 Eigen::Matrix<double, 2, 1> output =
47 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
48
49 EXPECT_EQ(R(0, 0), output(0, 0));
50 EXPECT_EQ(R(1, 0), output(1, 0));
Lee Mracek65686142020-01-10 22:21:39 -050051}
52
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080053TEST_F(CoerceGoalTest, LineOutside) {
James Kuszmaul61750662021-06-21 21:32:33 -070054 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080055
56 // Make a line equivalent to y = -x, which does not pass through the box and
57 // is nearest the box at (1, 1).
58 Eigen::Matrix<double, 1, 2> K;
59 K << 1, 1;
60
61 Eigen::Matrix<double, 2, 1> R;
62 R << /*[[*/ 0.0, 0.0 /*]]*/;
63
64 Eigen::Matrix<double, 2, 1> output =
65 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
66
67 EXPECT_EQ(1.0, output(0, 0));
68 EXPECT_EQ(1.0, output(1, 0));
69
70 // Test the same line, but on the other side of the box, where the (2, 2)
71 // vertex will be closest.
72 output = frc971::control_loops::CoerceGoal<double>(box, K, 5, R);
73 EXPECT_EQ(2.0, output(0, 0));
74 EXPECT_EQ(2.0, output(1, 0));
75}
76
77TEST_F(CoerceGoalTest, GoalOutsideLineInsideThroughOrigin) {
James Kuszmaul61750662021-06-21 21:32:33 -070078 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080079
80 Eigen::Matrix<double, 1, 2> K;
81 K << 1, -1;
82
83 Eigen::Matrix<double, 2, 1> R;
84 R << 5, 5;
85
86 Eigen::Matrix<double, 2, 1> output =
87 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
88
89 EXPECT_EQ(2.0, output(0, 0));
90 EXPECT_EQ(2.0, output(1, 0));
91}
92
93TEST_F(CoerceGoalTest, GoalOutsideLineNotThroughOrigin) {
James Kuszmaul61750662021-06-21 21:32:33 -070094 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -080095
96 Eigen::Matrix<double, 1, 2> K;
97 K << 1, 1;
98
99 Eigen::Matrix<double, 2, 1> R;
100 R << 0, 3;
101
102 Eigen::Matrix<double, 2, 1> output =
103 frc971::control_loops::CoerceGoal<double>(box, K, 3, R);
104
105 EXPECT_EQ(1.0, output(0, 0));
106 EXPECT_DOUBLE_EQ(2.0, output(1, 0));
107}
108
109TEST_F(CoerceGoalTest, GoalOutsideLineThroughVertex) {
James Kuszmaul61750662021-06-21 21:32:33 -0700110 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800111
112 Eigen::Matrix<double, 1, 2> K;
113 K << 1, -1;
114
115 Eigen::Matrix<double, 2, 1> R;
116 R << 5, 5;
117
118 Eigen::Matrix<double, 2, 1> output =
119 frc971::control_loops::CoerceGoal<double>(box, K, 1, R);
120
121 EXPECT_EQ(2.0, output(0, 0));
122 EXPECT_EQ(1.0, output(1, 0));
123}
124
125TEST_F(CoerceGoalTest, LineAndGoalOutside) {
James Kuszmaul61750662021-06-21 21:32:33 -0700126 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(3, 4, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800127
128 Eigen::Matrix<double, 1, 2> K;
129 K << 1, -1;
130
131 Eigen::Matrix<double, 2, 1> R;
132 R << 5, 5;
133
134 Eigen::Matrix<double, 2, 1> output =
135 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
136
137 EXPECT_EQ(3.0, output(0, 0));
138 EXPECT_EQ(2.0, output(1, 0));
139}
140
141TEST_F(CoerceGoalTest, LineThroughEdgeOfBox) {
James Kuszmaul61750662021-06-21 21:32:33 -0700142 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(0, 4, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800143
144 Eigen::Matrix<double, 1, 2> K;
145 K << -1, 1;
146
147 Eigen::Matrix<double, 2, 1> R;
148 R << 5, 5;
149
150 Eigen::Matrix<double, 2, 1> output =
151 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
152
153 EXPECT_EQ(2.0, output(0, 0));
154 EXPECT_EQ(2.0, output(1, 0));
155}
156
157TEST_F(CoerceGoalTest, PerpendicularLine) {
James Kuszmaul61750662021-06-21 21:32:33 -0700158 frc971::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800159
160 Eigen::Matrix<double, 1, 2> K;
161 K << 1, 1;
162
163 Eigen::Matrix<double, 2, 1> R;
164 R << 5, 5;
165
166 Eigen::Matrix<double, 2, 1> output =
167 frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
168
169 EXPECT_EQ(1.0, output(0, 0));
170 EXPECT_EQ(1.0, output(1, 0));
171}
172
173TEST_F(CoerceGoalTest, WithinRegion) {
174 const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
Lee Mracek65686142020-01-10 22:21:39 -0500175 Eigen::Matrix<double, 1, 2> k;
176 k << 2, 2;
177
178 Eigen::Matrix<double, 2, 1> goal;
179 goal << -2, 2;
180
181 auto result = CoerceGoal<double>(upoly, k, 0, goal);
182
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800183 EXPECT_EQ(result(0, 0), goal(0, 0));
184 EXPECT_EQ(result(1, 0), goal(1, 0));
Lee Mracek65686142020-01-10 22:21:39 -0500185}
186
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800187TEST_F(CoerceGoalTest, VerticalLine) {
188 const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
Lee Mracek65686142020-01-10 22:21:39 -0500189 Eigen::Matrix<double, 1, 2> k;
190 k << 2, 0;
191
192 Eigen::Matrix<double, 2, 1> goal;
193 goal << 0, 13;
194
195 auto result = CoerceGoal<double>(upoly, k, 0, goal);
196
197 EXPECT_EQ(result(0, 0), 0);
198 EXPECT_EQ(result(1, 0), 12);
199}
200
James Kuszmaul0ee1fce2020-01-11 16:59:21 -0800201TEST_F(CoerceGoalTest, HorizontalLine) {
202 const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
Lee Mracek65686142020-01-10 22:21:39 -0500203 Eigen::Matrix<double, 1, 2> k;
204 k << 0, 2;
205
206 Eigen::Matrix<double, 2, 1> goal;
207 goal << 13, 2;
208
209 auto result = CoerceGoal<double>(upoly, k, 0, goal);
210
211 EXPECT_EQ(result(0, 0), 12);
212 EXPECT_EQ(result(1, 0), 0);
213}
214
Lee Mracek65686142020-01-10 22:21:39 -0500215} // namespace control_loops
216} // namespace frc971