blob: acf3699466548e78a095771ac25567ea0c2109f3 [file] [log] [blame]
Benjamin Fredricksona74b0bd2015-03-07 00:32:52 -08001#include <cmath>
2
3#include "gtest/gtest.h"
4
5#include "aos/common/logging/logging.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05006#include "aos/testing/test_logging.h"
Brian Silvermanb691f5e2015-08-02 11:37:55 -07007#include "y2015/util/kinematics.h"
Benjamin Fredricksona74b0bd2015-03-07 00:32:52 -08008#include "frc971/control_loops/team_number_test_environment.h"
9
10namespace aos {
11namespace util {
12namespace testing {
13
14// For verifcation against Mr. Schuh's internal tests.
15// Please do not comment on this in a code review. We can remove this after the
16// season to satisfy any OCD.
17bool k_internal_debug = false;
18
19class KinematicsTest : public ::testing::Test {
20 public:
21 KinematicsTest()
22 : lower_height_limit_(0.01),
23 upper_height_limit_(0.65),
24 lower_angle_limit_(-M_PI / 2.0),
25 upper_angle_limit_(M_PI / 2.0) {}
26
27 void SetUp() {
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050028 ::aos::testing::EnableTestLogging();
Benjamin Fredricksona74b0bd2015-03-07 00:32:52 -080029 kinematics_ = ElevatorArmKinematics(arm_length_, upper_height_limit_, lower_height_limit_,
30 upper_angle_limit_, lower_angle_limit_);
31 }
32
33 protected:
34 double lower_height_limit_;
35 double upper_height_limit_;
36 double lower_angle_limit_;
37 double upper_angle_limit_;
38 double arm_length_ = 0.7366;
39
40 ElevatorArmKinematics kinematics_;
41};
42
43// Used for internal debugging and verification only not acctual testing.
44// Please do not comment on this in a code review. We can remove this after
45// the season to satisfy any OCD.
46TEST_F(KinematicsTest,
47 PrintPointsSoWeCanHandVerifyThemUntilABetterTestIsMadeAndBrianIsHappy) {
48 if (k_internal_debug) {
49 for (double y = -1.0; y <= 1.0; y += 0.2) {
50 for (double x = -1.0; x <= 1.0; x += 0.2) {
51 ElevatorArmKinematics::KinematicResult res;
52 int region = kinematics_.InverseKinematic(x, y, 0.0, 0.0, &res);
53 printf(
54 " %12.3f %12.3f %8.3f %9.3f %8.2f %12d %12.4f %10.4f "
55 "%15.4f %16.4f\n",
56 x, y, res.elevator_height, res.arm_angle,
57 res.arm_angle * 180.0 / M_PI, region, res.fridge_x, res.fridge_h,
58 res.fridge_x - x, res.fridge_h - y);
59 }
60 }
61
62 // Make a set of calls to test the grabber arm intersection test code.
63 printf(
64 "# ArmAngle (degrees) ElevatorHeight ClawAngle (degrees) GrabberX "
65 "GrabberH intersectReturn SafeClawAngle (degrees)\n");
66 for (double elevator_height = kinematics_.get_elevator_min();
67 elevator_height <= kinematics_.get_elevator_max();
68 elevator_height += 0.10) {
69 for (double arm_angle = kinematics_.get_lower_angle_limit();
70 arm_angle <= kinematics_.get_upper_angle_limit() + 0.01;
71 arm_angle += M_PI * 0.5 / 9.0) {
72 double claw_angle = M_PI * 0.25;
73 double safe_claw_angle;
74 double intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
75 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
76 Eigen::Vector2d grabber_location =
77 kinematics_.ForwardKinematicNoChecking(elevator_height, arm_angle);
78
79 printf(
80 " %8.4f %8.2f %8.2f %14.4f %9.2f %9.2f %9.2f %10.3f %13.4f "
81 "%12.3f\n",
82 arm_angle, arm_angle * 180.0 / M_PI, elevator_height, claw_angle,
83 claw_angle * 180.0 / M_PI, grabber_location.x(),
84 grabber_location.y(), intersectReturnValue, safe_claw_angle,
85 safe_claw_angle * 180.0 / M_PI);
86 }
87 printf("\n");
88 }
89 }
90}
91
92TEST_F(KinematicsTest, ValidIntersectCheckPointAtBottomOfElevatorRange) {
93 double safe_claw_angle;
94 double elevator_height = 0.01;
95 double arm_angle = 30.0 * M_PI / 180.0;
96 double claw_angle = M_PI * 0.25;
97 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
98 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
99 EXPECT_TRUE(intersectReturnValue);
100 EXPECT_EQ(safe_claw_angle, claw_angle);
101}
102
103TEST_F(KinematicsTest, ValidIntersectCheckPointAtMiddleOfElevatorRange) {
104 double safe_claw_angle;
105 double elevator_height = 0.4;
106 double arm_angle = 30.0 * M_PI / 180.0;
107 double claw_angle = M_PI * 0.25;
108 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
109 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
110 EXPECT_TRUE(intersectReturnValue);
111 EXPECT_EQ(safe_claw_angle, claw_angle);
112}
113
114TEST_F(KinematicsTest,
115 invalidIntersectCheckPointAtBottomOfElevatorRangeWithSafeClawAngle) {
116 double safe_claw_angle;
117 double elevator_height = 0.01;
118 double arm_angle = -20.0 * M_PI / 180.0;
119 double claw_angle = M_PI * 0.25;
120 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
121 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
122 EXPECT_FALSE(intersectReturnValue);
123 EXPECT_NEAR(safe_claw_angle, 0.0435733, 0.000001);
124}
125
126TEST_F(KinematicsTest,
127 invalidIntersectCheckPointAtMiddleOfElevatorRangeWithSafeClawAngle) {
128 double safe_claw_angle;
129 double elevator_height = 0.41;
130 double arm_angle = -60.0 * M_PI / 180.0;
131 double claw_angle = M_PI * 0.25;
132 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
133 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
134 EXPECT_FALSE(intersectReturnValue);
135 EXPECT_NEAR(safe_claw_angle, 0.12655341, 0.000001);
136}
137
138TEST_F(KinematicsTest,
139 invalidIntersectCheckPointAtBottomOfElevatorRangeNoSafeClawAngle) {
140 double safe_claw_angle;
141 double elevator_height = 0.01;
142 double arm_angle = -30.0 * M_PI / 180.0;
143 double claw_angle = M_PI * 0.25;
144 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
145 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
146 EXPECT_FALSE(intersectReturnValue);
147 EXPECT_EQ(safe_claw_angle, -1.0);
148}
149
150TEST_F(KinematicsTest,
151 invalidIntersectCheckPointAtMiddleOfElevatorRangeNoSafeClawAngle) {
152 double safe_claw_angle;
153 double elevator_height = 0.41;
154 double arm_angle = -70.0 * M_PI / 180.0;
155 double claw_angle = M_PI * 0.25;
156 bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
157 elevator_height, arm_angle, claw_angle, &safe_claw_angle);
158 EXPECT_FALSE(intersectReturnValue);
159 EXPECT_EQ(safe_claw_angle, -1.0);
160}
161
162// Tests that velocity calulations are correct
163TEST_F(KinematicsTest, InverseKinematicVelocity) {
164 ElevatorArmKinematics::KinematicResult result;
165 // move striaght up and verify that only hieght changes
166 EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 0.0, 0.7, &result));
167 EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
168 EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
169 // check the negative
170 EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 0.0, -0.7, &result));
171 EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
172 EXPECT_NEAR(-0.7, result.elevator_velocity, 0.00001);
173 // even with the arm out we should still just move up
174 EXPECT_EQ(0, kinematics_.InverseKinematic(M_PI / 6, 0.2, 0.0, 0.7, &result));
175 EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
176 EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
177 // even with the arm back we should still just move up
178 EXPECT_EQ(0, kinematics_.InverseKinematic(-M_PI / 6, 0.2, 0.0, 0.7, &result));
179 EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
180 EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
181
182 // should move only angle forward
183 EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 1.0, 0.0, &result));
184 EXPECT_NEAR(-1.35759, result.arm_velocity, 0.00001);
185 EXPECT_NEAR(0.0, result.elevator_velocity, 0.00001);
186 // check the negative
187 EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, -1.0, 0.0, &result));
188 EXPECT_NEAR(1.35759, result.arm_velocity, 0.00001);
189 EXPECT_NEAR(0.0, result.elevator_velocity, 0.00001);
190 // with the arm out a change in x should make arm angle greater and
191 // bring the evevator down.
192 EXPECT_EQ(0, kinematics_.InverseKinematic(0.2, 0.2, 1.0, 0.0, &result));
193 EXPECT_GT(0.0, result.arm_velocity);
194 EXPECT_LT(0.0, result.elevator_velocity);
195 // with the arm out a change in x should make arm angle greater and
196 // bring the evevator down.
197 EXPECT_EQ(0, kinematics_.InverseKinematic(-0.2, 0.2, 1.0, 0.0, &result));
198 EXPECT_GT(0.0, result.arm_velocity);
199 EXPECT_GT(0.0, result.elevator_velocity);
200}
201
202// Tests that velocity calulations are correct
203TEST_F(KinematicsTest, ForwardKinematicVelocity) {
204 ElevatorArmKinematics::KinematicResult result;
205
206 // moving the arm forward at zero should result in x velocity
207 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 0.0, 1.35759, &result));
208 EXPECT_NEAR(-1.0, result.fridge_x_velocity, 0.00001);
209 EXPECT_NEAR(0.0, result.fridge_h_velocity, 0.00001);
210 // check the negative
211 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 0.0, -1.35759, &result));
212 EXPECT_NEAR(1.0, result.fridge_x_velocity, 0.00001);
213 EXPECT_NEAR(0.0, result.fridge_h_velocity, 0.00001);
214 // moving the arm up at zero should result in h velocity
215 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 1.0, 0.0, &result));
216 EXPECT_NEAR(0.0, result.fridge_x_velocity, 0.00001);
217 EXPECT_NEAR(1.0, result.fridge_h_velocity, 0.00001);
218 // check the negative
219 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, -1.0, 0.0, &result));
220 EXPECT_NEAR(0.0, result.fridge_x_velocity, 0.00001);
221 EXPECT_NEAR(-1.0, result.fridge_h_velocity, 0.00001);
222 // arm is forward a negative angle should make x head forward and y head down.
223 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, -0.2, 0.0, -1.0, &result));
224 EXPECT_GT(result.fridge_x_velocity, 0.0);
225 EXPECT_LT(result.fridge_h_velocity, 0.0);
226 // arm is forward a positive angle should make x head backwardward and y head up.
227 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, -0.2, 0.0, 1.0, &result));
228 EXPECT_LT(result.fridge_x_velocity, 0.0);
229 EXPECT_GT(result.fridge_h_velocity, 0.0);
230 // arm is backward a negative angle should make x head forward and y head down.
231 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, 0.2, 0.0, -1.0, &result));
232 EXPECT_GT(result.fridge_x_velocity, 0.0);
233 EXPECT_GT(result.fridge_h_velocity, 0.0);
234 // arm is backward a negative angle should make x head forward and y head down.
235 EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, 0.2, 0.0, 1.0, &result));
236 EXPECT_LT(result.fridge_x_velocity, 0.0);
237 EXPECT_LT(result.fridge_h_velocity, 0.0);
238}
239
240} // namespace testing
241} // namespace util
242} // namespace aos