blob: 9b4f7f8297b82223ad257c919216910ca57428fd [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
229 std::this_thread::sleep_for(chrono::milliseconds(500));
230 Shoot();
231
232 AOS_LOG(
233 INFO, "Shooting Preloaded Note %lfs\n",
234 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
235
236 if (!WaitForNoteFired(initial_shot_count, std::chrono::seconds(2))) return;
237
238 AOS_LOG(
239 INFO, "Shot first note %lfs\n",
240 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
241
242 Intake();
243 StopFiring();
244
245 AOS_LOG(
246 INFO, "Starting Spline 1 %lfs\n",
247 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
248
249 if (!splines[0].WaitForPlan()) return;
250
251 splines[0].Start();
252
253 if (!splines[0].WaitForSplineDistanceRemaining(0.01)) return;
254
255 if (!splines[1].WaitForPlan()) return;
256
257 AOS_LOG(
258 INFO, "Starting second spline %lfs\n",
259 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
260
261 splines[1].Start();
262
263 if (!splines[1].WaitForSplineDistanceRemaining(0.01)) return;
264
265 AOS_LOG(
266 INFO, "Finished second spline %lfs\n",
267 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
268
269 std::this_thread::sleep_for(chrono::milliseconds(250));
270
271 Shoot();
272
273 if (!WaitForNoteFired(initial_shot_count + 1, std::chrono::seconds(2)))
274 return;
275
276 AOS_LOG(
277 INFO, "Shot second note, starting drive %lfs\n",
278 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
279
280 if (!splines[2].WaitForPlan()) return;
281 splines[2].Start();
282
283 if (!splines[2].WaitForSplineDistanceRemaining(0.01)) return;
284
285 if (!WaitForNoteFired(initial_shot_count + 3, std::chrono::seconds(5)))
286 return;
287
288 AOS_LOG(
289 INFO, "Finished 4 notes at %lfs\n",
290 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
291
292 if (!FLAGS_do_fifth_piece) {
293 AOS_LOG(INFO, "Exitting early due to --nodo_fifth_piece");
294 return;
295 }
296
297 if (!splines[3].WaitForPlan()) return;
298 splines[3].Start();
299
300 if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
301
302 AOS_LOG(
303 INFO, "Got to 5th note at %lfs\n",
304 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
305
306 StopFiring();
307
308 if (!splines[4].WaitForPlan()) return;
309 splines[4].Start();
310
311 if (!splines[4].WaitForSplineDistanceRemaining(0.05)) return;
312
313 AOS_LOG(
314 INFO, "Done with spline %lfs\n",
315 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
316
317 std::this_thread::sleep_for(chrono::milliseconds(300));
318
319 AOS_LOG(
320 INFO, "Shooting last note! %lfs\n",
321 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
322
323 Shoot();
324
325 if (!WaitForNoteFired(initial_shot_count + 4, std::chrono::seconds(5)))
326 return;
327
328 AOS_LOG(
329 INFO, "Done %lfs\n",
330 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
331}
332
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800333void AutonomousActor::SendSuperstructureGoal() {
334 aos::Sender<control_loops::superstructure::GoalStatic>::StaticBuilder
335 goal_builder = superstructure_goal_sender_.MakeStaticBuilder();
336
337 goal_builder->set_intake_goal(intake_goal_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700338 if (intake_goal_ == control_loops::superstructure::IntakeGoal::INTAKE) {
339 goal_builder->set_intake_pivot(
340 control_loops::superstructure::IntakePivotGoal::DOWN);
341 } else {
342 goal_builder->set_intake_pivot(
343 control_loops::superstructure::IntakePivotGoal::UP);
344 }
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800345 goal_builder->set_note_goal(note_goal_);
346 goal_builder->set_fire(fire_);
James Kuszmaulb5f11832024-03-15 22:30:59 -0700347 goal_builder->set_climber_goal(
348 control_loops::superstructure::ClimberGoal::STOWED);
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800349
350 control_loops::superstructure::ShooterGoalStatic *shooter_goal =
351 goal_builder->add_shooter_goal();
352
353 shooter_goal->set_auto_aim(auto_aim_);
354 shooter_goal->set_preloaded(preloaded_);
355
356 goal_builder.CheckOk(goal_builder.Send());
357}
358
359void AutonomousActor::Intake() {
360 set_intake_goal(control_loops::superstructure::IntakeGoal::INTAKE);
361 set_note_goal(control_loops::superstructure::NoteGoal::CATAPULT);
362 SendSuperstructureGoal();
363}
364
365void AutonomousActor::Aim() {
366 set_auto_aim(true);
367 SendSuperstructureGoal();
368}
369
370void AutonomousActor::Shoot() {
371 set_fire(true);
372 SendSuperstructureGoal();
373}
374
James Kuszmaulb5f11832024-03-15 22:30:59 -0700375void AutonomousActor::StopFiring() {
376 set_fire(false);
377 SendSuperstructureGoal();
378}
379
Filip Kujawa58ffbf32024-02-24 18:28:34 -0800380[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
381 set_preloaded(true);
382 SendSuperstructureGoal();
383
384 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
385 event_loop()->monotonic_now(),
386 aos::common::actions::kLoopOffset);
387
388 bool loaded = false;
389 while (!loaded) {
390 if (ShouldCancel()) {
391 return false;
392 }
393
394 phased_loop.SleepUntilNext();
395 superstructure_status_fetcher_.Fetch();
396 CHECK(superstructure_status_fetcher_.get() != nullptr);
397
398 loaded = (superstructure_status_fetcher_->shooter()->catapult_state() ==
399 control_loops::superstructure::CatapultState::LOADED);
400 }
401
402 set_preloaded(false);
403 SendSuperstructureGoal();
404
405 return true;
406}
407
James Kuszmaulb5f11832024-03-15 22:30:59 -0700408uint32_t AutonomousActor::shot_count() {
409 superstructure_status_fetcher_.Fetch();
410 return superstructure_status_fetcher_->shot_count();
411}
412
413[[nodiscard]] bool AutonomousActor::WaitForNoteFired(
414 uint32_t penultimate_target_shot_count, std::chrono::nanoseconds timeout) {
415 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
416 event_loop()->monotonic_now(),
417 aos::common::actions::kLoopOffset);
418 aos::monotonic_clock::time_point end_time =
419 event_loop()->monotonic_now() + timeout;
420 while (true) {
421 if (ShouldCancel()) {
422 return false;
423 }
424
425 phased_loop.SleepUntilNext();
426
427 if (shot_count() > penultimate_target_shot_count ||
428 event_loop()->monotonic_now() > end_time) {
429 return true;
430 }
431 }
432}
433
434[[nodiscard]] bool AutonomousActor::WaitForCatapultReady() {
435 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
436 event_loop()->monotonic_now(),
437 aos::common::actions::kLoopOffset);
438
439 bool loaded = false;
440 while (!loaded) {
441 if (ShouldCancel()) {
442 return false;
443 }
444
445 phased_loop.SleepUntilNext();
446 superstructure_status_fetcher_.Fetch();
447 CHECK(superstructure_status_fetcher_.get() != nullptr);
448
449 loaded = (superstructure_status_fetcher_->state() ==
450 control_loops::superstructure::SuperstructureState::READY);
451 }
452
453 SendSuperstructureGoal();
454
455 return true;
456}
457
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800458} // namespace y2024::autonomous