blob: d7bdd2a9c380276fe176930769ba3f16aa5bc229 [file] [log] [blame]
Austin Schuh47017412013-03-10 11:50:46 -07001#include "stdio.h"
2
3#include "aos/aos_core.h"
4#include "aos/common/control_loop/Timing.h"
5#include "aos/common/time.h"
Austin Schuh6be011a2013-03-19 10:07:02 +00006#include "aos/common/util/trapezoid_profile.h"
Austin Schuh47017412013-03-10 11:50:46 -07007#include "frc971/autonomous/auto.q.h"
Austin Schuh6be011a2013-03-19 10:07:02 +00008#include "aos/common/messages/RobotState.q.h"
9#include "frc971/constants.h"
10#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Austin Schuh47017412013-03-10 11:50:46 -070011#include "frc971/control_loops/wrist/wrist_motor.q.h"
12#include "frc971/control_loops/index/index_motor.q.h"
13#include "frc971/control_loops/shooter/shooter_motor.q.h"
14#include "frc971/control_loops/angle_adjust/angle_adjust_motor.q.h"
15
16using ::aos::time::Time;
17
18namespace frc971 {
19namespace autonomous {
20
Brian Silverman3b89ed82013-03-22 18:59:16 -070021static double left_initial_position, right_initial_position;
22
Brian Silverman13be6682013-03-22 21:02:07 -070023// Multiply meters by this to get a drivetrain goal distance.
24static const double kDrivetrainCorrectionFactor =
25 ((32.0 / 44.0) / (64.0 /24.0 * 19.0 / 50.0));
26
Austin Schuh6be011a2013-03-19 10:07:02 +000027bool ShouldExitAuto() {
28 ::frc971::autonomous::autonomous.FetchLatest();
29 bool ans = !::frc971::autonomous::autonomous->run_auto;
30 if (ans) {
31 LOG(INFO, "Time to exit auto mode\n");
32 }
33 return ans;
34}
35
Austin Schuh47017412013-03-10 11:50:46 -070036void SetShooterVelocity(double velocity) {
Austin Schuh6be011a2013-03-19 10:07:02 +000037 LOG(INFO, "Setting shooter velocity to %f\n", velocity);
Austin Schuh47017412013-03-10 11:50:46 -070038 control_loops::shooter.goal.MakeWithBuilder()
39 .velocity(velocity).Send();
40}
41
Austin Schuh6be011a2013-03-19 10:07:02 +000042void SetWristGoal(double goal) {
43 LOG(INFO, "Setting wrist to %f\n", goal);
44 control_loops::wrist.goal.MakeWithBuilder()
45 .goal(goal).Send();
46}
47
48void SetAngle_AdjustGoal(double goal) {
49 LOG(INFO, "Setting angle adjust to %f\n", goal);
50 control_loops::angle_adjust.goal.MakeWithBuilder()
51 .goal(goal).Send();
52}
53
54void StartIndex() {
55 LOG(INFO, "Starting index\n");
56 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070057 .goal_state(2).Send();
58}
59
Austin Schuh6be011a2013-03-19 10:07:02 +000060void PreloadIndex() {
61 LOG(INFO, "Preloading index\n");
62 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070063 .goal_state(3).Send();
64}
65
Austin Schuh6be011a2013-03-19 10:07:02 +000066void ShootIndex() {
67 LOG(INFO, "Shooting index\n");
68 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070069 .goal_state(4).Send();
70}
71
Brian Silvermanb8d389f2013-03-19 22:54:06 -070072void ResetIndex() {
73 LOG(INFO, "Resetting index\n");
74 control_loops::index_loop.goal.MakeWithBuilder()
75 .goal_state(5).Send();
76}
77
78void WaitForIndexReset() {
79 LOG(INFO, "Waiting for the indexer to reset\n");
80 control_loops::index_loop.status.FetchLatest();
81
82 // Fetch a couple index status packets to make sure that the indexer has run.
83 for (int i = 0; i < 5; ++i) {
84 LOG(DEBUG, "Fetching another index status packet\n");
85 control_loops::index_loop.status.FetchNextBlocking();
86 if (ShouldExitAuto()) return;
87 }
88 LOG(INFO, "Indexer is now reset.\n");
89}
90
Austin Schuh6be011a2013-03-19 10:07:02 +000091void WaitForWrist() {
92 LOG(INFO, "Waiting for the wrist\n");
93 control_loops::wrist.status.FetchLatest();
94
95 while (!control_loops::wrist.status.get()) {
96 LOG(WARNING, "No previous wrist packet, trying to fetch again\n");
97 control_loops::wrist.status.FetchNextBlocking();
98 }
99
100 while (!control_loops::wrist.status->done) {
101 control_loops::wrist.status.FetchNextBlocking();
102 LOG(DEBUG, "Got a new wrist status packet\n");
103 if (ShouldExitAuto()) return;
104 }
105 LOG(INFO, "Done waiting for the wrist\n");
106}
Austin Schuh6be011a2013-03-19 10:07:02 +0000107void WaitForIndex() {
108 LOG(INFO, "Waiting for the indexer to be ready to intake\n");
109 control_loops::index_loop.status.FetchLatest();
110
111 while (!control_loops::index_loop.status.get()) {
112 LOG(WARNING, "No previous index packet, trying to fetch again\n");
113 control_loops::index_loop.status.FetchNextBlocking();
114 }
115
116 while (!control_loops::index_loop.status->ready_to_intake) {
117 control_loops::index_loop.status.FetchNextBlocking();
118 if (ShouldExitAuto()) return;
119 }
120 LOG(INFO, "Indexer ready to intake\n");
121}
122
123void WaitForAngle_Adjust() {
124 LOG(INFO, "Waiting for the angle adjuster to finish\n");
125 control_loops::angle_adjust.status.FetchLatest();
126
127 while (!control_loops::angle_adjust.status.get()) {
128 LOG(WARNING, "No previous angle adjust packet, trying to fetch again\n");
129 control_loops::angle_adjust.status.FetchNextBlocking();
130 }
131
132 while (!control_loops::angle_adjust.status->done) {
133 control_loops::angle_adjust.status.FetchNextBlocking();
134 if (ShouldExitAuto()) return;
135 }
136 LOG(INFO, "Angle adjuster done\n");
137}
138
Austin Schuh47017412013-03-10 11:50:46 -0700139void WaitForShooter() {
Austin Schuh6be011a2013-03-19 10:07:02 +0000140 LOG(INFO, "Waiting for the shooter to spin up\n");
Austin Schuh47017412013-03-10 11:50:46 -0700141 control_loops::shooter.status.FetchLatest();
Austin Schuh6be011a2013-03-19 10:07:02 +0000142
143 while (!control_loops::shooter.status.get()) {
144 LOG(WARNING, "No previous shooteracket, trying to fetch again\n");
Austin Schuh47017412013-03-10 11:50:46 -0700145 control_loops::shooter.status.FetchNextBlocking();
146 }
Austin Schuh47017412013-03-10 11:50:46 -0700147
Austin Schuh6be011a2013-03-19 10:07:02 +0000148 while (!control_loops::shooter.status->ready) {
149 control_loops::shooter.status.FetchNextBlocking();
150 if (ShouldExitAuto()) return;
Austin Schuh47017412013-03-10 11:50:46 -0700151 }
Austin Schuh6be011a2013-03-19 10:07:02 +0000152 LOG(INFO, "Shooter ready to shoot\n");
Austin Schuh47017412013-03-10 11:50:46 -0700153}
154
Austin Schuh6be011a2013-03-19 10:07:02 +0000155void ShootNDiscs(int n) {
156 LOG(INFO, "Waiting until %d discs have been shot\n", n);
157 control_loops::index_loop.status.FetchLatest();
158
159 while (!control_loops::index_loop.status.get()) {
160 LOG(WARNING, "No previous index_loop packet, trying to fetch again\n");
161 control_loops::index_loop.status.FetchNextBlocking();
162 }
163
164 int final_disc_count = control_loops::index_loop.status->shot_disc_count + n;
165 LOG(DEBUG, "Disc count should be %d when done\n", final_disc_count);
166 while (final_disc_count > control_loops::index_loop.status->shot_disc_count) {
167 control_loops::index_loop.status.FetchNextBlocking();
168 if (ShouldExitAuto()) return;
169 }
170 LOG(INFO, "Shot %d discs\n", n);
Austin Schuh47017412013-03-10 11:50:46 -0700171}
172
Austin Schuh6be011a2013-03-19 10:07:02 +0000173void StopDrivetrain() {
174 LOG(INFO, "Stopping the drivetrain\n");
Austin Schuh47017412013-03-10 11:50:46 -0700175 control_loops::drivetrain.goal.MakeWithBuilder()
Brian Silverman3b89ed82013-03-22 18:59:16 -0700176 .control_loop_driving(true)
Austin Schuh6be011a2013-03-19 10:07:02 +0000177 .highgear(false)
178 .steering(0.0)
179 .throttle(0.0)
Brian Silverman3b89ed82013-03-22 18:59:16 -0700180 .left_goal(left_initial_position)
181 .right_goal(right_initial_position)
Austin Schuh6be011a2013-03-19 10:07:02 +0000182 .quickturn(false)
183 .Send();
184}
185
186void SetDriveGoal(double yoffset) {
187 LOG(INFO, "Going to move %f\n", yoffset);
188
189 // Measured conversion to get the distance right.
Austin Schuhfae53362013-03-23 04:39:48 +0000190 yoffset *= kDrivetrainCorrectionFactor;
Austin Schuh6be011a2013-03-19 10:07:02 +0000191 LOG(INFO, "Going to move an adjusted %f\n", yoffset);
192 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
193 ::Eigen::Matrix<double, 2, 1> driveTrainState;
194 const double goal_velocity = 0.0;
195 const double epsilon = 0.01;
196
Austin Schuhfae53362013-03-23 04:39:48 +0000197 profile.set_maximum_acceleration(2.0);
198 profile.set_maximum_velocity(2.0);
Austin Schuh6be011a2013-03-19 10:07:02 +0000199
Austin Schuh6be011a2013-03-19 10:07:02 +0000200 while (true) {
Brian Silverman7f09f972013-03-22 23:11:39 -0700201 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
Austin Schuh6be011a2013-03-19 10:07:02 +0000202 driveTrainState = profile.Update(yoffset, goal_velocity);
203
Brian Silverman3b89ed82013-03-22 18:59:16 -0700204 if (::std::abs(driveTrainState(0, 0) - yoffset) < epsilon) break;
Austin Schuh6be011a2013-03-19 10:07:02 +0000205 if (ShouldExitAuto()) return;
206
207 LOG(DEBUG, "Driving left to %f, right to %f\n",
208 driveTrainState(0, 0) + left_initial_position,
209 driveTrainState(0, 0) + right_initial_position);
210 control_loops::drivetrain.goal.MakeWithBuilder()
211 .control_loop_driving(true)
212 .highgear(false)
213 .left_goal(driveTrainState(0, 0) + left_initial_position)
214 .right_goal(driveTrainState(0, 0) + right_initial_position)
215 .left_velocity_goal(driveTrainState(1, 0))
216 .right_velocity_goal(driveTrainState(1, 0))
217 .Send();
218 }
Brian Silverman3b89ed82013-03-22 18:59:16 -0700219 left_initial_position += yoffset;
220 right_initial_position += yoffset;
Austin Schuh6be011a2013-03-19 10:07:02 +0000221 LOG(INFO, "Done moving\n");
222}
223
Brian Silverman13be6682013-03-22 21:02:07 -0700224// Drives forward while we can pick up discs up to max_distance (in meters).
225void DriveForwardPickUp(double max_distance) {
226 LOG(INFO, "going to pick up at a max distance of %f\n", max_distance);
227 max_distance *= kDrivetrainCorrectionFactor;
228
229 static const ::aos::time::Time kPeriod = ::aos::time::Time::InMS(10);
230 ::aos::util::TrapezoidProfile profile(kPeriod);
231 ::Eigen::Matrix<double, 2, 1> driveTrainState;
232 const double goal_velocity = 0.0;
233 const double epsilon = 0.01;
234 static const double kMaximumAcceleration = 1.0;
235
236 profile.set_maximum_acceleration(kMaximumAcceleration);
237 profile.set_maximum_velocity(0.6);
238
Brian Silverman13be6682013-03-22 21:02:07 -0700239 bool driving_back = false;
Austin Schuhfae53362013-03-23 04:39:48 +0000240 const double kDestination = -0.20 * kDrivetrainCorrectionFactor;
Brian Silverman13be6682013-03-22 21:02:07 -0700241
242 while (true) {
Brian Silverman7f09f972013-03-22 23:11:39 -0700243 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
Brian Silvermanc6ba6ee2013-03-22 21:10:38 -0700244 driveTrainState = profile.Update(driving_back ? kDestination : max_distance,
245 goal_velocity);
Brian Silverman13be6682013-03-22 21:02:07 -0700246
247 if (ShouldExitAuto()) return;
248
Brian Silvermanc6ba6ee2013-03-22 21:10:38 -0700249 if (driving_back) {
250 if (::std::abs(driveTrainState(0, 0)) < epsilon) break;
251 } else if (::std::abs(driveTrainState(0, 0) - max_distance) < epsilon) {
252 LOG(INFO, "went the max distance; driving back\n");
253 driving_back = true;
Brian Silverman13be6682013-03-22 21:02:07 -0700254 }
255
256 if (control_loops::index_loop.status.FetchLatest()) {
257 if (control_loops::index_loop.status->hopper_disc_count >= 4) {
258 LOG(INFO, "done intaking; driving back\n");
259 driving_back = true;
Brian Silverman13be6682013-03-22 21:02:07 -0700260 }
261 } else {
262 LOG(WARNING, "getting index status failed\n");
263 }
264
265 LOG(DEBUG, "Driving left to %f, right to %f\n",
266 driveTrainState(0, 0) + left_initial_position,
267 driveTrainState(0, 0) + right_initial_position);
268 control_loops::drivetrain.goal.MakeWithBuilder()
269 .control_loop_driving(true)
270 .highgear(false)
271 .left_goal(driveTrainState(0, 0) + left_initial_position)
272 .right_goal(driveTrainState(0, 0) + right_initial_position)
273 .left_velocity_goal(driveTrainState(1, 0))
274 .right_velocity_goal(driveTrainState(1, 0))
275 .Send();
276 }
Austin Schuhfae53362013-03-23 04:39:48 +0000277 left_initial_position += kDestination;
278 right_initial_position += kDestination;
Brian Silverman13be6682013-03-22 21:02:07 -0700279 LOG(INFO, "Done moving\n");
280}
281
Brian Silverman3b89ed82013-03-22 18:59:16 -0700282void DriveSpin(double radians) {
283 LOG(INFO, "going to spin %f\n", radians);
284
285 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
286 ::Eigen::Matrix<double, 2, 1> driveTrainState;
287 const double goal_velocity = 0.0;
288 const double epsilon = 0.01;
Brian Silverman13be6682013-03-22 21:02:07 -0700289 // in drivetrain "meters"
Brian Silverman3b89ed82013-03-22 18:59:16 -0700290 const double kRobotWidth = 0.4544;
291
292 profile.set_maximum_acceleration(1);
293 profile.set_maximum_velocity(0.6);
294
295 const double side_offset = kRobotWidth * radians / 2.0;
296
297 while (true) {
Brian Silverman7f09f972013-03-22 23:11:39 -0700298 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
Brian Silverman3b89ed82013-03-22 18:59:16 -0700299 driveTrainState = profile.Update(side_offset, goal_velocity);
300
301 if (::std::abs(driveTrainState(0, 0) - side_offset) < epsilon) break;
302 if (ShouldExitAuto()) return;
303
304 LOG(DEBUG, "Driving left to %f, right to %f\n",
305 left_initial_position + driveTrainState(0, 0),
306 right_initial_position - driveTrainState(0, 0));
307 control_loops::drivetrain.goal.MakeWithBuilder()
308 .control_loop_driving(true)
309 .highgear(false)
310 .left_goal(left_initial_position + driveTrainState(0, 0))
311 .right_goal(right_initial_position - driveTrainState(0, 0))
312 .left_velocity_goal(driveTrainState(1, 0))
313 .right_velocity_goal(-driveTrainState(1, 0))
314 .Send();
315 }
316 left_initial_position += side_offset;
317 right_initial_position -= side_offset;
318 LOG(INFO, "Done moving\n");
319}
320
321// start with N discs in the indexer
Austin Schuh6be011a2013-03-19 10:07:02 +0000322void HandleAuto() {
323 LOG(INFO, "Handling auto mode\n");
324 double WRIST_UP;
325
326 ::aos::robot_state.FetchLatest();
Brian Silvermanc5277542013-03-22 13:33:07 -0700327 if (!::aos::robot_state.get() ||
Austin Schuh6be011a2013-03-19 10:07:02 +0000328 !constants::wrist_hall_effect_start_angle(&WRIST_UP)) {
329 LOG(ERROR, "Constants not ready\n");
330 return;
331 }
332 WRIST_UP -= 0.4;
333 LOG(INFO, "Got constants\n");
334 const double WRIST_DOWN = -0.633;
Brian Silvermanc5277542013-03-22 13:33:07 -0700335 const double ANGLE_ONE = 0.5101;
Brian Silverman7f09f972013-03-22 23:11:39 -0700336 //const double ANGLE_TWO = 0.685;
Austin Schuh6be011a2013-03-19 10:07:02 +0000337
Brian Silverman3b89ed82013-03-22 18:59:16 -0700338 control_loops::drivetrain.position.FetchLatest();
339 while (!control_loops::drivetrain.position.get()) {
340 LOG(WARNING, "No previous drivetrain position packet, trying to fetch again\n");
341 control_loops::drivetrain.position.FetchNextBlocking();
342 }
343 left_initial_position =
344 control_loops::drivetrain.position->left_encoder;
345 right_initial_position =
346 control_loops::drivetrain.position->right_encoder;
347
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700348 ResetIndex();
Brian Silverman3b89ed82013-03-22 18:59:16 -0700349 StopDrivetrain();
Austin Schuh6be011a2013-03-19 10:07:02 +0000350
Brian Silverman7f09f972013-03-22 23:11:39 -0700351 SetWristGoal(WRIST_UP); // wrist must calibrate itself on power-up
Austin Schuh6be011a2013-03-19 10:07:02 +0000352 SetAngle_AdjustGoal(ANGLE_ONE);
Brian Silvermanc5277542013-03-22 13:33:07 -0700353 SetShooterVelocity(410.0);
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700354 WaitForIndexReset();
Brian Silverman7f09f972013-03-22 23:11:39 -0700355 if (ShouldExitAuto()) return;
356 PreloadIndex(); // spin to top and put 1 disc into loader
Austin Schuh6be011a2013-03-19 10:07:02 +0000357
358 if (ShouldExitAuto()) return;
359 WaitForWrist();
360 if (ShouldExitAuto()) return;
361 WaitForAngle_Adjust();
Brian Silverman7f09f972013-03-22 23:11:39 -0700362 ShootIndex(); // tilt up, shoot, repeat until empty
363 // calls WaitForShooter
364 ShootNDiscs(3); // ShootNDiscs returns if ShouldExitAuto
Austin Schuh6be011a2013-03-19 10:07:02 +0000365 if (ShouldExitAuto()) return;
Austin Schuh6be011a2013-03-19 10:07:02 +0000366
Brian Silverman7f09f972013-03-22 23:11:39 -0700367 StartIndex(); // take in up to 4 discs
Austin Schuh6be011a2013-03-19 10:07:02 +0000368
Austin Schuhfae53362013-03-23 04:39:48 +0000369 const double kDistanceToCenterMeters = 3.11023;
370 const double kMaxPickupDistance = 2.5;
371 const double kTurnToCenterDegrees = 73.2;
Austin Schuh6be011a2013-03-19 10:07:02 +0000372
Austin Schuhfae53362013-03-23 04:39:48 +0000373 // Drive back to the center line.
374 SetDriveGoal(-kDistanceToCenterMeters);
Austin Schuh6be011a2013-03-19 10:07:02 +0000375 if (ShouldExitAuto()) return;
376
Austin Schuhfae53362013-03-23 04:39:48 +0000377 SetWristGoal(WRIST_DOWN);
378 // Turn towards the center.
Brian Silverman7f09f972013-03-22 23:11:39 -0700379 DriveSpin(kTurnToCenterDegrees * M_PI / 180.0);
Austin Schuh6be011a2013-03-19 10:07:02 +0000380 if (ShouldExitAuto()) return;
Austin Schuhfae53362013-03-23 04:39:48 +0000381 WaitForWrist();
382 if (ShouldExitAuto()) return;
383
384 // Pick up at most 4 discs and drive at most kMaxPickupDistance.
385 DriveForwardPickUp(kMaxPickupDistance);
386
Brian Silverman7f09f972013-03-22 23:11:39 -0700387 SetWristGoal(WRIST_UP);
388 DriveSpin(-kTurnToCenterDegrees * M_PI / 180.0);
Austin Schuhfae53362013-03-23 04:39:48 +0000389 if (ShouldExitAuto()) return;
390 // Drive back to where we were.
391 SetDriveGoal(kDistanceToCenterMeters);
392 if (ShouldExitAuto()) return;
393
394 ShootNDiscs(4);
395 if (ShouldExitAuto()) return;
Austin Schuh47017412013-03-10 11:50:46 -0700396}
397
398} // namespace autonomous
399} // namespace frc971