blob: 0504cf3f267c00959a09348cc58fe29da2b77f15 [file] [log] [blame]
Niko Sohmers3860f8a2024-01-12 21:05:19 -08001#include "y2024/autonomous/autonomous_actor.h"
2
3#include <chrono>
4#include <cinttypes>
5#include <cmath>
6
7#include "aos/logging/logging.h"
8#include "aos/util/math.h"
9#include "frc971/control_loops/drivetrain/localizer_generated.h"
10#include "y2024/autonomous/auto_splines.h"
11#include "y2024/constants.h"
12#include "y2024/control_loops/drivetrain/drivetrain_base.h"
13
14DEFINE_bool(spline_auto, false, "Run simple test S-spline auto mode.");
James Kuszmaulb5f11832024-03-15 22:30:59 -070015DEFINE_bool(do_fifth_piece, true, "");
Niko Sohmers3860f8a2024-01-12 21:05:19 -080016
Stephan Pleinesf63bde82024-01-13 15:59:33 -080017namespace y2024::autonomous {
Niko Sohmers3860f8a2024-01-12 21:05:19 -080018
19using ::frc971::ProfileParametersT;
20
21ProfileParametersT MakeProfileParameters(float max_velocity,
22 float max_acceleration) {
23 ProfileParametersT result;
24 result.max_velocity = max_velocity;
25 result.max_acceleration = max_acceleration;
26 return result;
27}
28
29using ::aos::monotonic_clock;
30using frc971::CreateProfileParameters;
31using ::frc971::ProfileParametersT;
32using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
33using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
34using frc971::control_loops::drivetrain::LocalizerControl;
35namespace chrono = ::std::chrono;
36
James Kuszmaulb5f11832024-03-15 22:30:59 -070037AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop,
38 const y2024::Constants *robot_constants)
Filip Kujawa58ffbf32024-02-24 18:28:34 -080039 : frc971::autonomous::UserButtonLocalizedAutonomousActor(
James Kuszmaul2549e752024-01-20 17:42:51 -080040 event_loop,
41 control_loops::drivetrain::GetDrivetrainConfig(event_loop)),
Niko Sohmers3860f8a2024-01-12 21:05:19 -080042 localizer_control_sender_(
43 event_loop->MakeSender<
44 ::frc971::control_loops::drivetrain::LocalizerControl>(
45 "/drivetrain")),
Niko Sohmers3860f8a2024-01-12 21:05:19 -080046 superstructure_goal_sender_(
Filip Kujawa58ffbf32024-02-24 18:28:34 -080047 event_loop
48 ->MakeSender<::y2024::control_loops::superstructure::GoalStatic>(
49 "/superstructure")),
Niko Sohmers3860f8a2024-01-12 21:05:19 -080050 superstructure_status_fetcher_(
51 event_loop
52 ->MakeFetcher<::y2024::control_loops::superstructure::Status>(
Filip Kujawa58ffbf32024-02-24 18:28:34 -080053 "/superstructure")),
James Kuszmaulb5f11832024-03-15 22:30:59 -070054 robot_constants_(CHECK_NOTNULL(robot_constants)),
Filip Kujawa58ffbf32024-02-24 18:28:34 -080055 auto_splines_() {}
Niko Sohmers3860f8a2024-01-12 21:05:19 -080056
57void AutonomousActor::Replan() {
James Kuszmaulb5f11832024-03-15 22:30:59 -070058 AutonomousMode mode = robot_constants_->common()->autonomous_mode();
59 switch (mode) {
60 case AutonomousMode::NONE:
61 break;
62 case AutonomousMode::SPLINE_AUTO:
63 test_spline_ =
64 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
65 std::placeholders::_1, alliance_),
66 SplineDirection::kForward);
Niko Sohmers3860f8a2024-01-12 21:05:19 -080067
James Kuszmaulb5f11832024-03-15 22:30:59 -070068 starting_position_ = test_spline_->starting_position();
69 break;
70 case AutonomousMode::MOBILITY_AND_SHOOT:
71 AOS_LOG(INFO, "Mobility & shoot replanning!");
72 mobility_and_shoot_splines_ = {PlanSpline(
73 std::bind(&AutonomousSplines::MobilityAndShootSpline, &auto_splines_,
74 std::placeholders::_1, alliance_),
75 SplineDirection::kForward)};
76
77 starting_position_ =
78 mobility_and_shoot_splines_.value()[0].starting_position();
79 CHECK(starting_position_);
80 break;
81 case AutonomousMode::FOUR_PIECE:
82 AOS_LOG(INFO, "FOUR_PIECE replanning!");
83 four_piece_splines_ = {
84 PlanSpline(
85 std::bind(&AutonomousSplines::FourPieceSpline1, &auto_splines_,
86 std::placeholders::_1, alliance_),
87 SplineDirection::kForward),
88 PlanSpline(
89 std::bind(&AutonomousSplines::FourPieceSpline2, &auto_splines_,
90 std::placeholders::_1, alliance_),
91 SplineDirection::kBackward),
92 PlanSpline(
93 std::bind(&AutonomousSplines::FourPieceSpline3, &auto_splines_,
94 std::placeholders::_1, alliance_),
95 SplineDirection::kForward),
96 PlanSpline(
97 std::bind(&AutonomousSplines::FourPieceSpline4, &auto_splines_,
98 std::placeholders::_1, alliance_),
99 SplineDirection::kForward),
100 PlanSpline(
101 std::bind(&AutonomousSplines::FourPieceSpline5, &auto_splines_,
102 std::placeholders::_1, alliance_),
103 SplineDirection::kBackward)};
104
105 starting_position_ = four_piece_splines_.value()[0].starting_position();
106 CHECK(starting_position_);
107 break;
Maxwell Hendersona2dadd02024-03-24 13:57:09 -0700108 case AutonomousMode::TWO_PIECE_STEAL:
109 AOS_LOG(INFO, "TWO_PIECE_STEAL replanning!");
110 two_piece_steal_splines_ = {
111 PlanSpline(
112 std::bind(&AutonomousSplines::TwoPieceStealSpline1,
113 &auto_splines_, std::placeholders::_1, alliance_),
114 SplineDirection::kForward),
115 PlanSpline(
116 std::bind(&AutonomousSplines::TwoPieceStealSpline2,
117 &auto_splines_, std::placeholders::_1, alliance_),
118 SplineDirection::kBackward),
119 PlanSpline(
120 std::bind(&AutonomousSplines::TwoPieceStealSpline3,
121 &auto_splines_, std::placeholders::_1, alliance_),
122 SplineDirection::kForward),
123 PlanSpline(
124 std::bind(&AutonomousSplines::TwoPieceStealSpline4,
125 &auto_splines_, std::placeholders::_1, alliance_),
126 SplineDirection::kForward)};
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800127 }
128
129 is_planned_ = true;
130
131 MaybeSendStartingPosition();
132}
133
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800134bool AutonomousActor::Run(
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800135 const ::frc971::autonomous::AutonomousActionParams *params) {
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800136 AOS_LOG(INFO, "Params are %d\n", params->mode());
137 if (alliance_ == aos::Alliance::kInvalid) {
138 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
139 return false;
140 }
James Kuszmaulb5f11832024-03-15 22:30:59 -0700141
142 AutonomousMode mode = robot_constants_->common()->autonomous_mode();
143 switch (mode) {
144 case AutonomousMode::NONE:
145 AOS_LOG(WARNING, "No auto mode selected.");
146 break;
147 case AutonomousMode::SPLINE_AUTO:
148 SplineAuto();
149 break;
150 case AutonomousMode::MOBILITY_AND_SHOOT:
151 MobilityAndShoot();
152 break;
153 case AutonomousMode::FOUR_PIECE:
154 FourPieceAuto();
155 break;
Maxwell Hendersona2dadd02024-03-24 13:57:09 -0700156 case AutonomousMode::TWO_PIECE_STEAL:
157 TwoPieceStealAuto();
158 break;
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800159 }
160 return true;
161}
162
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800163void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
164 // Set up the starting position for the blue alliance.
165
166 auto builder = localizer_control_sender_.MakeBuilder();
167
168 LocalizerControl::Builder localizer_control_builder =
169 builder.MakeBuilder<LocalizerControl>();
170 localizer_control_builder.add_x(start(0));
171 localizer_control_builder.add_y(start(1));
172 localizer_control_builder.add_theta(start(2));
173 localizer_control_builder.add_theta_uncertainty(0.00001);
174 AOS_LOG(INFO, "User button pressed, x: %f y: %f theta: %f", start(0),
175 start(1), start(2));
176 if (builder.Send(localizer_control_builder.Finish()) !=
177 aos::RawSender::Error::kOk) {
178 AOS_LOG(ERROR, "Failed to reset localizer.\n");
179 }
180}
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800181
182void AutonomousActor::Reset() {
183 set_intake_goal(control_loops::superstructure::IntakeGoal::NONE);
184 set_note_goal(control_loops::superstructure::NoteGoal::NONE);
185 set_auto_aim(false);
186 set_fire(false);
187 set_preloaded(false);
188 SendSuperstructureGoal();
189}
190
191void AutonomousActor::SplineAuto() {
192 CHECK(test_spline_);
193
194 if (!test_spline_->WaitForPlan()) return;
195 test_spline_->Start();
196
197 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
198}
199
James Kuszmaulb5f11832024-03-15 22:30:59 -0700200void AutonomousActor::MobilityAndShoot() {
201 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
202
203 uint32_t initial_shot_count = shot_count();
204
205 CHECK(mobility_and_shoot_splines_);
206
207 auto &splines = *mobility_and_shoot_splines_;
208
209 AOS_LOG(INFO, "Going to preload");
210
211 // Always be auto-aiming.
212 Aim();
213
214 if (!WaitForPreloaded()) return;
215
216 AOS_LOG(INFO, "Starting to Move");
217
218 if (!splines[0].WaitForPlan()) return;
219
220 splines[0].Start();
221
222 if (!splines[0].WaitForSplineDistanceRemaining(0.05)) return;
223
224 AOS_LOG(
225 INFO, "Got there %lf s\nNow Shooting\n",
226 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
227
228 Shoot();
229
230 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(5))) return;
231
232 StopFiring();
233
234 AOS_LOG(
235 INFO, "Note fired at %lf seconds\n",
236 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
237}
238
239void AutonomousActor::FourPieceAuto() {
240 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
241
242 CHECK(four_piece_splines_);
243 auto &splines = *four_piece_splines_;
244
245 uint32_t initial_shot_count = shot_count();
246
247 // Always be aiming & firing.
248 Aim();
249 if (!WaitForPreloaded()) return;
250
James Kuszmaulb5f11832024-03-15 22:30:59 -0700251 Shoot();
252
253 AOS_LOG(
254 INFO, "Shooting Preloaded Note %lfs\n",
255 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
256
257 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
258
259 AOS_LOG(
260 INFO, "Shot first note %lfs\n",
261 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
262
263 Intake();
264 StopFiring();
265
266 AOS_LOG(
267 INFO, "Starting Spline 1 %lfs\n",
268 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
269
270 if (!splines[0].WaitForPlan()) return;
271
272 splines[0].Start();
273
274 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
275
276 if (!splines[1].WaitForPlan()) return;
277
278 AOS_LOG(
279 INFO, "Starting second spline %lfs\n",
280 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
281
282 splines[1].Start();
283
284 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
285
286 AOS_LOG(
287 INFO, "Finished second spline %lfs\n",
288 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
289
290 std::this_thread::sleep_for(chrono::milliseconds(250));
291
292 Shoot();
293
294 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
295 return;
296
297 AOS_LOG(
298 INFO, "Shot second note, starting drive %lfs\n",
299 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
300
301 if (!splines[2].WaitForPlan()) return;
302 splines[2].Start();
303
304 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
305
306 if (!WaitForNoteFired(initial_shot_count + 3, std::chrono::seconds(5)))
307 return;
308
309 AOS_LOG(
310 INFO, "Finished 4 notes at %lfs\n",
311 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
312
313 if (!FLAGS_do_fifth_piece) {
314 AOS_LOG(INFO, "Exitting early due to --nodo_fifth_piece");
315 return;
316 }
317
318 if (!splines[3].WaitForPlan()) return;
319 splines[3].Start();
320
321 if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
322
323 AOS_LOG(
324 INFO, "Got to 5th note at %lfs\n",
325 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
326
327 StopFiring();
328
329 if (!splines[4].WaitForPlan()) return;
330 splines[4].Start();
331
James Kuszmaulf2f95b32024-03-23 20:12:05 -0700332 if (!splines[4].WaitForSplineDistanceRemaining(0.01)) return;
James Kuszmaulb5f11832024-03-15 22:30:59 -0700333
334 AOS_LOG(
335 INFO, "Done with spline %lfs\n",
336 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
337
James Kuszmaulf2f95b32024-03-23 20:12:05 -0700338 std::this_thread::sleep_for(chrono::milliseconds(500));
James Kuszmaulb5f11832024-03-15 22:30:59 -0700339
340 AOS_LOG(
341 INFO, "Shooting last note! %lfs\n",
342 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
343
344 Shoot();
345
346 if (!WaitForNoteFired(initial_shot_count + 4, std::chrono::seconds(5)))
347 return;
348
349 AOS_LOG(
350 INFO, "Done %lfs\n",
351 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
352}
353
Maxwell Hendersona2dadd02024-03-24 13:57:09 -0700354void AutonomousActor::TwoPieceStealAuto() {
355 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
356
357 CHECK(two_piece_steal_splines_);
358 auto &splines = *two_piece_steal_splines_;
359
360 uint32_t initial_shot_count = shot_count();
361
362 // Always be aiming & firing.
363 Aim();
364 if (!WaitForPreloaded()) return;
365
366 std::this_thread::sleep_for(chrono::milliseconds(500));
367 Shoot();
368
369 AOS_LOG(
370 INFO, "Shooting Preloaded Note %lfs\n",
371 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
372
373 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
374
375 AOS_LOG(
376 INFO, "Shot first note %lfs\n",
377 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
378
379 Intake();
380 StopFiring();
381
382 AOS_LOG(
383 INFO, "Starting Spline 1 %lfs\n",
384 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
385
386 if (!splines[0].WaitForPlan()) return;
387
388 splines[0].Start();
389
390 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
391
392 if (!splines[1].WaitForPlan()) return;
393
394 AOS_LOG(
395 INFO, "Starting second spline %lfs\n",
396 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
397
398 splines[1].Start();
399
400 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
401
402 AOS_LOG(
403 INFO, "Finished second spline %lfs\n",
404 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
405
406 std::this_thread::sleep_for(chrono::milliseconds(250));
407
408 Shoot();
409
410 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
411 return;
412
413 StopFiring();
414
415 AOS_LOG(
416 INFO, "Shot second note, starting drive %lfs\n",
417 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
418
419 if (!splines[2].WaitForPlan()) return;
420
421 AOS_LOG(
422 INFO, "Starting third spline %lfs\n",
423 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
424 splines[2].Start();
425
426 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
427
428 if (!splines[3].WaitForPlan()) return;
429
430 AOS_LOG(
431 INFO, "Starting fourth spline %lfs\n",
432 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
433 splines[3].Start();
434
435 if (!splines[3].WaitForSplineDistanceRemaining(0.01)) return;
436
437 Shoot();
438
439 if (!WaitForNoteFired(initial_shot_count + 2, std::chrono::seconds(2)))
440 return;
441
442 AOS_LOG(
443 INFO, "Done %lfs\n",
444 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
445}
446
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800447void AutonomousActor::SendSuperstructureGoal() {
448 aos::Sender<control_loops::superstructure::GoalStatic>::StaticBuilder
449 goal_builder = superstructure_goal_sender_.MakeStaticBuilder();
450
451 goal_builder->set_intake_goal(intake_goal_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700452 if (intake_goal_ == control_loops::superstructure::IntakeGoal::INTAKE) {
453 goal_builder->set_intake_pivot(
454 control_loops::superstructure::IntakePivotGoal::DOWN);
455 } else {
456 goal_builder->set_intake_pivot(
457 control_loops::superstructure::IntakePivotGoal::UP);
458 }
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800459 goal_builder->set_note_goal(note_goal_);
460 goal_builder->set_fire(fire_);
461
462 control_loops::superstructure::ShooterGoalStatic *shooter_goal =
463 goal_builder->add_shooter_goal();
464
465 shooter_goal->set_auto_aim(auto_aim_);
466 shooter_goal->set_preloaded(preloaded_);
467
468 goal_builder.CheckOk(goal_builder.Send());
469}
470
471void AutonomousActor::Intake() {
472 set_intake_goal(control_loops::superstructure::IntakeGoal::INTAKE);
473 set_note_goal(control_loops::superstructure::NoteGoal::CATAPULT);
474 SendSuperstructureGoal();
475}
476
477void AutonomousActor::Aim() {
478 set_auto_aim(true);
479 SendSuperstructureGoal();
480}
481
482void AutonomousActor::Shoot() {
483 set_fire(true);
484 SendSuperstructureGoal();
485}
486
James Kuszmaulb5f11832024-03-15 22:30:59 -0700487void AutonomousActor::StopFiring() {
488 set_fire(false);
489 SendSuperstructureGoal();
490}
491
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800492[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
493 set_preloaded(true);
494 SendSuperstructureGoal();
495
496 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
497 event_loop()->monotonic_now(),
498 aos::common::actions::kLoopOffset);
499
500 bool loaded = false;
501 while (!loaded) {
502 if (ShouldCancel()) {
503 return false;
504 }
505
506 phased_loop.SleepUntilNext();
507 superstructure_status_fetcher_.Fetch();
508 CHECK(superstructure_status_fetcher_.get() != nullptr);
509
510 loaded = (superstructure_status_fetcher_->shooter()->catapult_state() ==
511 control_loops::superstructure::CatapultState::LOADED);
512 }
513
514 set_preloaded(false);
515 SendSuperstructureGoal();
516
517 return true;
518}
519
James Kuszmaulb5f11832024-03-15 22:30:59 -0700520uint32_t AutonomousActor::shot_count() {
521 superstructure_status_fetcher_.Fetch();
522 return superstructure_status_fetcher_->shot_count();
523}
524
525[[nodiscard]] bool AutonomousActor::WaitForNoteFired(
526 uint32_t penultimate_target_shot_count, std::chrono::nanoseconds timeout) {
527 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
528 event_loop()->monotonic_now(),
529 aos::common::actions::kLoopOffset);
530 aos::monotonic_clock::time_point end_time =
531 event_loop()->monotonic_now() + timeout;
532 while (true) {
533 if (ShouldCancel()) {
534 return false;
535 }
536
537 phased_loop.SleepUntilNext();
538
539 if (shot_count() > penultimate_target_shot_count ||
540 event_loop()->monotonic_now() > end_time) {
541 return true;
542 }
543 }
544}
545
546[[nodiscard]] bool AutonomousActor::WaitForCatapultReady() {
547 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
548 event_loop()->monotonic_now(),
549 aos::common::actions::kLoopOffset);
550
551 bool loaded = false;
552 while (!loaded) {
553 if (ShouldCancel()) {
554 return false;
555 }
556
557 phased_loop.SleepUntilNext();
558 superstructure_status_fetcher_.Fetch();
559 CHECK(superstructure_status_fetcher_.get() != nullptr);
560
561 loaded = (superstructure_status_fetcher_->state() ==
562 control_loops::superstructure::SuperstructureState::READY);
563 }
564
565 SendSuperstructureGoal();
566
567 return true;
568}
569
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800570} // namespace y2024::autonomous