blob: f50e8f6384f582183170833d503891ce1d3df925 [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
251 std::this_thread::sleep_for(chrono::milliseconds(500));
252 Shoot();
253
254 AOS_LOG(
255 INFO, "Shooting Preloaded Note %lfs\n",
256 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
257
258 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
259
260 AOS_LOG(
261 INFO, "Shot first note %lfs\n",
262 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
263
264 Intake();
265 StopFiring();
266
267 AOS_LOG(
268 INFO, "Starting Spline 1 %lfs\n",
269 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
270
271 if (!splines[0].WaitForPlan()) return;
272
273 splines[0].Start();
274
275 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
276
277 if (!splines[1].WaitForPlan()) return;
278
279 AOS_LOG(
280 INFO, "Starting second spline %lfs\n",
281 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
282
283 splines[1].Start();
284
285 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
286
287 AOS_LOG(
288 INFO, "Finished second spline %lfs\n",
289 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
290
291 std::this_thread::sleep_for(chrono::milliseconds(250));
292
293 Shoot();
294
295 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
296 return;
297
298 AOS_LOG(
299 INFO, "Shot second note, starting drive %lfs\n",
300 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
301
302 if (!splines[2].WaitForPlan()) return;
303 splines[2].Start();
304
305 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
306
307 if (!WaitForNoteFired(initial_shot_count + 3, std::chrono::seconds(5)))
308 return;
309
310 AOS_LOG(
311 INFO, "Finished 4 notes at %lfs\n",
312 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
313
314 if (!FLAGS_do_fifth_piece) {
315 AOS_LOG(INFO, "Exitting early due to --nodo_fifth_piece");
316 return;
317 }
318
319 if (!splines[3].WaitForPlan()) return;
320 splines[3].Start();
321
322 if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
323
324 AOS_LOG(
325 INFO, "Got to 5th note at %lfs\n",
326 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
327
328 StopFiring();
329
330 if (!splines[4].WaitForPlan()) return;
331 splines[4].Start();
332
333 if (!splines[4].WaitForSplineDistanceRemaining(0.05)) return;
334
335 AOS_LOG(
336 INFO, "Done with spline %lfs\n",
337 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
338
339 std::this_thread::sleep_for(chrono::milliseconds(300));
340
341 AOS_LOG(
342 INFO, "Shooting last note! %lfs\n",
343 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
344
345 Shoot();
346
347 if (!WaitForNoteFired(initial_shot_count + 4, std::chrono::seconds(5)))
348 return;
349
350 AOS_LOG(
351 INFO, "Done %lfs\n",
352 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
353}
354
Maxwell Hendersona2dadd02024-03-24 13:57:09 -0700355void AutonomousActor::TwoPieceStealAuto() {
356 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
357
358 CHECK(two_piece_steal_splines_);
359 auto &splines = *two_piece_steal_splines_;
360
361 uint32_t initial_shot_count = shot_count();
362
363 // Always be aiming & firing.
364 Aim();
365 if (!WaitForPreloaded()) return;
366
367 std::this_thread::sleep_for(chrono::milliseconds(500));
368 Shoot();
369
370 AOS_LOG(
371 INFO, "Shooting Preloaded Note %lfs\n",
372 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
373
374 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
375
376 AOS_LOG(
377 INFO, "Shot first note %lfs\n",
378 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
379
380 Intake();
381 StopFiring();
382
383 AOS_LOG(
384 INFO, "Starting Spline 1 %lfs\n",
385 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
386
387 if (!splines[0].WaitForPlan()) return;
388
389 splines[0].Start();
390
391 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
392
393 if (!splines[1].WaitForPlan()) return;
394
395 AOS_LOG(
396 INFO, "Starting second spline %lfs\n",
397 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
398
399 splines[1].Start();
400
401 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
402
403 AOS_LOG(
404 INFO, "Finished second spline %lfs\n",
405 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
406
407 std::this_thread::sleep_for(chrono::milliseconds(250));
408
409 Shoot();
410
411 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
412 return;
413
414 StopFiring();
415
416 AOS_LOG(
417 INFO, "Shot second note, starting drive %lfs\n",
418 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
419
420 if (!splines[2].WaitForPlan()) return;
421
422 AOS_LOG(
423 INFO, "Starting third spline %lfs\n",
424 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
425 splines[2].Start();
426
427 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
428
429 if (!splines[3].WaitForPlan()) return;
430
431 AOS_LOG(
432 INFO, "Starting fourth spline %lfs\n",
433 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
434 splines[3].Start();
435
436 if (!splines[3].WaitForSplineDistanceRemaining(0.01)) return;
437
438 Shoot();
439
440 if (!WaitForNoteFired(initial_shot_count + 2, std::chrono::seconds(2)))
441 return;
442
443 AOS_LOG(
444 INFO, "Done %lfs\n",
445 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
446}
447
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800448void AutonomousActor::SendSuperstructureGoal() {
449 aos::Sender<control_loops::superstructure::GoalStatic>::StaticBuilder
450 goal_builder = superstructure_goal_sender_.MakeStaticBuilder();
451
452 goal_builder->set_intake_goal(intake_goal_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700453 if (intake_goal_ == control_loops::superstructure::IntakeGoal::INTAKE) {
454 goal_builder->set_intake_pivot(
455 control_loops::superstructure::IntakePivotGoal::DOWN);
456 } else {
457 goal_builder->set_intake_pivot(
458 control_loops::superstructure::IntakePivotGoal::UP);
459 }
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800460 goal_builder->set_note_goal(note_goal_);
461 goal_builder->set_fire(fire_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700462 goal_builder->set_climber_goal(
463 control_loops::superstructure::ClimberGoal::STOWED);
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800464
465 control_loops::superstructure::ShooterGoalStatic *shooter_goal =
466 goal_builder->add_shooter_goal();
467
468 shooter_goal->set_auto_aim(auto_aim_);
469 shooter_goal->set_preloaded(preloaded_);
470
471 goal_builder.CheckOk(goal_builder.Send());
472}
473
474void AutonomousActor::Intake() {
475 set_intake_goal(control_loops::superstructure::IntakeGoal::INTAKE);
476 set_note_goal(control_loops::superstructure::NoteGoal::CATAPULT);
477 SendSuperstructureGoal();
478}
479
480void AutonomousActor::Aim() {
481 set_auto_aim(true);
482 SendSuperstructureGoal();
483}
484
485void AutonomousActor::Shoot() {
486 set_fire(true);
487 SendSuperstructureGoal();
488}
489
James Kuszmaulb5f11832024-03-15 22:30:59 -0700490void AutonomousActor::StopFiring() {
491 set_fire(false);
492 SendSuperstructureGoal();
493}
494
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800495[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
496 set_preloaded(true);
497 SendSuperstructureGoal();
498
499 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
500 event_loop()->monotonic_now(),
501 aos::common::actions::kLoopOffset);
502
503 bool loaded = false;
504 while (!loaded) {
505 if (ShouldCancel()) {
506 return false;
507 }
508
509 phased_loop.SleepUntilNext();
510 superstructure_status_fetcher_.Fetch();
511 CHECK(superstructure_status_fetcher_.get() != nullptr);
512
513 loaded = (superstructure_status_fetcher_->shooter()->catapult_state() ==
514 control_loops::superstructure::CatapultState::LOADED);
515 }
516
517 set_preloaded(false);
518 SendSuperstructureGoal();
519
520 return true;
521}
522
James Kuszmaulb5f11832024-03-15 22:30:59 -0700523uint32_t AutonomousActor::shot_count() {
524 superstructure_status_fetcher_.Fetch();
525 return superstructure_status_fetcher_->shot_count();
526}
527
528[[nodiscard]] bool AutonomousActor::WaitForNoteFired(
529 uint32_t penultimate_target_shot_count, std::chrono::nanoseconds timeout) {
530 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
531 event_loop()->monotonic_now(),
532 aos::common::actions::kLoopOffset);
533 aos::monotonic_clock::time_point end_time =
534 event_loop()->monotonic_now() + timeout;
535 while (true) {
536 if (ShouldCancel()) {
537 return false;
538 }
539
540 phased_loop.SleepUntilNext();
541
542 if (shot_count() > penultimate_target_shot_count ||
543 event_loop()->monotonic_now() > end_time) {
544 return true;
545 }
546 }
547}
548
549[[nodiscard]] bool AutonomousActor::WaitForCatapultReady() {
550 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
551 event_loop()->monotonic_now(),
552 aos::common::actions::kLoopOffset);
553
554 bool loaded = false;
555 while (!loaded) {
556 if (ShouldCancel()) {
557 return false;
558 }
559
560 phased_loop.SleepUntilNext();
561 superstructure_status_fetcher_.Fetch();
562 CHECK(superstructure_status_fetcher_.get() != nullptr);
563
564 loaded = (superstructure_status_fetcher_->state() ==
565 control_loops::superstructure::SuperstructureState::READY);
566 }
567
568 SendSuperstructureGoal();
569
570 return true;
571}
572
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800573} // namespace y2024::autonomous