blob: 6ad8bfff62a1bfb3266bd76c6c8557670eca19d1 [file] [log] [blame]
Austin Schuh13379ba2019-03-12 21:06:46 -07001#include "y2019/actors/autonomous_actor.h"
2
3#include <inttypes.h>
4
5#include <chrono>
6#include <cmath>
7
8#include "aos/logging/logging.h"
9#include "aos/util/phased_loop.h"
10
11#include "frc971/control_loops/drivetrain/drivetrain.q.h"
12#include "frc971/control_loops/drivetrain/localizer.q.h"
Austin Schuh6bcc2302019-03-23 22:28:06 -070013#include "y2019/actors/auto_splines.h"
Austin Schuh13379ba2019-03-12 21:06:46 -070014#include "y2019/control_loops/drivetrain/drivetrain_base.h"
15
16namespace y2019 {
17namespace actors {
18using ::frc971::control_loops::drivetrain_queue;
Austin Schuh13379ba2019-03-12 21:06:46 -070019using ::aos::monotonic_clock;
20namespace chrono = ::std::chrono;
21
22namespace {
23
24double DoubleSeconds(monotonic_clock::duration duration) {
25 return ::std::chrono::duration_cast<::std::chrono::duration<double>>(duration)
26 .count();
27}
28
29} // namespace
30
31AutonomousActor::AutonomousActor(
Austin Schuheb99d072019-05-12 21:03:38 -070032 ::aos::EventLoop *event_loop,
Austin Schuh13379ba2019-03-12 21:06:46 -070033 ::frc971::autonomous::AutonomousActionQueueGroup *s)
34 : frc971::autonomous::BaseAutonomousActor(
Austin Schuheb99d072019-05-12 21:03:38 -070035 event_loop, s, control_loops::drivetrain::GetDrivetrainConfig()),
36 localizer_control_sender_(
37 event_loop->MakeSender<
38 ::frc971::control_loops::drivetrain::LocalizerControl>(
39 ".frc971.control_loops.drivetrain.localizer_control")) {}
Austin Schuh13379ba2019-03-12 21:06:46 -070040
Austin Schuhb5b79a52019-05-08 20:32:07 -070041bool AutonomousActor::WaitForDriveXGreater(double x) {
42 LOG(INFO, "Waiting until x > %f\n", x);
43 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
44 ::std::chrono::milliseconds(5) / 2);
45
46 while (true) {
47 if (ShouldCancel()) {
48 return false;
49 }
50 phased_loop.SleepUntilNext();
51 drivetrain_queue.status.FetchLatest();
52 if (drivetrain_queue.status->x > x) {
53 LOG(INFO, "X at %f\n", drivetrain_queue.status->x);
54 return true;
55 }
56 }
57}
58
59bool AutonomousActor::WaitForDriveYCloseToZero(double y) {
60 LOG(INFO, "Waiting until |y| < %f\n", y);
61 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
62 ::std::chrono::milliseconds(5) / 2);
63
64 while (true) {
65 if (ShouldCancel()) {
66 return false;
67 }
68 phased_loop.SleepUntilNext();
69 drivetrain_queue.status.FetchLatest();
70 if (::std::abs(drivetrain_queue.status->y) < y) {
71 LOG(INFO, "Y at %f\n", drivetrain_queue.status->y);
72 return true;
73 }
74 }
75}
76
Austin Schuha9644062019-03-28 14:31:52 -070077void AutonomousActor::Reset(bool is_left) {
78 const double turn_scalar = is_left ? 1.0 : -1.0;
Austin Schuh13379ba2019-03-12 21:06:46 -070079 elevator_goal_ = 0.01;
80 wrist_goal_ = -M_PI / 2.0;
81 intake_goal_ = -1.2;
82
83 suction_on_ = false;
84 suction_gamepiece_ = 1;
85
86 elevator_max_velocity_ = 0.0;
87 elevator_max_acceleration_ = 0.0;
88 wrist_max_velocity_ = 0.0;
89 wrist_max_acceleration_ = 0.0;
90
91 InitializeEncoders();
92 SendSuperstructureGoal();
93
94 {
Austin Schuheb99d072019-05-12 21:03:38 -070095 auto localizer_resetter = localizer_control_sender_.MakeMessage();
Austin Schuh13379ba2019-03-12 21:06:46 -070096 // Start on the left l2.
97 localizer_resetter->x = 1.0;
Austin Schuhb5b79a52019-05-08 20:32:07 -070098 localizer_resetter->y = 1.35 * turn_scalar;
Austin Schuh13379ba2019-03-12 21:06:46 -070099 localizer_resetter->theta = M_PI;
Austin Schuhb5b79a52019-05-08 20:32:07 -0700100 localizer_resetter->theta_uncertainty = 0.00001;
Austin Schuh13379ba2019-03-12 21:06:46 -0700101 if (!localizer_resetter.Send()) {
102 LOG(ERROR, "Failed to reset localizer.\n");
103 }
104 }
105
106 // Wait for the drivetrain to run so it has time to reset the heading.
107 // Otherwise our drivetrain reset will do a 180 right at the start.
108 drivetrain_queue.status.FetchAnother();
109 LOG(INFO, "Heading is %f\n", drivetrain_queue.status->estimated_heading);
110 InitializeEncoders();
111 ResetDrivetrain();
112 drivetrain_queue.status.FetchAnother();
113 LOG(INFO, "Heading is %f\n", drivetrain_queue.status->estimated_heading);
114
115 ResetDrivetrain();
116 InitializeEncoders();
117}
118
119const ProfileParameters kJumpDrive = {2.0, 3.0};
120const ProfileParameters kDrive = {4.0, 3.0};
121const ProfileParameters kTurn = {5.0, 15.0};
122
Austin Schuhb5b79a52019-05-08 20:32:07 -0700123const ElevatorWristPosition kPanelHPIntakeForwrdPos{0.01, M_PI / 2.0};
124const ElevatorWristPosition kPanelHPIntakeBackwardPos{0.015, -M_PI / 2.0};
125
126const ElevatorWristPosition kPanelForwardMiddlePos{0.75, M_PI / 2.0};
127const ElevatorWristPosition kPanelBackwardMiddlePos{0.78, -M_PI / 2.0};
128
129const ElevatorWristPosition kPanelBackwardUpperPos{1.50, -M_PI / 2.0};
130
131const ElevatorWristPosition kPanelCargoBackwardPos{0.0, -M_PI / 2.0};
132
Austin Schuh13379ba2019-03-12 21:06:46 -0700133bool AutonomousActor::RunAction(
134 const ::frc971::autonomous::AutonomousActionParams &params) {
Austin Schuhb5b79a52019-05-08 20:32:07 -0700135 const monotonic_clock::time_point start_time = monotonic_clock::now();
Austin Schuha9644062019-03-28 14:31:52 -0700136 const bool is_left = params.mode == 0;
137
138 {
139 LOG(INFO, "Starting autonomous action with mode %" PRId32 " %s\n",
140 params.mode, is_left ? "left" : "right");
141 }
Austin Schuhb5b79a52019-05-08 20:32:07 -0700142
Austin Schuha9644062019-03-28 14:31:52 -0700143 const double turn_scalar = is_left ? 1.0 : -1.0;
144
145 Reset(is_left);
Austin Schuhb5b79a52019-05-08 20:32:07 -0700146 enum class Mode { kTesting, kRocket, kCargoship };
147 Mode mode = Mode::kCargoship;
148 if (mode == Mode::kRocket) {
149 SplineHandle spline1 =
150 PlanSpline(AutonomousSplines::HabToFarRocketTest(is_left),
151 SplineDirection::kBackward);
Austin Schuh13379ba2019-03-12 21:06:46 -0700152
Austin Schuhb5b79a52019-05-08 20:32:07 -0700153 // Grab the disk, jump, wait until we have vacuum, then raise the elevator
154 set_elevator_goal(0.010);
155 set_wrist_goal(-M_PI / 2.0);
156 set_intake_goal(-1.2);
157 set_suction_goal(true, 1);
158 SendSuperstructureGoal();
Austin Schuh13379ba2019-03-12 21:06:46 -0700159
Austin Schuhb5b79a52019-05-08 20:32:07 -0700160 // if planned start the spline and plan the next
161 if (!spline1.WaitForPlan()) return true;
162 LOG(INFO, "Planned\n");
163 spline1.Start();
Austin Schuh13379ba2019-03-12 21:06:46 -0700164
Austin Schuhb5b79a52019-05-08 20:32:07 -0700165 // If suction, move the superstructure to score
166 if (!WaitForGamePiece()) return true;
167 LOG(INFO, "Has game piece\n");
168 if (!spline1.WaitForSplineDistanceRemaining(3.5)) return true;
169 set_elevator_wrist_goal(kPanelBackwardMiddlePos);
170 SendSuperstructureGoal();
Austin Schuh13379ba2019-03-12 21:06:46 -0700171
Austin Schuhb5b79a52019-05-08 20:32:07 -0700172 if (!spline1.WaitForSplineDistanceRemaining(2.0)) return true;
173 set_elevator_wrist_goal(kPanelForwardMiddlePos);
174 SendSuperstructureGoal();
Austin Schuh13379ba2019-03-12 21:06:46 -0700175
Austin Schuhb5b79a52019-05-08 20:32:07 -0700176 // END SPLINE 1
Austin Schuh13379ba2019-03-12 21:06:46 -0700177
Austin Schuhb5b79a52019-05-08 20:32:07 -0700178 if (!spline1.WaitForSplineDistanceRemaining(0.2)) return true;
179 LineFollowAtVelocity(1.3, 4);
180 if (!WaitForMilliseconds(::std::chrono::milliseconds(1200))) return true;
Austin Schuh13379ba2019-03-12 21:06:46 -0700181
Austin Schuhb5b79a52019-05-08 20:32:07 -0700182 set_suction_goal(false, 1);
183 SendSuperstructureGoal();
184 if (!WaitForMilliseconds(::std::chrono::milliseconds(200))) return true;
185 LineFollowAtVelocity(-1.0, 4);
186 SplineHandle spline2 = PlanSpline(AutonomousSplines::FarRocketToHP(is_left),
187 SplineDirection::kBackward);
Austin Schuh13379ba2019-03-12 21:06:46 -0700188
Austin Schuhb5b79a52019-05-08 20:32:07 -0700189 if (!WaitForMilliseconds(::std::chrono::milliseconds(150))) return true;
190 if (!spline2.WaitForPlan()) return true;
191 LOG(INFO, "Planned\n");
192 // Drive back to hp and set the superstructure accordingly
193 spline2.Start();
194 if (!WaitForMilliseconds(::std::chrono::milliseconds(500))) return true;
195 set_elevator_wrist_goal(kPanelHPIntakeBackwardPos);
196 SendSuperstructureGoal();
197 if (!WaitForMilliseconds(::std::chrono::milliseconds(1000))) return true;
198 set_suction_goal(true, 1);
199 SendSuperstructureGoal();
Austin Schuh13379ba2019-03-12 21:06:46 -0700200
Austin Schuhb5b79a52019-05-08 20:32:07 -0700201 if (!spline2.WaitForSplineDistanceRemaining(1.6)) return true;
202 LineFollowAtVelocity(-1.6);
203
204 // As soon as we pick up Panel 2 go score on the back rocket
205 if (!WaitForGamePiece()) return true;
206 LineFollowAtVelocity(1.5);
207 SplineHandle spline3 = PlanSpline(AutonomousSplines::HPToFarRocket(is_left),
208 SplineDirection::kForward);
209 if (!WaitForDriveXGreater(0.50)) return true;
210 if (!spline3.WaitForPlan()) return true;
211 spline3.Start();
212 LOG(INFO, "Has game piece\n");
213 if (!WaitForMilliseconds(::std::chrono::milliseconds(1000))) return true;
214 set_elevator_wrist_goal(kPanelBackwardMiddlePos);
215 SendSuperstructureGoal();
216 if (!WaitForDriveXGreater(7.1)) return true;
217 LineFollowAtVelocity(-1.5, 4);
218 if (!WaitForMilliseconds(::std::chrono::milliseconds(1000))) return true;
219 set_elevator_wrist_goal(kPanelBackwardUpperPos);
220 SendSuperstructureGoal();
221 if (!WaitForMilliseconds(::std::chrono::milliseconds(1500))) return true;
222 set_suction_goal(false, 1);
223 SendSuperstructureGoal();
224 if (!WaitForMilliseconds(::std::chrono::milliseconds(400))) return true;
225 LineFollowAtVelocity(1.0, 4);
226 SendSuperstructureGoal();
227 if (!WaitForMilliseconds(::std::chrono::milliseconds(200))) return true;
228 } else if (mode == Mode::kCargoship) {
229 SplineHandle spline1 =
230 PlanSpline(AutonomousSplines::HABToSecondCargoShipBay(is_left),
231 SplineDirection::kBackward);
232 set_elevator_goal(0.01);
233 set_wrist_goal(-M_PI / 2.0);
234 set_intake_goal(-1.2);
235 set_suction_goal(true, 1);
236 SendSuperstructureGoal();
237
238 // if planned start the spline and plan the next
239 if (!spline1.WaitForPlan()) return true;
240 LOG(INFO, "Planned\n");
241 spline1.Start();
242
243 // If suction, move the superstructure to score
244 if (!WaitForGamePiece()) return true;
245 LOG(INFO, "Has game piece\n");
246 // unstick the hatch panel
247 if (!WaitForMilliseconds(::std::chrono::milliseconds(500))) return true;
248 set_elevator_goal(0.5);
249 set_wrist_goal(-M_PI / 2.0);
250 SendSuperstructureGoal();
251 if (!WaitForMilliseconds(::std::chrono::milliseconds(500))) return true;
252 set_elevator_wrist_goal(kPanelCargoBackwardPos);
253 SendSuperstructureGoal();
254
255 if (!spline1.WaitForSplineDistanceRemaining(0.8)) return true;
256 // Line follow in to the first disc.
257 LineFollowAtVelocity(-0.9, 2);
258 if (!WaitForDriveYCloseToZero(1.2)) return true;
259
260 set_suction_goal(false, 1);
261 SendSuperstructureGoal();
262 LOG(INFO, "Dropping disc 1 %f\n",
263 DoubleSeconds(monotonic_clock::now() - start_time));
264
265 if (!WaitForDriveYCloseToZero(1.13)) return true;
266 if (!WaitForMilliseconds(::std::chrono::milliseconds(300))) return true;
267
268 LineFollowAtVelocity(0.9, 2);
269 SplineHandle spline2 =
270 PlanSpline(AutonomousSplines::SecondCargoShipBayToHP(is_left),
271 SplineDirection::kForward);
272 if (!WaitForMilliseconds(::std::chrono::milliseconds(400))) return true;
273 if (!spline2.WaitForPlan()) return true;
274 LOG(INFO, "Planned\n");
275 // Drive back to hp and set the superstructure accordingly
276 spline2.Start();
277 if (!WaitForMilliseconds(::std::chrono::milliseconds(200))) return true;
278 set_elevator_wrist_goal(kPanelHPIntakeForwrdPos);
279 SendSuperstructureGoal();
280 if (!WaitForMilliseconds(::std::chrono::milliseconds(1000))) return true;
281 set_suction_goal(true, 1);
282 SendSuperstructureGoal();
283
284 if (!spline2.WaitForSplineDistanceRemaining(1.75)) return true;
285 LineFollowAtVelocity(1.5);
286 // As soon as we pick up Panel 2 go score on the rocket
287 if (!WaitForGamePiece()) return true;
288 LOG(INFO, "Got gamepiece %f\n",
289 DoubleSeconds(monotonic_clock::now() - start_time));
290 LineFollowAtVelocity(-4.0);
291 SplineHandle spline3 =
292 PlanSpline(AutonomousSplines::HPToThirdCargoShipBay(is_left),
293 SplineDirection::kBackward);
294 if (!WaitForDriveXGreater(0.55)) return true;
295 if (!spline3.WaitForPlan()) return true;
296 spline3.Start();
297 // Wait until we are a bit out to lift.
298 if (!WaitForMilliseconds(::std::chrono::milliseconds(1000))) return true;
299 set_elevator_wrist_goal(kPanelCargoBackwardPos);
300 SendSuperstructureGoal();
301
302 if (!spline3.WaitForSplineDistanceRemaining(0.7)) return true;
303 // Line follow in to the second disc.
304 LineFollowAtVelocity(-0.7, 3);
305 LOG(INFO, "Drawing in disc 2 %f\n",
306 DoubleSeconds(monotonic_clock::now() - start_time));
307 if (!WaitForDriveYCloseToZero(1.2)) return true;
308
309 set_suction_goal(false, 1);
310 SendSuperstructureGoal();
311 LOG(INFO, "Dropping disc 2 %f\n",
312 DoubleSeconds(monotonic_clock::now() - start_time));
313
314 if (!WaitForDriveYCloseToZero(1.13)) return true;
315 if (!WaitForMilliseconds(::std::chrono::milliseconds(200))) return true;
316 LOG(INFO, "Backing up %f\n",
317 DoubleSeconds(monotonic_clock::now() - start_time));
318 LineFollowAtVelocity(0.9, 3);
319 if (!WaitForMilliseconds(::std::chrono::milliseconds(400))) return true;
320 } else {
321 // Grab the disk, wait until we have vacuum, then jump
322 set_elevator_goal(0.01);
323 set_wrist_goal(-M_PI / 2.0);
324 set_intake_goal(-1.2);
325 set_suction_goal(true, 1);
326 SendSuperstructureGoal();
327
328 if (!WaitForGamePiece()) return true;
329 LOG(INFO, "Has game piece\n");
330
331 StartDrive(-4.0, 0.0, kJumpDrive, kTurn);
332 if (!WaitForDriveNear(3.3, 10.0)) return true;
333 LOG(INFO, "Lifting\n");
334 set_elevator_goal(0.30);
335 SendSuperstructureGoal();
336
337 if (!WaitForDriveNear(2.8, 10.0)) return true;
338 LOG(INFO, "Off the platform\n");
339
340 StartDrive(0.0, 1.00 * turn_scalar, kDrive, kTurn);
341 LOG(INFO, "Turn started\n");
342 if (!WaitForSuperstructureDone()) return true;
343 LOG(INFO, "Superstructure done\n");
344
345 if (!WaitForDriveNear(0.7, 10.0)) return true;
346 StartDrive(0.0, -0.35 * turn_scalar, kDrive, kTurn);
347
348 LOG(INFO, "Elevator up\n");
349 set_elevator_goal(0.78);
350 SendSuperstructureGoal();
351
352 if (!WaitForDriveDone()) return true;
353 LOG(INFO, "Done driving\n");
354
355 if (!WaitForSuperstructureDone()) return true;
356 }
Austin Schuh13379ba2019-03-12 21:06:46 -0700357
358 LOG(INFO, "Done %f\n", DoubleSeconds(monotonic_clock::now() - start_time));
359
Austin Schuh13379ba2019-03-12 21:06:46 -0700360 return true;
361}
362
363} // namespace actors
364} // namespace y2019