blob: b458b742474d8a92a36f420f2c3419bf69aeb83d [file] [log] [blame]
Brian Silvermanaba7bf62016-01-31 18:03:59 -05001#include "aos/common/controls/polytope.h"
2
3#include <vector>
4
5#include "Eigen/Dense"
6#include "gtest/gtest.h"
7#include "gmock/gmock.h"
8
9#include "aos/testing/test_logging.h"
10
11namespace aos {
12namespace controls {
13
14class HPolytopeTest : public ::testing::Test {
15 protected:
16 HPolytope<2> Polytope1() {
17 return HPolytope<2>{
18 (Eigen::Matrix<double, 4, 2>() << 1, 0, -1, 0, 0, 1, 0, -1).finished(),
19 (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0, 12.0, 12.0).finished()};
20 }
21 HPolytope<2> Polytope2() {
22 return HPolytope<2>{
23 (Eigen::Matrix<double, 4, 2>() << 1, 1, -1, -1, 0, 1, 0, -1).finished(),
24 (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0, 12.0, 12.0).finished()};
25 }
26 HPolytope<1> Polytope3() {
27 return HPolytope<1>{(Eigen::Matrix<double, 2, 1>() << 1, -0.5).finished(),
28 (Eigen::Matrix<double, 2, 1>() << 5.0, 2.0).finished()};
29 }
30 HPolytope<2> Polytope4() {
31 return HPolytope<2>{
32 (Eigen::Matrix<double, 4, 2>() << 1, 1, -1, -1, 1, -1, -1, 1)
33 .finished(),
34 (Eigen::Matrix<double, 4, 1>() << 2, -1, 2, -1).finished()};
35 }
36 HPolytope<2> Polytope5() {
37 return HPolytope<2>{
38 (Eigen::Matrix<double, 4, 2>() << 1, 1, -1, -1, 1, -1, -1, 1)
39 .finished(),
40 (Eigen::Matrix<double, 4, 1>() << 1.5, -0.5, 1.5, -0.5).finished()};
41 }
42
43 void SetUp() override {
44 ::aos::testing::EnableTestLogging();
45 ::aos::testing::ForcePrintLogsDuringTests();
46 HPolytope<0>::Init();
47 }
48
49 template <typename T>
50 ::std::vector<::std::vector<double>> MatrixToVectors(const T &matrix) {
51 ::std::vector<::std::vector<double>> r;
52 for (int i = 0; i < matrix.cols(); ++i) {
53 ::std::vector<double> col;
54 for (int j = 0; j < matrix.rows(); ++j) {
55 col.emplace_back(matrix(j, i));
56 }
57 r.emplace_back(col);
58 }
59 return r;
60 }
61
62 template <typename T>
63 ::std::vector<::testing::Matcher<::std::vector<double>>> MatrixToMatchers(
64 const T &matrix) {
65 ::std::vector<::testing::Matcher<::std::vector<double>>> r;
66 for (int i = 0; i < matrix.cols(); ++i) {
67 ::std::vector<::testing::Matcher<double>> col;
68 for (int j = 0; j < matrix.rows(); ++j) {
69 col.emplace_back(::testing::DoubleNear(matrix(j, i), 0.000001));
70 }
71 r.emplace_back(::testing::ElementsAreArray(col));
72 }
73 return r;
74 }
75
76 template <int number_of_dimensions>
77 void CheckShiftedVertices(
78 const HPolytope<number_of_dimensions> &base,
79 const Eigen::Matrix<double, number_of_dimensions, number_of_dimensions> &
80 H_multiplier,
81 const Eigen::Matrix<double, number_of_dimensions, 1> &k_shifter) {
82 LOG_MATRIX(DEBUG, "base vertices", base.Vertices());
83 const auto shifted = HPolytope<number_of_dimensions>(
84 base.H() * H_multiplier, base.k() + base.H() * k_shifter);
85 LOG_MATRIX(DEBUG, "shifted vertices", shifted.Vertices());
86 LOG_MATRIX(DEBUG, "shifted - base", shifted.Vertices() - base.Vertices());
87 EXPECT_THAT(MatrixToVectors(HPolytope<number_of_dimensions>(
88 base, H_multiplier, k_shifter).Vertices()),
89 ::testing::UnorderedElementsAreArray(
90 MatrixToMatchers(shifted.Vertices())));
91 }
92};
93
94// Tests that the vertices for various polytopes calculated from H and k are
95// correct.
96TEST_F(HPolytopeTest, CalculatedVertices) {
97 EXPECT_THAT(MatrixToVectors(Polytope1().Vertices()),
98 ::testing::UnorderedElementsAreArray(
99 MatrixToVectors((Eigen::Matrix<double, 2, 4>() << -12, -12,
100 12, 12, -12, 12, 12, -12).finished())));
101 EXPECT_THAT(MatrixToVectors(Polytope2().Vertices()),
102 ::testing::UnorderedElementsAreArray(
103 MatrixToVectors((Eigen::Matrix<double, 2, 4>() << 24, 0, -24,
104 0, -12, 12, 12, -12).finished())));
105 EXPECT_THAT(MatrixToVectors(Polytope3().Vertices()),
106 ::testing::UnorderedElementsAreArray(MatrixToVectors(
107 (Eigen::Matrix<double, 1, 2>() << 5, -4).finished())));
108 EXPECT_THAT(MatrixToVectors(Polytope4().Vertices()),
109 ::testing::UnorderedElementsAreArray(
110 MatrixToVectors((Eigen::Matrix<double, 2, 4>() << 1, 1.5, 1.5,
111 2, 0, -0.5, 0.5, 0).finished())));
112 EXPECT_THAT(MatrixToVectors(Polytope5().Vertices()),
113 ::testing::UnorderedElementsAreArray(
114 MatrixToVectors((Eigen::Matrix<double, 2, 4>() << 0.5, 1, 1.5,
115 1, 0, 0.5, 0, -0.5).finished())));
116}
117
118TEST_F(HPolytopeTest, ShiftedVertices) {
119 CheckShiftedVertices(
120 Polytope1(), (Eigen::Matrix<double, 2, 2>() << 1, 1, 1, -1).finished(),
121 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
122 CheckShiftedVertices(
123 Polytope1(), (Eigen::Matrix<double, 2, 2>() << 1, -1, 1, 1).finished(),
124 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
125 CheckShiftedVertices(
126 Polytope1(), (Eigen::Matrix<double, 2, 2>() << 1, 1, 1.5, -1).finished(),
127 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
128 CheckShiftedVertices(
129 Polytope1(),
130 (Eigen::Matrix<double, 2, 2>() << 1, 1.5, -1.5, -1).finished(),
131 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
132 CheckShiftedVertices(
133 Polytope1(),
134 (Eigen::Matrix<double, 2, 2>() << 1, -1.5, -1.5, -1).finished(),
135 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
136 CheckShiftedVertices(
137 Polytope1(),
138 (Eigen::Matrix<double, 2, 2>() << 2, -1.5, -1.5, -1).finished(),
139 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
140 CheckShiftedVertices(
141 Polytope1(),
142 (Eigen::Matrix<double, 2, 2>() << 2, -1.5, -1.25, -1).finished(),
143 (Eigen::Matrix<double, 2, 1>() << 9.71, 2.54).finished());
144
145 CheckShiftedVertices(Polytope3(),
146 (Eigen::Matrix<double, 1, 1>() << 1).finished(),
147 (Eigen::Matrix<double, 1, 1>() << 9.71).finished());
148 CheckShiftedVertices(Polytope3(),
149 (Eigen::Matrix<double, 1, 1>() << -2.54).finished(),
150 (Eigen::Matrix<double, 1, 1>() << 16.78).finished());
151}
152
153} // namespace controls
154} // namespace aos