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