blob: e1b4e1d5bd38d5d3785efeca8ae6d6287d6ebf07 [file] [log] [blame]
Maxwell Hendersonad312342023-01-10 12:07:47 -08001#include "y2023/autonomous/autonomous_actor.h"
2
3#include <chrono>
4#include <cinttypes>
5#include <cmath>
6
7#include "aos/logging/logging.h"
Maxwell Henderson64f37452023-03-11 13:39:21 -08008#include "aos/util/math.h"
Maxwell Hendersonad312342023-01-10 12:07:47 -08009#include "frc971/control_loops/drivetrain/localizer_generated.h"
Maxwell Henderson64f37452023-03-11 13:39:21 -080010#include "y2023/autonomous/auto_splines.h"
11#include "y2023/constants.h"
Maxwell Hendersonad312342023-01-10 12:07:47 -080012#include "y2023/control_loops/drivetrain/drivetrain_base.h"
Maxwell Henderson64f37452023-03-11 13:39:21 -080013#include "y2023/control_loops/superstructure/arm/generated_graph.h"
Maxwell Hendersonad312342023-01-10 12:07:47 -080014
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -070015DEFINE_bool(spline_auto, false, "Run simple test S-spline auto mode.");
Maxwell Henderson64f37452023-03-11 13:39:21 -080016DEFINE_bool(charged_up, true, "If true run charged up autonomous mode");
Maxwell Henderson25378832023-04-07 14:37:41 -070017DEFINE_bool(charged_up_cable, false, "If true run cable side autonomous mode");
James Kuszmaul713c5ce2023-03-04 18:23:24 -080018
Maxwell Hendersonad312342023-01-10 12:07:47 -080019namespace y2023 {
Maxwell Henderson64f37452023-03-11 13:39:21 -080020namespace autonomous {
Maxwell Hendersonad312342023-01-10 12:07:47 -080021
Maxwell Hendersonad312342023-01-10 12:07:47 -080022using ::frc971::ProfileParametersT;
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -070023
24ProfileParametersT MakeProfileParameters(float max_velocity,
25 float max_acceleration) {
26 ProfileParametersT result;
27 result.max_velocity = max_velocity;
28 result.max_acceleration = max_acceleration;
29 return result;
30}
31
32using ::aos::monotonic_clock;
33using frc971::CreateProfileParameters;
34using ::frc971::ProfileParametersT;
35using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
36using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
Maxwell Hendersonad312342023-01-10 12:07:47 -080037using frc971::control_loops::drivetrain::LocalizerControl;
38namespace chrono = ::std::chrono;
39
40AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
41 : frc971::autonomous::BaseAutonomousActor(
James Kuszmaul713c5ce2023-03-04 18:23:24 -080042 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
43 localizer_control_sender_(
44 event_loop->MakeSender<
45 ::frc971::control_loops::drivetrain::LocalizerControl>(
46 "/drivetrain")),
47 joystick_state_fetcher_(
48 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
49 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
Maxwell Henderson64f37452023-03-11 13:39:21 -080050 auto_splines_(),
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -070051 arm_goal_position_(control_loops::superstructure::arm::StartingIndex()),
52 superstructure_goal_sender_(
53 event_loop->MakeSender<::y2023::control_loops::superstructure::Goal>(
54 "/superstructure")),
55 superstructure_status_fetcher_(
56 event_loop
57 ->MakeFetcher<::y2023::control_loops::superstructure::Status>(
58 "/superstructure")),
Maxwell Henderson64f37452023-03-11 13:39:21 -080059 points_(control_loops::superstructure::arm::PointList()) {
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -070060 drivetrain_status_fetcher_.Fetch();
James Kuszmaul713c5ce2023-03-04 18:23:24 -080061 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
62
63 event_loop->OnRun([this, event_loop]() {
64 replan_timer_->Setup(event_loop->monotonic_now());
65 button_poll_->Setup(event_loop->monotonic_now(), chrono::milliseconds(50));
66 });
67
68 // TODO(james): Really need to refactor this code since we keep using it.
69 button_poll_ = event_loop->AddTimer([this]() {
70 const aos::monotonic_clock::time_point now =
71 this->event_loop()->context().monotonic_event_time;
72 if (robot_state_fetcher_.Fetch()) {
73 if (robot_state_fetcher_->user_button()) {
74 user_indicated_safe_to_reset_ = true;
75 MaybeSendStartingPosition();
76 }
77 }
78 if (joystick_state_fetcher_.Fetch()) {
79 if (joystick_state_fetcher_->has_alliance() &&
80 (joystick_state_fetcher_->alliance() != alliance_)) {
81 alliance_ = joystick_state_fetcher_->alliance();
82 is_planned_ = false;
Maxwell Henderson64f37452023-03-11 13:39:21 -080083 // Only kick the planning out by 2 seconds. If we end up enabled in
84 // that second, then we will kick it out further based on the code
85 // below.
James Kuszmaul713c5ce2023-03-04 18:23:24 -080086 replan_timer_->Setup(now + std::chrono::seconds(2));
87 }
88 if (joystick_state_fetcher_->enabled()) {
89 if (!is_planned_) {
90 // Only replan once we've been disabled for 5 seconds.
91 replan_timer_->Setup(now + std::chrono::seconds(5));
92 }
93 }
94 }
95 });
96}
97
98void AutonomousActor::Replan() {
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -070099 if (!drivetrain_status_fetcher_.Fetch()) {
100 replan_timer_->Setup(event_loop()->monotonic_now() + chrono::seconds(1));
101 AOS_LOG(INFO, "Drivetrain not up, replanning in 1 second");
102 return;
103 }
104
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800105 if (alliance_ == aos::Alliance::kInvalid) {
106 return;
107 }
108 sent_starting_position_ = false;
109 if (FLAGS_spline_auto) {
110 test_spline_ =
111 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
112 std::placeholders::_1, alliance_),
113 SplineDirection::kForward);
114
115 starting_position_ = test_spline_->starting_position();
Maxwell Henderson64f37452023-03-11 13:39:21 -0800116 } else if (FLAGS_charged_up) {
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700117 AOS_LOG(INFO, "Charged up replanning!");
Maxwell Henderson64f37452023-03-11 13:39:21 -0800118 charged_up_splines_ = {
119 PlanSpline(std::bind(&AutonomousSplines::Spline1, &auto_splines_,
120 std::placeholders::_1, alliance_),
121 SplineDirection::kBackward),
122 PlanSpline(std::bind(&AutonomousSplines::Spline2, &auto_splines_,
123 std::placeholders::_1, alliance_),
124 SplineDirection::kForward),
125 PlanSpline(std::bind(&AutonomousSplines::Spline3, &auto_splines_,
126 std::placeholders::_1, alliance_),
127 SplineDirection::kBackward),
128 PlanSpline(std::bind(&AutonomousSplines::Spline4, &auto_splines_,
129 std::placeholders::_1, alliance_),
Maxwell Henderson25378832023-04-07 14:37:41 -0700130 SplineDirection::kForward)};
Maxwell Henderson64f37452023-03-11 13:39:21 -0800131
132 starting_position_ = charged_up_splines_.value()[0].starting_position();
133 CHECK(starting_position_);
Maxwell Henderson25378832023-04-07 14:37:41 -0700134 } else if (FLAGS_charged_up_cable) {
135 charged_up_cable_splines_ = {
136 PlanSpline(std::bind(&AutonomousSplines::SplineCable1, &auto_splines_,
137 std::placeholders::_1, alliance_),
138 SplineDirection::kBackward),
139 PlanSpline(std::bind(&AutonomousSplines::SplineCable2, &auto_splines_,
140 std::placeholders::_1, alliance_),
141 SplineDirection::kForward),
142 PlanSpline(std::bind(&AutonomousSplines::SplineCable3, &auto_splines_,
143 std::placeholders::_1, alliance_),
144 SplineDirection::kBackward),
145 PlanSpline(std::bind(&AutonomousSplines::SplineCable4, &auto_splines_,
146 std::placeholders::_1, alliance_),
147 SplineDirection::kForward)};
148
149 starting_position_ =
150 charged_up_cable_splines_.value()[0].starting_position();
151 CHECK(starting_position_);
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800152 }
153
154 is_planned_ = true;
155
156 MaybeSendStartingPosition();
157}
158
159void AutonomousActor::MaybeSendStartingPosition() {
160 if (is_planned_ && user_indicated_safe_to_reset_ &&
161 !sent_starting_position_) {
162 CHECK(starting_position_);
163 SendStartingPosition(starting_position_.value());
164 }
165}
Maxwell Hendersonad312342023-01-10 12:07:47 -0800166
167void AutonomousActor::Reset() {
168 InitializeEncoders();
169 ResetDrivetrain();
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800170
171 joystick_state_fetcher_.Fetch();
172 CHECK(joystick_state_fetcher_.get() != nullptr)
173 << "Expect at least one JoystickState message before running auto...";
174 alliance_ = joystick_state_fetcher_->alliance();
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700175
176 wrist_goal_ = 0.0;
177 roller_goal_ = control_loops::superstructure::RollerGoal::IDLE;
178 arm_goal_position_ = control_loops::superstructure::arm::StartingIndex();
179 preloaded_ = false;
180 SendSuperstructureGoal();
Maxwell Hendersonad312342023-01-10 12:07:47 -0800181}
182
183bool AutonomousActor::RunAction(
184 const ::frc971::autonomous::AutonomousActionParams *params) {
185 Reset();
186
187 AOS_LOG(INFO, "Params are %d\n", params->mode());
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800188
189 if (!user_indicated_safe_to_reset_) {
190 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
191 CHECK(starting_position_);
192 SendStartingPosition(starting_position_.value());
193 }
Maxwell Henderson64f37452023-03-11 13:39:21 -0800194 // Clear this so that we don't accidentally resend things as soon as we
195 // replan later.
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800196 user_indicated_safe_to_reset_ = false;
197 is_planned_ = false;
198 starting_position_.reset();
199
200 AOS_LOG(INFO, "Params are %d\n", params->mode());
201 if (alliance_ == aos::Alliance::kInvalid) {
202 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
203 return false;
204 }
205 if (FLAGS_spline_auto) {
206 SplineAuto();
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700207 } else if (FLAGS_charged_up) {
208 ChargedUp();
Austin Schuh8c9d2d02023-04-09 20:05:42 -0700209 } else if (FLAGS_charged_up_cable) {
210 ChargedUpCableSide();
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800211 } else {
212 AOS_LOG(WARNING, "No auto mode selected.");
213 }
Maxwell Hendersonad312342023-01-10 12:07:47 -0800214 return true;
215}
216
James Kuszmaul713c5ce2023-03-04 18:23:24 -0800217void AutonomousActor::SplineAuto() {
218 CHECK(test_spline_);
219
220 if (!test_spline_->WaitForPlan()) return;
221 test_spline_->Start();
222
223 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
224}
225
226void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
227 // Set up the starting position for the blue alliance.
228
229 auto builder = localizer_control_sender_.MakeBuilder();
230
231 LocalizerControl::Builder localizer_control_builder =
232 builder.MakeBuilder<LocalizerControl>();
233 localizer_control_builder.add_x(start(0));
234 localizer_control_builder.add_y(start(1));
235 localizer_control_builder.add_theta(start(2));
236 localizer_control_builder.add_theta_uncertainty(0.00001);
237 AOS_LOG(INFO, "User button pressed, x: %f y: %f theta: %f", start(0),
238 start(1), start(2));
239 if (builder.Send(localizer_control_builder.Finish()) !=
240 aos::RawSender::Error::kOk) {
241 AOS_LOG(ERROR, "Failed to reset localizer.\n");
242 }
243}
244
Maxwell Henderson25378832023-04-07 14:37:41 -0700245// Charged Up 3 Game Object Autonomous (non-cable side)
Maxwell Henderson64f37452023-03-11 13:39:21 -0800246void AutonomousActor::ChargedUp() {
247 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
248
249 CHECK(charged_up_splines_);
250
251 auto &splines = *charged_up_splines_;
252
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700253 AOS_LOG(INFO, "Going to preload");
254
Maxwell Henderson64f37452023-03-11 13:39:21 -0800255 // Tell the superstructure a cone was preloaded
256 if (!WaitForPreloaded()) return;
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700257 AOS_LOG(INFO, "Moving arm");
Maxwell Henderson64f37452023-03-11 13:39:21 -0800258
259 // Place first cone on mid level
260 MidConeScore();
261
262 // Wait until the arm is at the goal to spit
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700263 if (!WaitForArmGoal(0.10)) return;
Maxwell Henderson64f37452023-03-11 13:39:21 -0800264 Spit();
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700265 if (!WaitForArmGoal(0.01)) return;
266
267 std::this_thread::sleep_for(chrono::milliseconds(100));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800268
269 AOS_LOG(
270 INFO, "Placed first cone %lf s\n",
271 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
272
273 // Drive and intake the cube nearest to the starting zone
274 if (!splines[0].WaitForPlan()) return;
275 splines[0].Start();
276
277 // Move arm into position to pickup a cube and start cube intake
278 PickupCube();
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700279
280 std::this_thread::sleep_for(chrono::milliseconds(500));
281
Maxwell Henderson64f37452023-03-11 13:39:21 -0800282 IntakeCube();
283
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700284 AOS_LOG(
285 INFO, "Turning on rollers %lf s\n",
286 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
287
Maxwell Henderson64f37452023-03-11 13:39:21 -0800288 if (!splines[0].WaitForSplineDistanceRemaining(0.02)) return;
289
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700290 AOS_LOG(
291 INFO, "Got there %lf s\n",
292 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
293
Maxwell Henderson64f37452023-03-11 13:39:21 -0800294 // Drive back to grid and place cube on high level
295 if (!splines[1].WaitForPlan()) return;
296 splines[1].Start();
297
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700298 std::this_thread::sleep_for(chrono::milliseconds(300));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800299 HighCubeScore();
300
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700301 if (!splines[1].WaitForSplineDistanceRemaining(0.08)) return;
302 AOS_LOG(
303 INFO, "Back for first cube %lf s\n",
304 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800305
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700306 if (!WaitForArmGoal(0.10)) return;
307
308 AOS_LOG(
309 INFO, "Arm in place for first cube %lf s\n",
310 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
311
Maxwell Henderson64f37452023-03-11 13:39:21 -0800312 Spit();
313
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700314 if (!splines[1].WaitForSplineDistanceRemaining(0.08)) return;
315
316 AOS_LOG(
317 INFO, "Finished spline back %lf s\n",
318 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
319
320 if (!WaitForArmGoal(0.05)) return;
321
Austin Schuha7c3bc62023-04-16 19:46:23 -0700322 std::this_thread::sleep_for(chrono::milliseconds(100));
323
Maxwell Henderson64f37452023-03-11 13:39:21 -0800324 AOS_LOG(
325 INFO, "Placed first cube %lf s\n",
326 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
327
328 // Drive and intake the cube second nearest to the starting zone
329 if (!splines[2].WaitForPlan()) return;
330 splines[2].Start();
331
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700332 std::this_thread::sleep_for(chrono::milliseconds(200));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800333 PickupCube();
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700334
335 std::this_thread::sleep_for(chrono::milliseconds(500));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800336 IntakeCube();
337
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700338 if (!splines[2].WaitForSplineDistanceRemaining(0.05)) return;
339 AOS_LOG(
340 INFO, "Picked up second cube %lf s\n",
341 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800342
343 // Drive back to grid and place object on mid level
344 if (!splines[3].WaitForPlan()) return;
345 splines[3].Start();
346
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700347 AOS_LOG(
348 INFO, "Driving back %lf s\n",
349 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
350
Maxwell Henderson64f37452023-03-11 13:39:21 -0800351 MidCubeScore();
352
Austin Schuh700bfff2023-04-05 19:45:55 -0700353 if (!splines[3].WaitForSplineDistanceRemaining(0.07)) return;
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700354 AOS_LOG(
355 INFO, "Got back from second cube at %lf s\n",
356 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson64f37452023-03-11 13:39:21 -0800357
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700358 if (!WaitForArmGoal(0.05)) return;
Maxwell Henderson64f37452023-03-11 13:39:21 -0800359 Spit();
360
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700361 if (!splines[3].WaitForSplineDistanceRemaining(0.02)) return;
362
Maxwell Henderson64f37452023-03-11 13:39:21 -0800363 AOS_LOG(
364 INFO, "Placed second cube %lf s\n",
365 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700366 InitializeEncoders();
Maxwell Henderson64f37452023-03-11 13:39:21 -0800367
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700368 const ProfileParametersT kDrive = MakeProfileParameters(2.0, 4.0);
369 const ProfileParametersT kTurn = MakeProfileParameters(3.0, 4.5);
370 StartDrive(0.0, 0.0, kDrive, kTurn);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800371
Austin Schuh700bfff2023-04-05 19:45:55 -0700372 std::this_thread::sleep_for(chrono::milliseconds(100));
373
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700374 {
375 double side_scalar = (alliance_ == aos::Alliance::kRed) ? 1.0 : -1.0;
376 StartDrive(6.33 - std::abs(X()), 0.0, kDrive, kTurn);
377 if (!WaitForDriveProfileNear(0.01)) return;
378
379 AOS_LOG(
380 INFO, "Done backing up %lf s\n",
381 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
382
Austin Schuha7c3bc62023-04-16 19:46:23 -0700383 const ProfileParametersT kInPlaceTurn = MakeProfileParameters(2.7, 8.0);
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700384 StartDrive(0.0, aos::math::NormalizeAngle(M_PI / 2.0 - Theta()), kDrive,
385 kInPlaceTurn);
386
387 std::this_thread::sleep_for(chrono::milliseconds(400));
388 StopSpitting();
389
390 AOS_LOG(
391 INFO, "Roller off %lf s\n",
392 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
393
Austin Schuh700bfff2023-04-05 19:45:55 -0700394 if (!WaitForTurnProfileNear(0.6)) return;
395 AOS_LOG(
396 INFO, "Balance arm %lf s\n",
397 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
398
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700399 Balance();
Austin Schuh700bfff2023-04-05 19:45:55 -0700400 if (!WaitForTurnProfileNear(0.001)) return;
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700401
402 AOS_LOG(
403 INFO, "Done turning %lf s\n",
404 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
405
406 const ProfileParametersT kDrive = MakeProfileParameters(1.4, 3.0);
407 const ProfileParametersT kFinalTurn = MakeProfileParameters(3.0, 4.5);
Austin Schuh700bfff2023-04-05 19:45:55 -0700408 const double kDriveDistance = 3.11;
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700409 StartDrive(-kDriveDistance, 0.0, kDrive, kFinalTurn);
410
411 const ProfileParametersT kFastTurn = MakeProfileParameters(5.0, 8.0);
412 if (!WaitForDriveProfileNear(kDriveDistance - 0.4)) return;
413
414 AOS_LOG(
415 INFO, "Turning %lf s\n",
416 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
417 StartDrive(0.0, -side_scalar * M_PI / 2.0, kDrive, kFastTurn);
418 if (!WaitForDriveProfileDone()) return;
419 if (!WaitForTurnProfileDone()) return;
420 AOS_LOG(
421 INFO, "Done %lf s\n",
422 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
423 }
Maxwell Henderson64f37452023-03-11 13:39:21 -0800424}
425
Maxwell Henderson25378832023-04-07 14:37:41 -0700426// Charged Up 3 Game Object Autonomous (cable side)
427void AutonomousActor::ChargedUpCableSide() {
428 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
429
430 CHECK(charged_up_cable_splines_);
431
432 auto &splines = *charged_up_cable_splines_;
433
434 AOS_LOG(INFO, "Going to preload");
435
436 // Tell the superstructure a cone was preloaded
437 if (!WaitForPreloaded()) return;
438 AOS_LOG(INFO, "Moving arm");
439
440 // Place first cone on mid level
441 MidConeScore();
442
443 // Wait until the arm is at the goal to spit
444 if (!WaitForArmGoal(0.10)) return;
445 Spit();
446 if (!WaitForArmGoal(0.01)) return;
447
448 std::this_thread::sleep_for(chrono::milliseconds(100));
449
450 AOS_LOG(
451 INFO, "Placed first cone %lf s\n",
452 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
453
454 // Drive and intake the cube nearest to the starting zone
455 if (!splines[0].WaitForPlan()) return;
456 splines[0].Start();
457
458 // Move arm into position to pickup a cube and start cube intake
459 PickupCube();
460
461 std::this_thread::sleep_for(chrono::milliseconds(500));
462
463 IntakeCube();
464
465 AOS_LOG(
466 INFO, "Turning on rollers %lf s\n",
467 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
468
469 if (!splines[0].WaitForSplineDistanceRemaining(0.02)) return;
470
471 AOS_LOG(
472 INFO, "Got there %lf s\n",
473 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
474
475 // Drive back to grid and place cube on high level
476 if (!splines[1].WaitForPlan()) return;
477 splines[1].Start();
478
479 std::this_thread::sleep_for(chrono::milliseconds(300));
Austin Schuhdd128822023-04-09 22:19:06 -0700480 Neutral();
481
482 if (!splines[1].WaitForSplineDistanceTraveled(3.2)) return;
Maxwell Henderson25378832023-04-07 14:37:41 -0700483 HighCubeScore();
Austin Schuhdd128822023-04-09 22:19:06 -0700484 AOS_LOG(
485 INFO, "Extending arm %lf s\n",
486 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson25378832023-04-07 14:37:41 -0700487
488 if (!splines[1].WaitForSplineDistanceRemaining(0.08)) return;
489 AOS_LOG(
490 INFO, "Back for first cube %lf s\n",
491 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
492
493 if (!WaitForArmGoal(0.10)) return;
494
495 AOS_LOG(
496 INFO, "Arm in place for first cube %lf s\n",
497 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
498
499 Spit();
500
501 if (!splines[1].WaitForSplineDistanceRemaining(0.08)) return;
502
503 AOS_LOG(
504 INFO, "Finished spline back %lf s\n",
505 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
506
507 if (!WaitForArmGoal(0.05)) return;
508
509 AOS_LOG(
510 INFO, "Placed first cube %lf s\n",
511 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
512
513 // Drive and intake the cube second nearest to the starting zone
514 if (!splines[2].WaitForPlan()) return;
515 splines[2].Start();
516
517 std::this_thread::sleep_for(chrono::milliseconds(200));
518 PickupCube();
519
520 std::this_thread::sleep_for(chrono::milliseconds(500));
521 IntakeCube();
522
523 if (!splines[2].WaitForSplineDistanceRemaining(0.05)) return;
524 AOS_LOG(
525 INFO, "Picked up second cube %lf s\n",
526 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
527
528 // Drive back to grid and place object on mid level
529 if (!splines[3].WaitForPlan()) return;
530 splines[3].Start();
531
Austin Schuhdd128822023-04-09 22:19:06 -0700532 std::this_thread::sleep_for(chrono::milliseconds(400));
533 Neutral();
534
Maxwell Henderson25378832023-04-07 14:37:41 -0700535 AOS_LOG(
536 INFO, "Driving back %lf s\n",
537 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
538
Austin Schuhdd128822023-04-09 22:19:06 -0700539 if (!splines[3].WaitForSplineDistanceTraveled(3.5)) return;
540 AOS_LOG(
541 INFO, "Extending arm %lf s\n",
542 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson25378832023-04-07 14:37:41 -0700543 MidCubeScore();
544
545 if (!splines[3].WaitForSplineDistanceRemaining(0.07)) return;
546 AOS_LOG(
547 INFO, "Got back from second cube at %lf s\n",
548 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
549
550 if (!WaitForArmGoal(0.05)) return;
551 Spit();
552
553 if (!splines[3].WaitForSplineDistanceRemaining(0.02)) return;
554
555 AOS_LOG(
556 INFO, "Placed second cube %lf s\n",
557 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Austin Schuh8c9d2d02023-04-09 20:05:42 -0700558
559 std::this_thread::sleep_for(chrono::milliseconds(200));
560 Neutral();
Austin Schuha7c3bc62023-04-16 19:46:23 -0700561 AOS_LOG(
562 INFO, "Going to neutral %lf s\n",
563 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
564
565 if (!WaitForArmGoal(0.05)) return;
566 AOS_LOG(
567 INFO, "Done at neutral %lf s\n",
568 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
Maxwell Henderson25378832023-04-07 14:37:41 -0700569}
570
Maxwell Henderson64f37452023-03-11 13:39:21 -0800571void AutonomousActor::SendSuperstructureGoal() {
572 auto builder = superstructure_goal_sender_.MakeBuilder();
573
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700574 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
575 wrist_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
576 *builder.fbb(), wrist_goal_,
577 CreateProfileParameters(*builder.fbb(), 12.0, 90.0));
578
Maxwell Henderson64f37452023-03-11 13:39:21 -0800579 control_loops::superstructure::Goal::Builder superstructure_builder =
580 builder.MakeBuilder<control_loops::superstructure::Goal>();
581
582 superstructure_builder.add_arm_goal_position(arm_goal_position_);
583 superstructure_builder.add_preloaded_with_cone(preloaded_);
584 superstructure_builder.add_roller_goal(roller_goal_);
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700585 superstructure_builder.add_wrist(wrist_offset);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800586
587 if (builder.Send(superstructure_builder.Finish()) !=
588 aos::RawSender::Error::kOk) {
589 AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
590 }
591}
592
593[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
594 set_preloaded(true);
595 SendSuperstructureGoal();
596
597 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
598 event_loop()->monotonic_now(),
599 ActorBase::kLoopOffset);
600
601 bool loaded = false;
602 while (!loaded) {
603 if (ShouldCancel()) {
604 return false;
605 }
606
607 phased_loop.SleepUntilNext();
608 superstructure_status_fetcher_.Fetch();
609 CHECK(superstructure_status_fetcher_.get() != nullptr);
610
611 loaded = (superstructure_status_fetcher_->end_effector_state() ==
612 control_loops::superstructure::EndEffectorState::LOADED);
613 }
614
615 set_preloaded(false);
616 SendSuperstructureGoal();
617
618 return true;
619}
620
621void AutonomousActor::MidConeScore() {
622 set_arm_goal_position(
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700623 control_loops::superstructure::arm::ScoreFrontMidConeUpAutoIndex());
624 set_wrist_goal(0.0);
625 SendSuperstructureGoal();
626}
627
628void AutonomousActor::Neutral() {
629 set_arm_goal_position(control_loops::superstructure::arm::NeutralIndex());
Austin Schuha7c3bc62023-04-16 19:46:23 -0700630 set_wrist_goal(1.0);
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700631 SendSuperstructureGoal();
632}
633
634void AutonomousActor::Balance() {
635 set_arm_goal_position(
Austin Schuh700bfff2023-04-05 19:45:55 -0700636 control_loops::superstructure::arm::ScoreFrontLowCubeIndex());
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700637 set_wrist_goal(0.0);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800638 SendSuperstructureGoal();
639}
640
641void AutonomousActor::HighCubeScore() {
642 set_arm_goal_position(
643 control_loops::superstructure::arm::ScoreFrontHighCubeIndex());
Austin Schuha7c3bc62023-04-16 19:46:23 -0700644 set_wrist_goal(1.0);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800645 SendSuperstructureGoal();
646}
647
648void AutonomousActor::MidCubeScore() {
649 set_arm_goal_position(
650 control_loops::superstructure::arm::ScoreFrontMidCubeIndex());
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700651 set_wrist_goal(1.0);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800652 SendSuperstructureGoal();
653}
654
655void AutonomousActor::PickupCube() {
656 set_arm_goal_position(
657 control_loops::superstructure::arm::GroundPickupBackCubeIndex());
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700658 set_wrist_goal(1.0);
Maxwell Henderson64f37452023-03-11 13:39:21 -0800659 SendSuperstructureGoal();
660}
661
662void AutonomousActor::Spit() {
663 set_roller_goal(control_loops::superstructure::RollerGoal::SPIT);
664 SendSuperstructureGoal();
665}
666
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700667void AutonomousActor::StopSpitting() {
668 set_roller_goal(control_loops::superstructure::RollerGoal::IDLE);
669 SendSuperstructureGoal();
670}
671
Maxwell Henderson64f37452023-03-11 13:39:21 -0800672void AutonomousActor::IntakeCube() {
673 set_roller_goal(control_loops::superstructure::RollerGoal::INTAKE_CUBE);
674 SendSuperstructureGoal();
675}
676
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700677[[nodiscard]] bool AutonomousActor::WaitForArmGoal(double distance_to_go) {
678 constexpr double kEpsTheta = 0.10;
Maxwell Henderson64f37452023-03-11 13:39:21 -0800679
680 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
681 event_loop()->monotonic_now(),
682 ActorBase::kLoopOffset);
683
684 bool at_goal = false;
685 while (!at_goal) {
686 if (ShouldCancel()) {
687 return false;
688 }
689
690 phased_loop.SleepUntilNext();
691 superstructure_status_fetcher_.Fetch();
692 CHECK(superstructure_status_fetcher_.get() != nullptr);
693
Maxwell Henderson3d0beaf2023-03-23 11:32:44 -0700694 at_goal = (arm_goal_position_ ==
695 superstructure_status_fetcher_->arm()->current_node() &&
696 superstructure_status_fetcher_->arm()->path_distance_to_go() <
697 distance_to_go) &&
Maxwell Henderson64f37452023-03-11 13:39:21 -0800698 (std::abs(wrist_goal_ -
699 superstructure_status_fetcher_->wrist()->position()) <
700 kEpsTheta);
701 }
702
Maxwell Henderson64f37452023-03-11 13:39:21 -0800703 return true;
704}
705
706} // namespace autonomous
Maxwell Hendersonad312342023-01-10 12:07:47 -0800707} // namespace y2023