blob: 18b89c34c86c83ad89df96c1cc6458433f1007c3 [file] [log] [blame]
Brian Silverman8d3816a2017-07-03 18:52:15 -07001#include "motors/algorithms.h"
2
3#include <inttypes.h>
Austin Schuh94f51e92017-10-30 19:25:32 -07004#include <cmath>
Brian Silverman8d3816a2017-07-03 18:52:15 -07005
6#include "gtest/gtest.h"
7
8namespace frc971 {
Brian Silvermana96c1a42018-05-12 12:11:31 -07009namespace motors {
Brian Silverman8d3816a2017-07-03 18:52:15 -070010namespace testing {
11
12class BalanceReadingsTest : public ::testing::Test {
13 protected:
14 void CheckReadingsResult(const ReadingsToBalance &to_balance) {
15 ASSERT_GE((to_balance.weights[0] > 0) + (to_balance.weights[1] > 0) +
16 (to_balance.weights[2] > 0),
17 2)
18 << "Need at least 2 readings";
19 ASSERT_GE(to_balance.weights[0], 0);
20 ASSERT_GE(to_balance.weights[1], 0);
21 ASSERT_GE(to_balance.weights[2], 0);
22
23 const BalancedReadings result = BalanceReadings(to_balance);
24
25 {
26 const auto sum =
27 result.readings[0] + result.readings[1] + result.readings[2];
28 EXPECT_GE(sum, -2);
29 EXPECT_LE(sum, 2);
30 }
31
32 if (to_balance.weights[0] == 0) {
33 const double averages[3] = {
34 0, static_cast<double>(to_balance.sums[1]) / to_balance.weights[1],
35 static_cast<double>(to_balance.sums[2]) / to_balance.weights[2]};
36 EXPECT_LE(::std::abs((averages[1] - averages[2]) -
37 (result.readings[1] - result.readings[2])),
38 0.5);
39 } else if (to_balance.weights[1] == 0) {
40 const double averages[3] = {
41 static_cast<double>(to_balance.sums[0]) / to_balance.weights[0], 0,
42 static_cast<double>(to_balance.sums[2]) / to_balance.weights[2]};
43 EXPECT_LE(::std::abs((averages[0] - averages[2]) -
44 (result.readings[0] - result.readings[2])),
45 0.5);
46 } else if (to_balance.weights[2] == 0) {
47 const double averages[3] = {
48 static_cast<double>(to_balance.sums[0]) / to_balance.weights[0],
49 static_cast<double>(to_balance.sums[1]) / to_balance.weights[1], 0};
50 EXPECT_LE(::std::abs((averages[0] - averages[1]) -
51 (result.readings[0] - result.readings[1])),
52 0.5);
53 } else {
54 const double averages[3] = {
55 static_cast<double>(to_balance.sums[0]) / to_balance.weights[0],
56 static_cast<double>(to_balance.sums[1]) / to_balance.weights[1],
57 static_cast<double>(to_balance.sums[2]) / to_balance.weights[2]};
58
59 const double middle = (averages[0] + averages[1] + averages[2]) / 3;
60 const double average_distances[3] = {
61 ::std::abs(averages[0] - middle - result.readings[0]),
62 ::std::abs(averages[1] - middle - result.readings[1]),
63 ::std::abs(averages[2] - middle - result.readings[2])};
64 // distances[0]/distances[1] = weights[1]/weights[0]
65 // distances[0]*weights[0]/weights[1] = distances[1]
66 EXPECT_LE(::std::abs(average_distances[0] *
67 static_cast<double>(to_balance.weights[0]) /
68 static_cast<double>(to_balance.weights[1]) -
69 average_distances[1]),
70 0.01);
71 EXPECT_LE(::std::abs(average_distances[2] *
72 static_cast<double>(to_balance.weights[2]) /
73 static_cast<double>(to_balance.weights[1]) -
74 average_distances[1]),
75 0.01);
76 EXPECT_LE(::std::abs(average_distances[0] *
77 static_cast<double>(to_balance.weights[0]) /
78 static_cast<double>(to_balance.weights[2]) -
79 average_distances[2]),
80 0.01);
81 }
82 }
83};
84
85TEST_F(BalanceReadingsTest, Basic) {
86 CheckReadingsResult({{50, 50, 50}, {1, 1, 1}});
87 CheckReadingsResult({{50, 50, 0}, {1, 1, 0}});
88 CheckReadingsResult({{50, 0, 50}, {1, 0, 1}});
89 CheckReadingsResult({{0, 50, 50}, {0, 1, 1}});
90 CheckReadingsResult({{0, 50, 100}, {0, 1, 2}});
91 CheckReadingsResult({{100, 50, 50}, {2, 1, 1}});
92 CheckReadingsResult({{100, 100, 50}, {2, 2, 1}});
93
94 CheckReadingsResult({{150, 50, 50}, {1, 1, 1}});
95 CheckReadingsResult({{150, 50, 50}, {2, 2, 2}});
96 CheckReadingsResult({{3424, 5013, 3424}, {2, 2, 2}});
97}
98
99} // namespace testing
Brian Silvermana96c1a42018-05-12 12:11:31 -0700100} // namespace motors
Brian Silverman8d3816a2017-07-03 18:52:15 -0700101} // namespace frc971