blob: 91100e8399a31d1f67be4e33d142f937acd37c87 [file] [log] [blame]
Brian Silverman8d3816a2017-07-03 18:52:15 -07001#include "motors/math.h"
2
3#include "gtest/gtest.h"
4#include "gmock/gmock.h"
5
6namespace frc971 {
Brian Silvermana96c1a42018-05-12 12:11:31 -07007namespace motors {
Brian Silverman8d3816a2017-07-03 18:52:15 -07008namespace testing {
9
10class SinCosIntTest : public ::testing::Test {
11 public:
12 void SetUp() override {
13 MathInit();
14 }
15
Brian Silverman9ccec6e2018-10-21 22:06:35 -070016 template <class Rotation, int kTableSize>
Brian Silverman8d3816a2017-07-03 18:52:15 -070017 void CheckSinCos() {
18 static constexpr float kTolerance = 0.004;
Brian Silverman9ccec6e2018-10-21 22:06:35 -070019 SCOPED_TRACE("num=" + ::std::to_string(Rotation::num) + " den=" +
20 ::std::to_string(Rotation::den) + " table_size=" +
21 ::std::to_string(kTableSize));
Brian Silverman8d3816a2017-07-03 18:52:15 -070022 for (uint32_t theta = 0; theta < Rotation::den; ++theta) {
Brian Silverman9ccec6e2018-10-21 22:06:35 -070023 const float theta_float = ThetaToFloat<Rotation>(theta);
24 SCOPED_TRACE("theta=" + ::std::to_string(theta) + " theta_float=" +
25 ::std::to_string(theta_float));
26 EXPECT_THAT((FastSinInt<Rotation, kTableSize>(theta)),
27 ::testing::FloatNear(sin(theta_float), kTolerance));
28 EXPECT_THAT((FastCosInt<Rotation, kTableSize>(theta)),
29 ::testing::FloatNear(cos(theta_float), kTolerance));
Brian Silverman8d3816a2017-07-03 18:52:15 -070030 }
31 }
32
33 private:
34 template <class Rotation>
35 double ThetaToFloat(uint32_t theta) {
36 const double rotation_double =
37 static_cast<double>(Rotation::num) / static_cast<double>(Rotation::den);
38 return (static_cast<double>(theta) + 0.5) * rotation_double * 2.0 * M_PI;
39 }
40};
41
Brian Silverman9ccec6e2018-10-21 22:06:35 -070042TEST_F(SinCosIntTest, Numerator1DefaultTable) {
43 CheckSinCos<::std::ratio<1, 2>, 2>();
44 CheckSinCos<::std::ratio<1, 4>, 4>();
45 CheckSinCos<::std::ratio<1, 8>, 8>();
46 CheckSinCos<::std::ratio<1, 128>, 128>();
47 CheckSinCos<::std::ratio<1, 1024>, 1024>();
48 CheckSinCos<::std::ratio<1, 4096>, 4096>();
Brian Silverman8d3816a2017-07-03 18:52:15 -070049}
50
Brian Silverman9ccec6e2018-10-21 22:06:35 -070051TEST_F(SinCosIntTest, Numerator1LargerTable) {
52 // Don't include silly things like a denominator of 2 and table size of 4
53 // here. It will fail because the slope varies so much that linearly
54 // interpolating between 0.5pi/1.5pi vs 0.25pi/0.75pi/1.25pi/1.75pi gives very
55 // different results.
56 CheckSinCos<::std::ratio<1, 2>, 4096>();
57 CheckSinCos<::std::ratio<1, 2>, 1024>();
58 CheckSinCos<::std::ratio<1, 8>, 4096>();
59 CheckSinCos<::std::ratio<1, 128>, 4096>();
60 CheckSinCos<::std::ratio<1, 1024>, 2048>();
61}
62
63TEST_F(SinCosIntTest, Numerator5DefaultTable) {
64 CheckSinCos<::std::ratio<5, 8>, 8>();
65 CheckSinCos<::std::ratio<5, 128>, 128>();
66 CheckSinCos<::std::ratio<5, 1024>, 1024>();
67 CheckSinCos<::std::ratio<5, 4096>, 4096>();
68}
69
70TEST_F(SinCosIntTest, Numerator5LargerTable) {
71 CheckSinCos<::std::ratio<5, 2>, 4096>();
72 CheckSinCos<::std::ratio<5, 2>, 1024>();
73 CheckSinCos<::std::ratio<5, 8>, 4096>();
74 CheckSinCos<::std::ratio<5, 128>, 4096>();
75 CheckSinCos<::std::ratio<5, 1024>, 2048>();
Brian Silverman8d3816a2017-07-03 18:52:15 -070076}
77
78class SinCosFloatTest : public ::testing::Test {
79 public:
80 void SetUp() override {
81 MathInit();
82 }
83
84 void CheckSinCos(float theta) {
85 ASSERT_GE(theta, -0.2f);
86 ASSERT_LE(theta, 0.2f);
87
88 static constexpr float kTolerance = 0.002;
89 EXPECT_THAT(FastSinFloat(theta),
90 ::testing::FloatNear(sin(theta), kTolerance));
91 EXPECT_THAT(FastCosFloat(theta),
92 ::testing::FloatNear(cos(theta), kTolerance));
93 }
94};
95
96TEST_F(SinCosFloatTest, Endpoints) {
97 CheckSinCos(0);
98 CheckSinCos(-0.2);
99 CheckSinCos(0.2);
100}
101
102} // namespace testing
Brian Silvermana96c1a42018-05-12 12:11:31 -0700103} // namespace motors
Brian Silverman8d3816a2017-07-03 18:52:15 -0700104} // namespace frc971