blob: 2e8faa801e918141ef1efa92f659e7c6ba9be296 [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}
107 // Index_loop has no FetchNextBlocking
108void WaitForIndex() {
109 LOG(INFO, "Waiting for the indexer to be ready to intake\n");
110 control_loops::index_loop.status.FetchLatest();
111
112 while (!control_loops::index_loop.status.get()) {
113 LOG(WARNING, "No previous index packet, trying to fetch again\n");
114 control_loops::index_loop.status.FetchNextBlocking();
115 }
116
117 while (!control_loops::index_loop.status->ready_to_intake) {
118 control_loops::index_loop.status.FetchNextBlocking();
119 if (ShouldExitAuto()) return;
120 }
121 LOG(INFO, "Indexer ready to intake\n");
122}
123
124void WaitForAngle_Adjust() {
125 LOG(INFO, "Waiting for the angle adjuster to finish\n");
126 control_loops::angle_adjust.status.FetchLatest();
127
128 while (!control_loops::angle_adjust.status.get()) {
129 LOG(WARNING, "No previous angle adjust packet, trying to fetch again\n");
130 control_loops::angle_adjust.status.FetchNextBlocking();
131 }
132
133 while (!control_loops::angle_adjust.status->done) {
134 control_loops::angle_adjust.status.FetchNextBlocking();
135 if (ShouldExitAuto()) return;
136 }
137 LOG(INFO, "Angle adjuster done\n");
138}
139
Austin Schuh47017412013-03-10 11:50:46 -0700140void WaitForShooter() {
Austin Schuh6be011a2013-03-19 10:07:02 +0000141 LOG(INFO, "Waiting for the shooter to spin up\n");
Austin Schuh47017412013-03-10 11:50:46 -0700142 control_loops::shooter.status.FetchLatest();
Austin Schuh6be011a2013-03-19 10:07:02 +0000143
144 while (!control_loops::shooter.status.get()) {
145 LOG(WARNING, "No previous shooteracket, trying to fetch again\n");
Austin Schuh47017412013-03-10 11:50:46 -0700146 control_loops::shooter.status.FetchNextBlocking();
147 }
Austin Schuh47017412013-03-10 11:50:46 -0700148
Austin Schuh6be011a2013-03-19 10:07:02 +0000149 while (!control_loops::shooter.status->ready) {
150 control_loops::shooter.status.FetchNextBlocking();
151 if (ShouldExitAuto()) return;
Austin Schuh47017412013-03-10 11:50:46 -0700152 }
Austin Schuh6be011a2013-03-19 10:07:02 +0000153 LOG(INFO, "Shooter ready to shoot\n");
Austin Schuh47017412013-03-10 11:50:46 -0700154}
155
Austin Schuh6be011a2013-03-19 10:07:02 +0000156void ShootNDiscs(int n) {
157 LOG(INFO, "Waiting until %d discs have been shot\n", n);
158 control_loops::index_loop.status.FetchLatest();
159
160 while (!control_loops::index_loop.status.get()) {
161 LOG(WARNING, "No previous index_loop packet, trying to fetch again\n");
162 control_loops::index_loop.status.FetchNextBlocking();
163 }
164
165 int final_disc_count = control_loops::index_loop.status->shot_disc_count + n;
166 LOG(DEBUG, "Disc count should be %d when done\n", final_disc_count);
167 while (final_disc_count > control_loops::index_loop.status->shot_disc_count) {
168 control_loops::index_loop.status.FetchNextBlocking();
169 if (ShouldExitAuto()) return;
170 }
171 LOG(INFO, "Shot %d discs\n", n);
Austin Schuh47017412013-03-10 11:50:46 -0700172}
173
Austin Schuh6be011a2013-03-19 10:07:02 +0000174void StopDrivetrain() {
175 LOG(INFO, "Stopping the drivetrain\n");
Austin Schuh47017412013-03-10 11:50:46 -0700176 control_loops::drivetrain.goal.MakeWithBuilder()
Brian Silverman3b89ed82013-03-22 18:59:16 -0700177 .control_loop_driving(true)
Austin Schuh6be011a2013-03-19 10:07:02 +0000178 .highgear(false)
179 .steering(0.0)
180 .throttle(0.0)
Brian Silverman3b89ed82013-03-22 18:59:16 -0700181 .left_goal(left_initial_position)
182 .right_goal(right_initial_position)
Austin Schuh6be011a2013-03-19 10:07:02 +0000183 .quickturn(false)
184 .Send();
185}
186
187void SetDriveGoal(double yoffset) {
188 LOG(INFO, "Going to move %f\n", yoffset);
189
190 // Measured conversion to get the distance right.
Austin Schuhfae53362013-03-23 04:39:48 +0000191 yoffset *= kDrivetrainCorrectionFactor;
Austin Schuh6be011a2013-03-19 10:07:02 +0000192 LOG(INFO, "Going to move an adjusted %f\n", yoffset);
193 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
194 ::Eigen::Matrix<double, 2, 1> driveTrainState;
195 const double goal_velocity = 0.0;
196 const double epsilon = 0.01;
197
Austin Schuhfae53362013-03-23 04:39:48 +0000198 profile.set_maximum_acceleration(2.0);
199 profile.set_maximum_velocity(2.0);
Austin Schuh6be011a2013-03-19 10:07:02 +0000200
Austin Schuh6be011a2013-03-19 10:07:02 +0000201 while (true) {
202 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
203 driveTrainState = profile.Update(yoffset, goal_velocity);
204
Brian Silverman3b89ed82013-03-22 18:59:16 -0700205 if (::std::abs(driveTrainState(0, 0) - yoffset) < epsilon) break;
Austin Schuh6be011a2013-03-19 10:07:02 +0000206 if (ShouldExitAuto()) return;
207
208 LOG(DEBUG, "Driving left to %f, right to %f\n",
209 driveTrainState(0, 0) + left_initial_position,
210 driveTrainState(0, 0) + right_initial_position);
211 control_loops::drivetrain.goal.MakeWithBuilder()
212 .control_loop_driving(true)
213 .highgear(false)
214 .left_goal(driveTrainState(0, 0) + left_initial_position)
215 .right_goal(driveTrainState(0, 0) + right_initial_position)
216 .left_velocity_goal(driveTrainState(1, 0))
217 .right_velocity_goal(driveTrainState(1, 0))
218 .Send();
219 }
Brian Silverman3b89ed82013-03-22 18:59:16 -0700220 left_initial_position += yoffset;
221 right_initial_position += yoffset;
Austin Schuh6be011a2013-03-19 10:07:02 +0000222 LOG(INFO, "Done moving\n");
223}
224
Brian Silverman13be6682013-03-22 21:02:07 -0700225// Drives forward while we can pick up discs up to max_distance (in meters).
226void DriveForwardPickUp(double max_distance) {
227 LOG(INFO, "going to pick up at a max distance of %f\n", max_distance);
228 max_distance *= kDrivetrainCorrectionFactor;
229
230 static const ::aos::time::Time kPeriod = ::aos::time::Time::InMS(10);
231 ::aos::util::TrapezoidProfile profile(kPeriod);
232 ::Eigen::Matrix<double, 2, 1> driveTrainState;
233 const double goal_velocity = 0.0;
234 const double epsilon = 0.01;
235 static const double kMaximumAcceleration = 1.0;
236
237 profile.set_maximum_acceleration(kMaximumAcceleration);
238 profile.set_maximum_velocity(0.6);
239
240 // Starts at our maximum distance and then gets changed back to the start once
241 // we're done getting discs or get to the initial goal.
242 double distance_goal = max_distance;
243 bool driving_back = false;
Austin Schuhfae53362013-03-23 04:39:48 +0000244 const double kDestination = -0.20 * kDrivetrainCorrectionFactor;
Brian Silverman13be6682013-03-22 21:02:07 -0700245
246 while (true) {
247 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
248 driveTrainState = profile.Update(distance_goal, goal_velocity);
249
250 if (ShouldExitAuto()) return;
251
252 // If we're where we want to be.
253 if (::std::abs(driveTrainState(0, 0) - distance_goal) < epsilon) {
254 if (driving_back) {
255 break;
256 } else {
257 LOG(INFO, "went the max distance; driving back\n");
258 driving_back = true;
Austin Schuhfae53362013-03-23 04:39:48 +0000259 distance_goal = kDestination;
Brian Silverman13be6682013-03-22 21:02:07 -0700260 }
261 }
262
263 if (control_loops::index_loop.status.FetchLatest()) {
264 if (control_loops::index_loop.status->hopper_disc_count >= 4) {
265 LOG(INFO, "done intaking; driving back\n");
266 driving_back = true;
Austin Schuhfae53362013-03-23 04:39:48 +0000267 distance_goal = kDestination;
Brian Silverman13be6682013-03-22 21:02:07 -0700268 }
269 } else {
270 LOG(WARNING, "getting index status failed\n");
271 }
272
273 LOG(DEBUG, "Driving left to %f, right to %f\n",
274 driveTrainState(0, 0) + left_initial_position,
275 driveTrainState(0, 0) + right_initial_position);
276 control_loops::drivetrain.goal.MakeWithBuilder()
277 .control_loop_driving(true)
278 .highgear(false)
279 .left_goal(driveTrainState(0, 0) + left_initial_position)
280 .right_goal(driveTrainState(0, 0) + right_initial_position)
281 .left_velocity_goal(driveTrainState(1, 0))
282 .right_velocity_goal(driveTrainState(1, 0))
283 .Send();
284 }
Austin Schuhfae53362013-03-23 04:39:48 +0000285 left_initial_position += kDestination;
286 right_initial_position += kDestination;
Brian Silverman13be6682013-03-22 21:02:07 -0700287 LOG(INFO, "Done moving\n");
288}
289
Brian Silverman3b89ed82013-03-22 18:59:16 -0700290void DriveSpin(double radians) {
291 LOG(INFO, "going to spin %f\n", radians);
292
293 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
294 ::Eigen::Matrix<double, 2, 1> driveTrainState;
295 const double goal_velocity = 0.0;
296 const double epsilon = 0.01;
Brian Silverman13be6682013-03-22 21:02:07 -0700297 // in drivetrain "meters"
Brian Silverman3b89ed82013-03-22 18:59:16 -0700298 const double kRobotWidth = 0.4544;
299
300 profile.set_maximum_acceleration(1);
301 profile.set_maximum_velocity(0.6);
302
303 const double side_offset = kRobotWidth * radians / 2.0;
304
305 while (true) {
306 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
307 driveTrainState = profile.Update(side_offset, goal_velocity);
308
309 if (::std::abs(driveTrainState(0, 0) - side_offset) < epsilon) break;
310 if (ShouldExitAuto()) return;
311
312 LOG(DEBUG, "Driving left to %f, right to %f\n",
313 left_initial_position + driveTrainState(0, 0),
314 right_initial_position - driveTrainState(0, 0));
315 control_loops::drivetrain.goal.MakeWithBuilder()
316 .control_loop_driving(true)
317 .highgear(false)
318 .left_goal(left_initial_position + driveTrainState(0, 0))
319 .right_goal(right_initial_position - driveTrainState(0, 0))
320 .left_velocity_goal(driveTrainState(1, 0))
321 .right_velocity_goal(-driveTrainState(1, 0))
322 .Send();
323 }
324 left_initial_position += side_offset;
325 right_initial_position -= side_offset;
326 LOG(INFO, "Done moving\n");
327}
328
329// start with N discs in the indexer
Austin Schuh6be011a2013-03-19 10:07:02 +0000330void HandleAuto() {
331 LOG(INFO, "Handling auto mode\n");
332 double WRIST_UP;
333
334 ::aos::robot_state.FetchLatest();
Brian Silvermanc5277542013-03-22 13:33:07 -0700335 if (!::aos::robot_state.get() ||
Austin Schuh6be011a2013-03-19 10:07:02 +0000336 !constants::wrist_hall_effect_start_angle(&WRIST_UP)) {
337 LOG(ERROR, "Constants not ready\n");
338 return;
339 }
340 WRIST_UP -= 0.4;
341 LOG(INFO, "Got constants\n");
342 const double WRIST_DOWN = -0.633;
Brian Silvermanc5277542013-03-22 13:33:07 -0700343 const double ANGLE_ONE = 0.5101;
Austin Schuh6be011a2013-03-19 10:07:02 +0000344 const double ANGLE_TWO = 0.685;
345
Brian Silverman3b89ed82013-03-22 18:59:16 -0700346 control_loops::drivetrain.position.FetchLatest();
347 while (!control_loops::drivetrain.position.get()) {
348 LOG(WARNING, "No previous drivetrain position packet, trying to fetch again\n");
349 control_loops::drivetrain.position.FetchNextBlocking();
350 }
351 left_initial_position =
352 control_loops::drivetrain.position->left_encoder;
353 right_initial_position =
354 control_loops::drivetrain.position->right_encoder;
355
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700356 ResetIndex();
Brian Silverman3b89ed82013-03-22 18:59:16 -0700357 StopDrivetrain();
Austin Schuh6be011a2013-03-19 10:07:02 +0000358
359 SetWristGoal(WRIST_UP); // wrist must calibrate itself on power-up
360 SetAngle_AdjustGoal(ANGLE_ONE);
Brian Silvermanc5277542013-03-22 13:33:07 -0700361 SetShooterVelocity(410.0);
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700362 WaitForIndexReset();
Austin Schuh6be011a2013-03-19 10:07:02 +0000363 PreloadIndex(); // spin to top and put 1 disc into loader
364
365 if (ShouldExitAuto()) return;
366 WaitForWrist();
367 if (ShouldExitAuto()) return;
368 WaitForAngle_Adjust();
369 ShootIndex(); // tilt up, shoot, repeat until empty
370 // calls WaitForShooter
371 ShootNDiscs(3); // ShootNDiscs returns if ShouldExitAuto
372 if (ShouldExitAuto()) return;
Austin Schuh6be011a2013-03-19 10:07:02 +0000373
Austin Schuh6be011a2013-03-19 10:07:02 +0000374 StartIndex(); // take in up to 4 discs
375
Austin Schuhfae53362013-03-23 04:39:48 +0000376 const double kDistanceToCenterMeters = 3.11023;
377 const double kMaxPickupDistance = 2.5;
378 const double kTurnToCenterDegrees = 73.2;
Austin Schuh6be011a2013-03-19 10:07:02 +0000379
Austin Schuhfae53362013-03-23 04:39:48 +0000380 // Drive back to the center line.
381 SetDriveGoal(-kDistanceToCenterMeters);
Austin Schuh6be011a2013-03-19 10:07:02 +0000382 if (ShouldExitAuto()) return;
383
Austin Schuhfae53362013-03-23 04:39:48 +0000384 SetWristGoal(WRIST_DOWN);
385 // Turn towards the center.
386 SetTurnGoal(kTurnToCenterDegrees * M_PI / 180.0);
Austin Schuh6be011a2013-03-19 10:07:02 +0000387 if (ShouldExitAuto()) return;
Austin Schuhfae53362013-03-23 04:39:48 +0000388 WaitForWrist();
389 if (ShouldExitAuto()) return;
390
391 // Pick up at most 4 discs and drive at most kMaxPickupDistance.
392 DriveForwardPickUp(kMaxPickupDistance);
393
394 SetWristGoal(WRIST_UP); // wrist must calibrate itself on power-up
395 SetTurnGoal(-kTurnToCenterDegrees * M_PI / 180.0);
396 if (ShouldExitAuto()) return;
397 // Drive back to where we were.
398 SetDriveGoal(kDistanceToCenterMeters);
399 if (ShouldExitAuto()) return;
400
401 ShootNDiscs(4);
402 if (ShouldExitAuto()) return;
Austin Schuh47017412013-03-10 11:50:46 -0700403}
404
405} // namespace autonomous
406} // namespace frc971