blob: c9da1f015c4104a6505c5d1a20858e281b59c942 [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;
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800108 }
109
110 is_planned_ = true;
111
112 MaybeSendStartingPosition();
113}
114
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800115bool AutonomousActor::Run(
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800116 const ::frc971::autonomous::AutonomousActionParams *params) {
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800117 AOS_LOG(INFO, "Params are %d\n", params->mode());
118 if (alliance_ == aos::Alliance::kInvalid) {
119 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
120 return false;
121 }
James Kuszmaulb5f11832024-03-15 22:30:59 -0700122
123 AutonomousMode mode = robot_constants_->common()->autonomous_mode();
124 switch (mode) {
125 case AutonomousMode::NONE:
126 AOS_LOG(WARNING, "No auto mode selected.");
127 break;
128 case AutonomousMode::SPLINE_AUTO:
129 SplineAuto();
130 break;
131 case AutonomousMode::MOBILITY_AND_SHOOT:
132 MobilityAndShoot();
133 break;
134 case AutonomousMode::FOUR_PIECE:
135 FourPieceAuto();
136 break;
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800137 }
138 return true;
139}
140
Niko Sohmers3860f8a2024-01-12 21:05:19 -0800141void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
142 // Set up the starting position for the blue alliance.
143
144 auto builder = localizer_control_sender_.MakeBuilder();
145
146 LocalizerControl::Builder localizer_control_builder =
147 builder.MakeBuilder<LocalizerControl>();
148 localizer_control_builder.add_x(start(0));
149 localizer_control_builder.add_y(start(1));
150 localizer_control_builder.add_theta(start(2));
151 localizer_control_builder.add_theta_uncertainty(0.00001);
152 AOS_LOG(INFO, "User button pressed, x: %f y: %f theta: %f", start(0),
153 start(1), start(2));
154 if (builder.Send(localizer_control_builder.Finish()) !=
155 aos::RawSender::Error::kOk) {
156 AOS_LOG(ERROR, "Failed to reset localizer.\n");
157 }
158}
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800159
160void AutonomousActor::Reset() {
161 set_intake_goal(control_loops::superstructure::IntakeGoal::NONE);
162 set_note_goal(control_loops::superstructure::NoteGoal::NONE);
163 set_auto_aim(false);
164 set_fire(false);
165 set_preloaded(false);
166 SendSuperstructureGoal();
167}
168
169void AutonomousActor::SplineAuto() {
170 CHECK(test_spline_);
171
172 if (!test_spline_->WaitForPlan()) return;
173 test_spline_->Start();
174
175 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
176}
177
James Kuszmaulb5f11832024-03-15 22:30:59 -0700178void AutonomousActor::MobilityAndShoot() {
179 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
180
181 uint32_t initial_shot_count = shot_count();
182
183 CHECK(mobility_and_shoot_splines_);
184
185 auto &splines = *mobility_and_shoot_splines_;
186
187 AOS_LOG(INFO, "Going to preload");
188
189 // Always be auto-aiming.
190 Aim();
191
192 if (!WaitForPreloaded()) return;
193
194 AOS_LOG(INFO, "Starting to Move");
195
196 if (!splines[0].WaitForPlan()) return;
197
198 splines[0].Start();
199
200 if (!splines[0].WaitForSplineDistanceRemaining(0.05)) return;
201
202 AOS_LOG(
203 INFO, "Got there %lf s\nNow Shooting\n",
204 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
205
206 Shoot();
207
208 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(5))) return;
209
210 StopFiring();
211
212 AOS_LOG(
213 INFO, "Note fired at %lf seconds\n",
214 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
215}
216
217void AutonomousActor::FourPieceAuto() {
218 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
219
220 CHECK(four_piece_splines_);
221 auto &splines = *four_piece_splines_;
222
223 uint32_t initial_shot_count = shot_count();
224
225 // Always be aiming & firing.
226 Aim();
227 if (!WaitForPreloaded()) return;
228
James Kuszmaulb5f11832024-03-15 22:30:59 -0700229 Shoot();
230
231 AOS_LOG(
232 INFO, "Shooting Preloaded Note %lfs\n",
233 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
234
235 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
236
237 AOS_LOG(
238 INFO, "Shot first note %lfs\n",
239 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
240
241 Intake();
242 StopFiring();
243
244 AOS_LOG(
245 INFO, "Starting Spline 1 %lfs\n",
246 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
247
248 if (!splines[0].WaitForPlan()) return;
249
250 splines[0].Start();
251
252 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
253
254 if (!splines[1].WaitForPlan()) return;
255
256 AOS_LOG(
257 INFO, "Starting second spline %lfs\n",
258 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
259
260 splines[1].Start();
261
262 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
263
264 AOS_LOG(
265 INFO, "Finished second spline %lfs\n",
266 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
267
268 std::this_thread::sleep_for(chrono::milliseconds(250));
269
270 Shoot();
271
272 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
273 return;
274
275 AOS_LOG(
276 INFO, "Shot second note, starting drive %lfs\n",
277 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
278
279 if (!splines[2].WaitForPlan()) return;
280 splines[2].Start();
281
282 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
283
284 if (!WaitForNoteFired(initial_shot_count + 3, std::chrono::seconds(5)))
285 return;
286
287 AOS_LOG(
288 INFO, "Finished 4 notes at %lfs\n",
289 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
290
291 if (!FLAGS_do_fifth_piece) {
292 AOS_LOG(INFO, "Exitting early due to --nodo_fifth_piece");
293 return;
294 }
295
296 if (!splines[3].WaitForPlan()) return;
297 splines[3].Start();
298
299 if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
300
301 AOS_LOG(
302 INFO, "Got to 5th note at %lfs\n",
303 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
304
305 StopFiring();
306
307 if (!splines[4].WaitForPlan()) return;
308 splines[4].Start();
309
James Kuszmaulf2f95b32024-03-23 20:12:05 -0700310 if (!splines[4].WaitForSplineDistanceRemaining(0.01)) return;
James Kuszmaulb5f11832024-03-15 22:30:59 -0700311
312 AOS_LOG(
313 INFO, "Done with spline %lfs\n",
314 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
315
James Kuszmaulf2f95b32024-03-23 20:12:05 -0700316 std::this_thread::sleep_for(chrono::milliseconds(500));
James Kuszmaulb5f11832024-03-15 22:30:59 -0700317
318 AOS_LOG(
319 INFO, "Shooting last note! %lfs\n",
320 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
321
322 Shoot();
323
324 if (!WaitForNoteFired(initial_shot_count + 4, std::chrono::seconds(5)))
325 return;
326
327 AOS_LOG(
328 INFO, "Done %lfs\n",
329 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
330}
331
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800332void AutonomousActor::SendSuperstructureGoal() {
333 aos::Sender<control_loops::superstructure::GoalStatic>::StaticBuilder
334 goal_builder = superstructure_goal_sender_.MakeStaticBuilder();
335
336 goal_builder->set_intake_goal(intake_goal_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700337 if (intake_goal_ == control_loops::superstructure::IntakeGoal::INTAKE) {
338 goal_builder->set_intake_pivot(
339 control_loops::superstructure::IntakePivotGoal::DOWN);
340 } else {
341 goal_builder->set_intake_pivot(
342 control_loops::superstructure::IntakePivotGoal::UP);
343 }
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800344 goal_builder->set_note_goal(note_goal_);
345 goal_builder->set_fire(fire_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700346 goal_builder->set_climber_goal(
347 control_loops::superstructure::ClimberGoal::STOWED);
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800348
349 control_loops::superstructure::ShooterGoalStatic *shooter_goal =
350 goal_builder->add_shooter_goal();
351
352 shooter_goal->set_auto_aim(auto_aim_);
353 shooter_goal->set_preloaded(preloaded_);
354
355 goal_builder.CheckOk(goal_builder.Send());
356}
357
358void AutonomousActor::Intake() {
359 set_intake_goal(control_loops::superstructure::IntakeGoal::INTAKE);
360 set_note_goal(control_loops::superstructure::NoteGoal::CATAPULT);
361 SendSuperstructureGoal();
362}
363
364void AutonomousActor::Aim() {
365 set_auto_aim(true);
366 SendSuperstructureGoal();
367}
368
369void AutonomousActor::Shoot() {
370 set_fire(true);
371 SendSuperstructureGoal();
372}
373
James Kuszmaulb5f11832024-03-15 22:30:59 -0700374void AutonomousActor::StopFiring() {
375 set_fire(false);
376 SendSuperstructureGoal();
377}
378
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800379[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
380 set_preloaded(true);
381 SendSuperstructureGoal();
382
383 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
384 event_loop()->monotonic_now(),
385 aos::common::actions::kLoopOffset);
386
387 bool loaded = false;
388 while (!loaded) {
389 if (ShouldCancel()) {
390 return false;
391 }
392
393 phased_loop.SleepUntilNext();
394 superstructure_status_fetcher_.Fetch();
395 CHECK(superstructure_status_fetcher_.get() != nullptr);
396
397 loaded = (superstructure_status_fetcher_->shooter()->catapult_state() ==
398 control_loops::superstructure::CatapultState::LOADED);
399 }
400
401 set_preloaded(false);
402 SendSuperstructureGoal();
403
404 return true;
405}
406
James Kuszmaulb5f11832024-03-15 22:30:59 -0700407uint32_t AutonomousActor::shot_count() {
408 superstructure_status_fetcher_.Fetch();
409 return superstructure_status_fetcher_->shot_count();
410}
411
412[[nodiscard]] bool AutonomousActor::WaitForNoteFired(
413 uint32_t penultimate_target_shot_count, std::chrono::nanoseconds timeout) {
414 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
415 event_loop()->monotonic_now(),
416 aos::common::actions::kLoopOffset);
417 aos::monotonic_clock::time_point end_time =
418 event_loop()->monotonic_now() + timeout;
419 while (true) {
420 if (ShouldCancel()) {
421 return false;
422 }
423
424 phased_loop.SleepUntilNext();
425
426 if (shot_count() > penultimate_target_shot_count ||
427 event_loop()->monotonic_now() > end_time) {
428 return true;
429 }
430 }
431}
432
433[[nodiscard]] bool AutonomousActor::WaitForCatapultReady() {
434 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
435 event_loop()->monotonic_now(),
436 aos::common::actions::kLoopOffset);
437
438 bool loaded = false;
439 while (!loaded) {
440 if (ShouldCancel()) {
441 return false;
442 }
443
444 phased_loop.SleepUntilNext();
445 superstructure_status_fetcher_.Fetch();
446 CHECK(superstructure_status_fetcher_.get() != nullptr);
447
448 loaded = (superstructure_status_fetcher_->state() ==
449 control_loops::superstructure::SuperstructureState::READY);
450 }
451
452 SendSuperstructureGoal();
453
454 return true;
455}
456
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800457} // namespace y2024::autonomous