blob: b996157a1838d823c0c5335c4d53351d6564bc6b [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
Austin Schuh6be011a2013-03-19 10:07:02 +000023bool ShouldExitAuto() {
24 ::frc971::autonomous::autonomous.FetchLatest();
25 bool ans = !::frc971::autonomous::autonomous->run_auto;
26 if (ans) {
27 LOG(INFO, "Time to exit auto mode\n");
28 }
29 return ans;
30}
31
Austin Schuh47017412013-03-10 11:50:46 -070032void SetShooterVelocity(double velocity) {
Austin Schuh6be011a2013-03-19 10:07:02 +000033 LOG(INFO, "Setting shooter velocity to %f\n", velocity);
Austin Schuh47017412013-03-10 11:50:46 -070034 control_loops::shooter.goal.MakeWithBuilder()
35 .velocity(velocity).Send();
36}
37
Austin Schuh6be011a2013-03-19 10:07:02 +000038void SetWristGoal(double goal) {
39 LOG(INFO, "Setting wrist to %f\n", goal);
40 control_loops::wrist.goal.MakeWithBuilder()
41 .goal(goal).Send();
42}
43
44void SetAngle_AdjustGoal(double goal) {
45 LOG(INFO, "Setting angle adjust to %f\n", goal);
46 control_loops::angle_adjust.goal.MakeWithBuilder()
47 .goal(goal).Send();
48}
49
50void StartIndex() {
51 LOG(INFO, "Starting index\n");
52 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070053 .goal_state(2).Send();
54}
55
Austin Schuh6be011a2013-03-19 10:07:02 +000056void PreloadIndex() {
57 LOG(INFO, "Preloading index\n");
58 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070059 .goal_state(3).Send();
60}
61
Austin Schuh6be011a2013-03-19 10:07:02 +000062void ShootIndex() {
63 LOG(INFO, "Shooting index\n");
64 control_loops::index_loop.goal.MakeWithBuilder()
Austin Schuh47017412013-03-10 11:50:46 -070065 .goal_state(4).Send();
66}
67
Brian Silvermanb8d389f2013-03-19 22:54:06 -070068void ResetIndex() {
69 LOG(INFO, "Resetting index\n");
70 control_loops::index_loop.goal.MakeWithBuilder()
71 .goal_state(5).Send();
72}
73
74void WaitForIndexReset() {
75 LOG(INFO, "Waiting for the indexer to reset\n");
76 control_loops::index_loop.status.FetchLatest();
77
78 // Fetch a couple index status packets to make sure that the indexer has run.
79 for (int i = 0; i < 5; ++i) {
80 LOG(DEBUG, "Fetching another index status packet\n");
81 control_loops::index_loop.status.FetchNextBlocking();
82 if (ShouldExitAuto()) return;
83 }
84 LOG(INFO, "Indexer is now reset.\n");
85}
86
Austin Schuh6be011a2013-03-19 10:07:02 +000087void WaitForWrist() {
88 LOG(INFO, "Waiting for the wrist\n");
89 control_loops::wrist.status.FetchLatest();
90
91 while (!control_loops::wrist.status.get()) {
92 LOG(WARNING, "No previous wrist packet, trying to fetch again\n");
93 control_loops::wrist.status.FetchNextBlocking();
94 }
95
96 while (!control_loops::wrist.status->done) {
97 control_loops::wrist.status.FetchNextBlocking();
98 LOG(DEBUG, "Got a new wrist status packet\n");
99 if (ShouldExitAuto()) return;
100 }
101 LOG(INFO, "Done waiting for the wrist\n");
102}
103 // Index_loop has no FetchNextBlocking
104void WaitForIndex() {
105 LOG(INFO, "Waiting for the indexer to be ready to intake\n");
106 control_loops::index_loop.status.FetchLatest();
107
108 while (!control_loops::index_loop.status.get()) {
109 LOG(WARNING, "No previous index packet, trying to fetch again\n");
110 control_loops::index_loop.status.FetchNextBlocking();
111 }
112
113 while (!control_loops::index_loop.status->ready_to_intake) {
114 control_loops::index_loop.status.FetchNextBlocking();
115 if (ShouldExitAuto()) return;
116 }
117 LOG(INFO, "Indexer ready to intake\n");
118}
119
120void WaitForAngle_Adjust() {
121 LOG(INFO, "Waiting for the angle adjuster to finish\n");
122 control_loops::angle_adjust.status.FetchLatest();
123
124 while (!control_loops::angle_adjust.status.get()) {
125 LOG(WARNING, "No previous angle adjust packet, trying to fetch again\n");
126 control_loops::angle_adjust.status.FetchNextBlocking();
127 }
128
129 while (!control_loops::angle_adjust.status->done) {
130 control_loops::angle_adjust.status.FetchNextBlocking();
131 if (ShouldExitAuto()) return;
132 }
133 LOG(INFO, "Angle adjuster done\n");
134}
135
Austin Schuh47017412013-03-10 11:50:46 -0700136void WaitForShooter() {
Austin Schuh6be011a2013-03-19 10:07:02 +0000137 LOG(INFO, "Waiting for the shooter to spin up\n");
Austin Schuh47017412013-03-10 11:50:46 -0700138 control_loops::shooter.status.FetchLatest();
Austin Schuh6be011a2013-03-19 10:07:02 +0000139
140 while (!control_loops::shooter.status.get()) {
141 LOG(WARNING, "No previous shooteracket, trying to fetch again\n");
Austin Schuh47017412013-03-10 11:50:46 -0700142 control_loops::shooter.status.FetchNextBlocking();
143 }
Austin Schuh47017412013-03-10 11:50:46 -0700144
Austin Schuh6be011a2013-03-19 10:07:02 +0000145 while (!control_loops::shooter.status->ready) {
146 control_loops::shooter.status.FetchNextBlocking();
147 if (ShouldExitAuto()) return;
Austin Schuh47017412013-03-10 11:50:46 -0700148 }
Austin Schuh6be011a2013-03-19 10:07:02 +0000149 LOG(INFO, "Shooter ready to shoot\n");
Austin Schuh47017412013-03-10 11:50:46 -0700150}
151
Austin Schuh6be011a2013-03-19 10:07:02 +0000152void ShootNDiscs(int n) {
153 LOG(INFO, "Waiting until %d discs have been shot\n", n);
154 control_loops::index_loop.status.FetchLatest();
155
156 while (!control_loops::index_loop.status.get()) {
157 LOG(WARNING, "No previous index_loop packet, trying to fetch again\n");
158 control_loops::index_loop.status.FetchNextBlocking();
159 }
160
161 int final_disc_count = control_loops::index_loop.status->shot_disc_count + n;
162 LOG(DEBUG, "Disc count should be %d when done\n", final_disc_count);
163 while (final_disc_count > control_loops::index_loop.status->shot_disc_count) {
164 control_loops::index_loop.status.FetchNextBlocking();
165 if (ShouldExitAuto()) return;
166 }
167 LOG(INFO, "Shot %d discs\n", n);
Austin Schuh47017412013-03-10 11:50:46 -0700168}
169
Austin Schuh6be011a2013-03-19 10:07:02 +0000170void StopDrivetrain() {
171 LOG(INFO, "Stopping the drivetrain\n");
Austin Schuh47017412013-03-10 11:50:46 -0700172 control_loops::drivetrain.goal.MakeWithBuilder()
Brian Silverman3b89ed82013-03-22 18:59:16 -0700173 .control_loop_driving(true)
Austin Schuh6be011a2013-03-19 10:07:02 +0000174 .highgear(false)
175 .steering(0.0)
176 .throttle(0.0)
Brian Silverman3b89ed82013-03-22 18:59:16 -0700177 .left_goal(left_initial_position)
178 .right_goal(right_initial_position)
Austin Schuh6be011a2013-03-19 10:07:02 +0000179 .quickturn(false)
180 .Send();
181}
182
183void SetDriveGoal(double yoffset) {
184 LOG(INFO, "Going to move %f\n", yoffset);
185
186 // Measured conversion to get the distance right.
187 yoffset *= 0.73;
188 LOG(INFO, "Going to move an adjusted %f\n", yoffset);
189 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
190 ::Eigen::Matrix<double, 2, 1> driveTrainState;
191 const double goal_velocity = 0.0;
192 const double epsilon = 0.01;
193
Brian Silvermanc5277542013-03-22 13:33:07 -0700194 profile.set_maximum_acceleration(1);
195 profile.set_maximum_velocity(0.6);
Austin Schuh6be011a2013-03-19 10:07:02 +0000196
Austin Schuh6be011a2013-03-19 10:07:02 +0000197 while (true) {
198 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
199 driveTrainState = profile.Update(yoffset, goal_velocity);
200
Brian Silverman3b89ed82013-03-22 18:59:16 -0700201 if (::std::abs(driveTrainState(0, 0) - yoffset) < epsilon) break;
Austin Schuh6be011a2013-03-19 10:07:02 +0000202 if (ShouldExitAuto()) return;
203
204 LOG(DEBUG, "Driving left to %f, right to %f\n",
205 driveTrainState(0, 0) + left_initial_position,
206 driveTrainState(0, 0) + right_initial_position);
207 control_loops::drivetrain.goal.MakeWithBuilder()
208 .control_loop_driving(true)
209 .highgear(false)
210 .left_goal(driveTrainState(0, 0) + left_initial_position)
211 .right_goal(driveTrainState(0, 0) + right_initial_position)
212 .left_velocity_goal(driveTrainState(1, 0))
213 .right_velocity_goal(driveTrainState(1, 0))
214 .Send();
215 }
Brian Silverman3b89ed82013-03-22 18:59:16 -0700216 left_initial_position += yoffset;
217 right_initial_position += yoffset;
Austin Schuh6be011a2013-03-19 10:07:02 +0000218 LOG(INFO, "Done moving\n");
219}
220
Brian Silverman3b89ed82013-03-22 18:59:16 -0700221void DriveSpin(double radians) {
222 LOG(INFO, "going to spin %f\n", radians);
223
224 ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(10));
225 ::Eigen::Matrix<double, 2, 1> driveTrainState;
226 const double goal_velocity = 0.0;
227 const double epsilon = 0.01;
228 // in meters
229 const double kRobotWidth = 0.4544;
230
231 profile.set_maximum_acceleration(1);
232 profile.set_maximum_velocity(0.6);
233
234 const double side_offset = kRobotWidth * radians / 2.0;
235
236 while (true) {
237 ::aos::time::PhasedLoop10MS(5000); // wait until next 10ms tick
238 driveTrainState = profile.Update(side_offset, goal_velocity);
239
240 if (::std::abs(driveTrainState(0, 0) - side_offset) < epsilon) break;
241 if (ShouldExitAuto()) return;
242
243 LOG(DEBUG, "Driving left to %f, right to %f\n",
244 left_initial_position + driveTrainState(0, 0),
245 right_initial_position - driveTrainState(0, 0));
246 control_loops::drivetrain.goal.MakeWithBuilder()
247 .control_loop_driving(true)
248 .highgear(false)
249 .left_goal(left_initial_position + driveTrainState(0, 0))
250 .right_goal(right_initial_position - driveTrainState(0, 0))
251 .left_velocity_goal(driveTrainState(1, 0))
252 .right_velocity_goal(-driveTrainState(1, 0))
253 .Send();
254 }
255 left_initial_position += side_offset;
256 right_initial_position -= side_offset;
257 LOG(INFO, "Done moving\n");
258}
259
260// start with N discs in the indexer
Austin Schuh6be011a2013-03-19 10:07:02 +0000261void HandleAuto() {
262 LOG(INFO, "Handling auto mode\n");
263 double WRIST_UP;
264
265 ::aos::robot_state.FetchLatest();
Brian Silvermanc5277542013-03-22 13:33:07 -0700266 if (!::aos::robot_state.get() ||
Austin Schuh6be011a2013-03-19 10:07:02 +0000267 !constants::wrist_hall_effect_start_angle(&WRIST_UP)) {
268 LOG(ERROR, "Constants not ready\n");
269 return;
270 }
271 WRIST_UP -= 0.4;
272 LOG(INFO, "Got constants\n");
273 const double WRIST_DOWN = -0.633;
Brian Silvermanc5277542013-03-22 13:33:07 -0700274 const double ANGLE_ONE = 0.5101;
Austin Schuh6be011a2013-03-19 10:07:02 +0000275 const double ANGLE_TWO = 0.685;
276
Brian Silverman3b89ed82013-03-22 18:59:16 -0700277 control_loops::drivetrain.position.FetchLatest();
278 while (!control_loops::drivetrain.position.get()) {
279 LOG(WARNING, "No previous drivetrain position packet, trying to fetch again\n");
280 control_loops::drivetrain.position.FetchNextBlocking();
281 }
282 left_initial_position =
283 control_loops::drivetrain.position->left_encoder;
284 right_initial_position =
285 control_loops::drivetrain.position->right_encoder;
286
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700287 ResetIndex();
Brian Silverman3b89ed82013-03-22 18:59:16 -0700288 StopDrivetrain();
Austin Schuh6be011a2013-03-19 10:07:02 +0000289
290 SetWristGoal(WRIST_UP); // wrist must calibrate itself on power-up
291 SetAngle_AdjustGoal(ANGLE_ONE);
Brian Silvermanc5277542013-03-22 13:33:07 -0700292 SetShooterVelocity(410.0);
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700293 WaitForIndexReset();
Brian Silvermanc5277542013-03-22 13:33:07 -0700294
295 // Wait to get some more air pressure in the thing.
296 ::aos::time::SleepFor(::aos::time::Time::InSeconds(5.0));
Brian Silvermanb8d389f2013-03-19 22:54:06 -0700297
Austin Schuh6be011a2013-03-19 10:07:02 +0000298 PreloadIndex(); // spin to top and put 1 disc into loader
299
300 if (ShouldExitAuto()) return;
301 WaitForWrist();
302 if (ShouldExitAuto()) return;
303 WaitForAngle_Adjust();
304 ShootIndex(); // tilt up, shoot, repeat until empty
305 // calls WaitForShooter
306 ShootNDiscs(3); // ShootNDiscs returns if ShouldExitAuto
307 if (ShouldExitAuto()) return;
308 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
309
Brian Silvermanc5277542013-03-22 13:33:07 -0700310 return;
311
Austin Schuh6be011a2013-03-19 10:07:02 +0000312 SetWristGoal(WRIST_DOWN);
313 SetAngle_AdjustGoal(ANGLE_TWO);
314 SetShooterVelocity(375.0);
315 StartIndex(); // take in up to 4 discs
316
317 if (ShouldExitAuto()) return;
318 WaitForWrist(); // wrist must be down before moving
319 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
320
321 if (ShouldExitAuto()) return;
322 WaitForIndex(); // ready to pick up discs
323
Brian Silvermanc5277542013-03-22 13:33:07 -0700324 SetDriveGoal(3.5);
325 //SetDriveGoal(0.6);
326 //::aos::time::SleepFor(::aos::time::Time::InSeconds(0.25));
327 //SetDriveGoal(2.9);
Austin Schuh6be011a2013-03-19 10:07:02 +0000328 if (ShouldExitAuto()) return;
329
330 PreloadIndex();
331 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.4));
332 SetDriveGoal(-1.3);
333
334 if (ShouldExitAuto()) return;
335 WaitForAngle_Adjust();
336 ShootIndex();
Austin Schuh47017412013-03-10 11:50:46 -0700337}
338
339} // namespace autonomous
340} // namespace frc971