blob: 4fd3f153f2e6dcf7029cf2b1b9ebca4982e15e2e [file] [log] [blame]
James Kuszmaul9f9676d2019-01-25 21:27:58 -08001#include "frc971/control_loops/pose.h"
2
3#include "gtest/gtest.h"
4
5namespace frc971 {
6namespace control_loops {
7namespace testing {
8
9// Test that basic accessors on an individual Pose object work as expected.
10TEST(PoseTest, BasicPoseTest) {
11 // Provide a basic Pose with non-zero components for everything.
12 Pose pose({1, 1, 0.5}, 0.5);
13 // The xy_norm should just be based on the x/y positions, not the Z; hence
14 // sqrt(2) rather than sqrt(1^2 + 1^2 + 0.5^2).
15 EXPECT_DOUBLE_EQ(::std::sqrt(2.0), pose.xy_norm());
16 // Similarly, heading should just be atan2(y, x).
17 EXPECT_DOUBLE_EQ(M_PI / 4.0, pose.heading());
18 // Global and relative poses should be the same since we did not construct
19 // this off of a separate Pose.
20 EXPECT_EQ(1.0, pose.rel_pos().x());
21 EXPECT_EQ(1.0, pose.rel_pos().y());
22 EXPECT_EQ(0.5, pose.rel_pos().z());
23
24 EXPECT_EQ(1.0, pose.abs_pos().x());
25 EXPECT_EQ(1.0, pose.abs_pos().y());
James Kuszmaul090563a2019-02-09 14:43:20 -080026 EXPECT_EQ(1.0, pose.abs_xy().x());
27 EXPECT_EQ(1.0, pose.abs_xy().y());
James Kuszmaul9f9676d2019-01-25 21:27:58 -080028 EXPECT_EQ(0.5, pose.abs_pos().z());
29
30 EXPECT_EQ(0.5, pose.rel_theta());
31 EXPECT_EQ(0.5, pose.abs_theta());
32
33 pose.set_theta(3.14);
34 EXPECT_EQ(3.14, pose.rel_theta());
35 pose.mutable_pos()->x() = 9.71;
36 EXPECT_EQ(9.71, pose.rel_pos().x());
James Kuszmaul090563a2019-02-09 14:43:20 -080037
38 EXPECT_EQ(nullptr, pose.base());
39 Pose new_base;
40 pose.set_base(&new_base);
41 EXPECT_EQ(&new_base, pose.base());
James Kuszmaul9f9676d2019-01-25 21:27:58 -080042}
43
44// Check that Poses behave as expected when constructed relative to another
45// POse.
46TEST(PoseTest, BaseTest) {
47 // Tolerance for the EXPECT_NEARs. Because we are doing enough trig operations
48 // under the hood we actually start to lose some precision.
49 constexpr double kEps = 1e-15;
50 // The points we will construct have absolute positions at:
51 // base1: (1, 1)
52 // base2: (-1, 1)
53 // rel1: (0, 2)
54 // Where rel1 is expressed as compared to base1, noting that because base1
55 // has a yaw of M_PI, the position of rel1 compared to base1 is (1, -1)
56 // rather than (-1, 1).
57 Pose base1({1, 1, 0}, M_PI);
58 Pose base2({-1, 1, 0}, -M_PI / 2.0);
59 Pose rel1(&base1, {1, -1, 0}, 0.0);
60 EXPECT_NEAR(0.0, rel1.abs_pos().x(), kEps);
61 EXPECT_NEAR(2.0, rel1.abs_pos().y(), kEps);
62 EXPECT_NEAR(M_PI, rel1.abs_theta(), kEps);
63 // Check that, when rebasing to base2, the absolute position does not change
64 // and the relative POse changes to be relative to base2.
65 Pose rel2 = rel1.Rebase(&base2);
66 EXPECT_NEAR(rel1.abs_pos().x(), rel2.abs_pos().x(), kEps);
67 EXPECT_NEAR(rel1.abs_pos().y(), rel2.abs_pos().y(), kEps);
68 EXPECT_NEAR(rel1.abs_pos().z(), rel2.abs_pos().z(), kEps);
69 EXPECT_NEAR(rel1.abs_theta(), rel2.abs_theta(), kEps);
70 EXPECT_NEAR(-1.0, rel2.rel_pos().x(), kEps);
71 EXPECT_NEAR(1.0, rel2.rel_pos().y(), kEps);
72 EXPECT_NEAR(-M_PI / 2.0, rel2.rel_theta(), kEps);
73 // Check that rebasing onto nullptr results in a Pose based in the global
74 // frame.
75 Pose abs = rel1.Rebase(nullptr);
76 EXPECT_NEAR(rel1.abs_pos().x(), abs.abs_pos().x(), kEps);
77 EXPECT_NEAR(rel1.abs_pos().y(), abs.abs_pos().y(), kEps);
78 EXPECT_NEAR(rel1.abs_pos().z(), abs.abs_pos().z(), kEps);
79 EXPECT_NEAR(rel1.abs_theta(), abs.abs_theta(), kEps);
80 EXPECT_NEAR(rel1.abs_pos().x(), abs.rel_pos().x(), kEps);
81 EXPECT_NEAR(rel1.abs_pos().y(), abs.rel_pos().y(), kEps);
82 EXPECT_NEAR(rel1.abs_pos().z(), abs.rel_pos().z(), kEps);
83 EXPECT_NEAR(rel1.abs_theta(), abs.rel_theta(), kEps);
84}
85
James Kuszmaul090563a2019-02-09 14:43:20 -080086// Tests that basic accessors for LineSegment behave as expected.
87TEST(LineSegmentTest, BasicAccessorTest) {
88 LineSegment l;
89 EXPECT_EQ(0.0, l.pose1().rel_theta());
90 l.mutable_pose1()->set_theta(1.234);
91 EXPECT_EQ(1.234, l.pose1().rel_theta());
92 EXPECT_EQ(0.0, l.pose2().rel_theta());
93 l.mutable_pose2()->set_theta(5.678);
94 EXPECT_EQ(5.678, l.pose2().rel_theta());
95
96 const ::std::vector<Pose> plot_pts = l.PlotPoints();
97 ASSERT_EQ(2u, plot_pts.size());
98 EXPECT_EQ(l.pose1().rel_theta(), plot_pts[0].rel_theta());
99 EXPECT_EQ(l.pose2().rel_theta(), plot_pts[1].rel_theta());
100}
101
James Kuszmaul9f9676d2019-01-25 21:27:58 -0800102// Tests that basic checks for intersection function as expected.
103TEST(LineSegmentTest, TrivialIntersectTest) {
104 Pose p1({0, 0, 0}, 0.0), p2({2, 0, 0}, 0.0);
105 // A line segment from (0, 0) to (0, 2).
106 LineSegment l1(p1, p2);
107 Pose q1({1, -1, 0}, 0.0), q2({1, 1, 0}, 0.0);
108 // A line segment from (1, -1) to (1, 1).
109 LineSegment l2(q1, q2);
110 // The two line segments should intersect.
111 EXPECT_TRUE(l1.Intersects(l2));
112 EXPECT_TRUE(l2.Intersects(l1));
113
114 // If we switch around the orderings such that the line segments are
115 // (0, 0) -> (1, -1) and (2, 0)->(1, 1) then the line segments do not
116 // intersect.
117 LineSegment l3(p1, q1);
118 LineSegment l4(p2, q2);
119 EXPECT_FALSE(l3.Intersects(l4));
120 EXPECT_FALSE(l4.Intersects(l3));
121}
122
123// Check that when we construct line segments that are collinear, both with
124// overlapping bits and without overlapping bits, they register as not
125// intersecting.
126// We may want this behavior to change in the future, but for now check for
127// consistency.
128TEST(LineSegmentTest, CollinearIntersectTest) {
129 Pose p1({0, 0, 0}, 0.0), p2({1, 0, 0}, 0.0), p3({2, 0, 0}, 0.0),
130 p4({3, 0, 0}, 0.0);
131 // These two line segments overlap and are collinear, one going from 0 to 2
132 // and the other from 1 to 3 on the X-axis.
133 LineSegment l1(p1, p3);
134 LineSegment l2(p2, p4);
135 EXPECT_FALSE(l1.Intersects(l2));
136 EXPECT_FALSE(l2.Intersects(l1));
137
138 // These two line segments do not overlap and are collinear, one going from 0
139 // to 1 and the other from 2 to 3 on the X-axis.
140 LineSegment l3(p1, p2);
141 LineSegment l4(p3, p4);
142 EXPECT_FALSE(l3.Intersects(l4));
143 EXPECT_FALSE(l4.Intersects(l3));
144
145 // Test when one line segment is completely contained within the other.
146 LineSegment l5(p1, p4);
147 LineSegment l6(p3, p2);
148 EXPECT_FALSE(l5.Intersects(l6));
149 EXPECT_FALSE(l6.Intersects(l5));
150}
151
152} // namespace testing
153} // namespace control_loops
154} // namespace frc971