James Kuszmaul | 0af658b | 2019-01-25 18:36:29 -0800 | [diff] [blame^] | 1 | #include "aos/util/math.h" |
| 2 | |
| 3 | #include "gtest/gtest.h" |
| 4 | |
| 5 | namespace aos { |
| 6 | namespace math { |
| 7 | namespace testing { |
| 8 | |
| 9 | bool AngleEqual(double a1, double a2) { |
| 10 | double diff = a1 - a2; |
| 11 | return ::std::fmod(diff, 2 * M_PI) == 0.0; |
| 12 | } |
| 13 | |
| 14 | bool AngleInBounds(double a) { return a <= M_PI && a > -M_PI; } |
| 15 | |
| 16 | // Check that something |
| 17 | void ExpectNormalizesCorrectly(double a) { |
| 18 | double b = NormalizeAngle(a); |
| 19 | EXPECT_PRED2(AngleEqual, a, b); |
| 20 | EXPECT_PRED1(AngleInBounds, b); |
| 21 | } |
| 22 | |
| 23 | void ExpectDiffsCorrectly(double a, double b) { |
| 24 | double diff = DiffAngle(a, b); |
| 25 | |
| 26 | EXPECT_PRED1(AngleInBounds, diff) << "a: " << a << " b: " << b; |
| 27 | EXPECT_PRED2(AngleEqual, a, b + diff); |
| 28 | } |
| 29 | |
| 30 | // Checks that normalizing positive and negative angles in and out of bounds |
| 31 | // works correctly. |
| 32 | TEST(MathTest, NormalizeAngleTest) { |
| 33 | ExpectNormalizesCorrectly(0.0); |
| 34 | ExpectNormalizesCorrectly(1.0); |
| 35 | ExpectNormalizesCorrectly(-1.0); |
| 36 | ExpectNormalizesCorrectly(M_PI); |
| 37 | ExpectNormalizesCorrectly(2.0 * M_PI); |
| 38 | ExpectNormalizesCorrectly(-2.0 * M_PI); |
| 39 | ExpectNormalizesCorrectly(100.0); |
| 40 | ExpectNormalizesCorrectly(-100.0); |
| 41 | } |
| 42 | |
| 43 | // Checks that subtracting one angle from another works for various combinations |
| 44 | // of angles. |
| 45 | TEST(MathTest, DiffAngleTest) { |
| 46 | ExpectDiffsCorrectly(0.0, 0.0); |
| 47 | ExpectDiffsCorrectly(1.0, 0.0); |
| 48 | ExpectDiffsCorrectly(0.0, 1.0); |
| 49 | ExpectDiffsCorrectly(-1.0, 1.0); |
| 50 | ExpectDiffsCorrectly(100.0, 1.0); |
| 51 | ExpectDiffsCorrectly(-100.0, 1.0); |
| 52 | ExpectDiffsCorrectly(M_PI, M_PI); |
| 53 | } |
| 54 | |
| 55 | // Check that points that are really counter-clockwise show up as |
| 56 | // counter-clockwise, and that invalid orderings don't show up as CCW. |
| 57 | TEST(MathTest, PointsAreCCWTest) { |
| 58 | Eigen::Vector2d a, b, c; |
| 59 | a << 0.0, 0.0; |
| 60 | b << 1.0, 0.0; |
| 61 | c << 0.0, 1.0; |
| 62 | // Because there are only six orderings we can just enumerate them all. |
| 63 | EXPECT_TRUE(PointsAreCCW<double>(a, b, c)); |
| 64 | EXPECT_FALSE(PointsAreCCW<double>(a, c, b)); |
| 65 | EXPECT_FALSE(PointsAreCCW<double>(b, a, c)); |
| 66 | EXPECT_TRUE(PointsAreCCW<double>(b, c, a)); |
| 67 | EXPECT_TRUE(PointsAreCCW<double>(c, a, b)); |
| 68 | EXPECT_FALSE(PointsAreCCW<double>(c, b, a)); |
| 69 | } |
| 70 | |
| 71 | // Collinear points should always appear as non-counter-clockwise. |
| 72 | TEST(MathTest, CollinearPointsAreCCWTest) { |
| 73 | // Create three collinear points along the X-axis and check that every |
| 74 | // combination is not CCW. |
| 75 | Eigen::Vector2d a, b, c; |
| 76 | a << 0.0, 0.0; |
| 77 | b << 1.0, 0.0; |
| 78 | c << 2.0, 0.0; |
| 79 | EXPECT_FALSE(PointsAreCCW<double>(a, b, c)); |
| 80 | EXPECT_FALSE(PointsAreCCW<double>(a, c, b)); |
| 81 | EXPECT_FALSE(PointsAreCCW<double>(b, a, c)); |
| 82 | EXPECT_FALSE(PointsAreCCW<double>(b, c, a)); |
| 83 | EXPECT_FALSE(PointsAreCCW<double>(c, a, b)); |
| 84 | EXPECT_FALSE(PointsAreCCW<double>(c, b, a)); |
| 85 | } |
| 86 | |
| 87 | } // namespace testing |
| 88 | } // namespace math |
| 89 | } // namespace aos |