blob: 3faa13dc231286dde4cde060302949197cdafa8d [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.
191 yoffset *= 0.73;
192 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
Brian Silvermanc5277542013-03-22 13:33:07 -0700198 profile.set_maximum_acceleration(1);
199 profile.set_maximum_velocity(0.6);
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;
244
245 while (true) {
246 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
247 driveTrainState = profile.Update(distance_goal, goal_velocity);
248
249 if (ShouldExitAuto()) return;
250
251 // If we're where we want to be.
252 if (::std::abs(driveTrainState(0, 0) - distance_goal) < epsilon) {
253 if (driving_back) {
254 break;
255 } else {
256 LOG(INFO, "went the max distance; driving back\n");
257 driving_back = true;
258 distance_goal = 0;
259 }
260 }
261
262 if (control_loops::index_loop.status.FetchLatest()) {
263 if (control_loops::index_loop.status->hopper_disc_count >= 4) {
264 LOG(INFO, "done intaking; driving back\n");
265 driving_back = true;
266 distance_goal = 0;
267 }
268 } else {
269 LOG(WARNING, "getting index status failed\n");
270 }
271
272 LOG(DEBUG, "Driving left to %f, right to %f\n",
273 driveTrainState(0, 0) + left_initial_position,
274 driveTrainState(0, 0) + right_initial_position);
275 control_loops::drivetrain.goal.MakeWithBuilder()
276 .control_loop_driving(true)
277 .highgear(false)
278 .left_goal(driveTrainState(0, 0) + left_initial_position)
279 .right_goal(driveTrainState(0, 0) + right_initial_position)
280 .left_velocity_goal(driveTrainState(1, 0))
281 .right_velocity_goal(driveTrainState(1, 0))
282 .Send();
283 }
284 LOG(INFO, "Done moving\n");
285}
286
Brian Silverman3b89ed82013-03-22 18:59:16 -0700287void DriveSpin(double radians) {
288 LOG(INFO, "going to spin %f\n", radians);
289
290 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
291 ::Eigen::Matrix<double, 2, 1> driveTrainState;
292 const double goal_velocity = 0.0;
293 const double epsilon = 0.01;
Brian Silverman13be6682013-03-22 21:02:07 -0700294 // in drivetrain "meters"
Brian Silverman3b89ed82013-03-22 18:59:16 -0700295 const double kRobotWidth = 0.4544;
296
297 profile.set_maximum_acceleration(1);
298 profile.set_maximum_velocity(0.6);
299
300 const double side_offset = kRobotWidth * radians / 2.0;
301
302 while (true) {
303 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
304 driveTrainState = profile.Update(side_offset, goal_velocity);
305
306 if (::std::abs(driveTrainState(0, 0) - side_offset) < epsilon) break;
307 if (ShouldExitAuto()) return;
308
309 LOG(DEBUG, "Driving left to %f, right to %f\n",
310 left_initial_position + driveTrainState(0, 0),
311 right_initial_position - driveTrainState(0, 0));
312 control_loops::drivetrain.goal.MakeWithBuilder()
313 .control_loop_driving(true)
314 .highgear(false)
315 .left_goal(left_initial_position + driveTrainState(0, 0))
316 .right_goal(right_initial_position - driveTrainState(0, 0))
317 .left_velocity_goal(driveTrainState(1, 0))
318 .right_velocity_goal(-driveTrainState(1, 0))
319 .Send();
320 }
321 left_initial_position += side_offset;
322 right_initial_position -= side_offset;
323 LOG(INFO, "Done moving\n");
324}
325
326// start with N discs in the indexer
Austin Schuh6be011a2013-03-19 10:07:02 +0000327void HandleAuto() {
328 LOG(INFO, "Handling auto mode\n");
329 double WRIST_UP;
330
331 ::aos::robot_state.FetchLatest();
Brian Silvermanc5277542013-03-22 13:33:07 -0700332 if (!::aos::robot_state.get() ||
Austin Schuh6be011a2013-03-19 10:07:02 +0000333 !constants::wrist_hall_effect_start_angle(&WRIST_UP)) {
334 LOG(ERROR, "Constants not ready\n");
335 return;
336 }
337 WRIST_UP -= 0.4;
338 LOG(INFO, "Got constants\n");
339 const double WRIST_DOWN = -0.633;
Brian Silvermanc5277542013-03-22 13:33:07 -0700340 const double ANGLE_ONE = 0.5101;
Austin Schuh6be011a2013-03-19 10:07:02 +0000341 const double ANGLE_TWO = 0.685;
342
Brian Silverman3b89ed82013-03-22 18:59:16 -0700343 control_loops::drivetrain.position.FetchLatest();
344 while (!control_loops::drivetrain.position.get()) {
345 LOG(WARNING, "No previous drivetrain position packet, trying to fetch again\n");
346 control_loops::drivetrain.position.FetchNextBlocking();
347 }
348 left_initial_position =
349 control_loops::drivetrain.position->left_encoder;
350 right_initial_position =
351 control_loops::drivetrain.position->right_encoder;
352
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700353 ResetIndex();
Brian Silverman3b89ed82013-03-22 18:59:16 -0700354 StopDrivetrain();
Austin Schuh6be011a2013-03-19 10:07:02 +0000355
356 SetWristGoal(WRIST_UP); // wrist must calibrate itself on power-up
357 SetAngle_AdjustGoal(ANGLE_ONE);
Brian Silvermanc5277542013-03-22 13:33:07 -0700358 SetShooterVelocity(410.0);
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700359 WaitForIndexReset();
Brian Silvermanc5277542013-03-22 13:33:07 -0700360
361 // Wait to get some more air pressure in the thing.
362 ::aos::time::SleepFor(::aos::time::Time::InSeconds(5.0));
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700363
Austin Schuh6be011a2013-03-19 10:07:02 +0000364 PreloadIndex(); // spin to top and put 1 disc into loader
365
366 if (ShouldExitAuto()) return;
367 WaitForWrist();
368 if (ShouldExitAuto()) return;
369 WaitForAngle_Adjust();
370 ShootIndex(); // tilt up, shoot, repeat until empty
371 // calls WaitForShooter
372 ShootNDiscs(3); // ShootNDiscs returns if ShouldExitAuto
373 if (ShouldExitAuto()) return;
374 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
375
Brian Silvermanc5277542013-03-22 13:33:07 -0700376 return;
377
Austin Schuh6be011a2013-03-19 10:07:02 +0000378 SetWristGoal(WRIST_DOWN);
379 SetAngle_AdjustGoal(ANGLE_TWO);
380 SetShooterVelocity(375.0);
381 StartIndex(); // take in up to 4 discs
382
383 if (ShouldExitAuto()) return;
384 WaitForWrist(); // wrist must be down before moving
385 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
386
387 if (ShouldExitAuto()) return;
388 WaitForIndex(); // ready to pick up discs
389
Brian Silvermanc5277542013-03-22 13:33:07 -0700390 SetDriveGoal(3.5);
391 //SetDriveGoal(0.6);
392 //::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
393 //SetDriveGoal(2.9);
Austin Schuh6be011a2013-03-19 10:07:02 +0000394 if (ShouldExitAuto()) return;
395
396 PreloadIndex();
397 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.4));
398 SetDriveGoal(-1.3);
399
400 if (ShouldExitAuto()) return;
401 WaitForAngle_Adjust();
402 ShootIndex();
Austin Schuh47017412013-03-10 11:50:46 -0700403}
404
405} // namespace autonomous
406} // namespace frc971