blob: 63e812f57e32dadc3fe6d20caa62bb8c8cfb85e4 [file] [log] [blame]
Brian Silverman8d3816a2017-07-03 18:52:15 -07001#include "motors/math.h"
2
Brian Silverman8d3816a2017-07-03 18:52:15 -07003#include "gmock/gmock.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07004#include "gtest/gtest.h"
Brian Silverman8d3816a2017-07-03 18:52:15 -07005
Stephan Pleinesf63bde82024-01-13 15:59:33 -08006namespace frc971::motors::testing {
Brian Silverman8d3816a2017-07-03 18:52:15 -07007
8class SinCosIntTest : public ::testing::Test {
9 public:
Philipp Schrader790cb542023-07-05 21:06:52 -070010 void SetUp() override { MathInit(); }
Brian Silverman8d3816a2017-07-03 18:52:15 -070011
Brian Silverman9ccec6e2018-10-21 22:06:35 -070012 template <class Rotation, int kTableSize>
Brian Silverman8d3816a2017-07-03 18:52:15 -070013 void CheckSinCos() {
14 static constexpr float kTolerance = 0.004;
Philipp Schrader790cb542023-07-05 21:06:52 -070015 SCOPED_TRACE("num=" + ::std::to_string(Rotation::num) +
16 " den=" + ::std::to_string(Rotation::den) +
17 " table_size=" + ::std::to_string(kTableSize));
Brian Silverman8d3816a2017-07-03 18:52:15 -070018 for (uint32_t theta = 0; theta < Rotation::den; ++theta) {
Brian Silverman9ccec6e2018-10-21 22:06:35 -070019 const float theta_float = ThetaToFloat<Rotation>(theta);
Philipp Schrader790cb542023-07-05 21:06:52 -070020 SCOPED_TRACE("theta=" + ::std::to_string(theta) +
21 " theta_float=" + ::std::to_string(theta_float));
Brian Silverman9ccec6e2018-10-21 22:06:35 -070022 EXPECT_THAT((FastSinInt<Rotation, kTableSize>(theta)),
23 ::testing::FloatNear(sin(theta_float), kTolerance));
24 EXPECT_THAT((FastCosInt<Rotation, kTableSize>(theta)),
25 ::testing::FloatNear(cos(theta_float), kTolerance));
Brian Silverman8d3816a2017-07-03 18:52:15 -070026 }
27 }
28
29 private:
30 template <class Rotation>
31 double ThetaToFloat(uint32_t theta) {
32 const double rotation_double =
33 static_cast<double>(Rotation::num) / static_cast<double>(Rotation::den);
34 return (static_cast<double>(theta) + 0.5) * rotation_double * 2.0 * M_PI;
35 }
36};
37
Brian Silverman9ccec6e2018-10-21 22:06:35 -070038TEST_F(SinCosIntTest, Numerator1DefaultTable) {
39 CheckSinCos<::std::ratio<1, 2>, 2>();
40 CheckSinCos<::std::ratio<1, 4>, 4>();
41 CheckSinCos<::std::ratio<1, 8>, 8>();
42 CheckSinCos<::std::ratio<1, 128>, 128>();
43 CheckSinCos<::std::ratio<1, 1024>, 1024>();
44 CheckSinCos<::std::ratio<1, 4096>, 4096>();
Brian Silverman8d3816a2017-07-03 18:52:15 -070045}
46
Brian Silverman9ccec6e2018-10-21 22:06:35 -070047TEST_F(SinCosIntTest, Numerator1LargerTable) {
48 // Don't include silly things like a denominator of 2 and table size of 4
49 // here. It will fail because the slope varies so much that linearly
50 // interpolating between 0.5pi/1.5pi vs 0.25pi/0.75pi/1.25pi/1.75pi gives very
51 // different results.
52 CheckSinCos<::std::ratio<1, 2>, 4096>();
53 CheckSinCos<::std::ratio<1, 2>, 1024>();
54 CheckSinCos<::std::ratio<1, 8>, 4096>();
55 CheckSinCos<::std::ratio<1, 128>, 4096>();
56 CheckSinCos<::std::ratio<1, 1024>, 2048>();
57}
58
59TEST_F(SinCosIntTest, Numerator5DefaultTable) {
60 CheckSinCos<::std::ratio<5, 8>, 8>();
61 CheckSinCos<::std::ratio<5, 128>, 128>();
62 CheckSinCos<::std::ratio<5, 1024>, 1024>();
63 CheckSinCos<::std::ratio<5, 4096>, 4096>();
64}
65
66TEST_F(SinCosIntTest, Numerator5LargerTable) {
67 CheckSinCos<::std::ratio<5, 2>, 4096>();
68 CheckSinCos<::std::ratio<5, 2>, 1024>();
69 CheckSinCos<::std::ratio<5, 8>, 4096>();
70 CheckSinCos<::std::ratio<5, 128>, 4096>();
71 CheckSinCos<::std::ratio<5, 1024>, 2048>();
Brian Silverman8d3816a2017-07-03 18:52:15 -070072}
73
74class SinCosFloatTest : public ::testing::Test {
75 public:
Philipp Schrader790cb542023-07-05 21:06:52 -070076 void SetUp() override { MathInit(); }
Brian Silverman8d3816a2017-07-03 18:52:15 -070077
78 void CheckSinCos(float theta) {
79 ASSERT_GE(theta, -0.2f);
80 ASSERT_LE(theta, 0.2f);
81
82 static constexpr float kTolerance = 0.002;
83 EXPECT_THAT(FastSinFloat(theta),
84 ::testing::FloatNear(sin(theta), kTolerance));
85 EXPECT_THAT(FastCosFloat(theta),
86 ::testing::FloatNear(cos(theta), kTolerance));
87 }
88};
89
90TEST_F(SinCosFloatTest, Endpoints) {
91 CheckSinCos(0);
92 CheckSinCos(-0.2);
93 CheckSinCos(0.2);
94}
95
Stephan Pleinesf63bde82024-01-13 15:59:33 -080096} // namespace frc971::motors::testing