blob: ca109e0722b3645fdfb194b8cc4606b9c4c8dce1 [file] [log] [blame]
milind-u086d7262022-01-19 20:44:18 -08001#include "y2022/actors/autonomous_actor.h"
2
3#include <chrono>
4#include <cinttypes>
5#include <cmath>
6
7#include "aos/logging/logging.h"
Ravago Jones81e50632022-03-11 16:23:51 -08008#include "aos/network/team_number.h"
9#include "aos/util/math.h"
milind-u086d7262022-01-19 20:44:18 -080010#include "frc971/control_loops/drivetrain/localizer_generated.h"
Ravago Jones81e50632022-03-11 16:23:51 -080011#include "y2022/actors/auto_splines.h"
12#include "y2022/constants.h"
milind-u086d7262022-01-19 20:44:18 -080013#include "y2022/control_loops/drivetrain/drivetrain_base.h"
14
Ravago Jones81e50632022-03-11 16:23:51 -080015DEFINE_bool(spline_auto, false, "If true, define a spline autonomous mode");
Austin Schuh42d7e5f2022-03-16 23:35:09 -070016DEFINE_bool(rapid_react, true,
Milind Upadhyaya7793962022-03-11 19:39:36 -080017 "If true, run the main rapid react autonomous mode");
Ravago Jones81e50632022-03-11 16:23:51 -080018
milind-u086d7262022-01-19 20:44:18 -080019namespace y2022 {
20namespace actors {
Ravago Jones81e50632022-03-11 16:23:51 -080021namespace {
Henry Speisere23d4de2022-04-05 16:47:47 -070022constexpr double kExtendIntakeGoal = -0.10;
Ravago Jones81e50632022-03-11 16:23:51 -080023constexpr double kRetractIntakeGoal = 1.47;
Austin Schuh42d7e5f2022-03-16 23:35:09 -070024constexpr double kIntakeRollerVoltage = 12.0;
Ravago Jones81e50632022-03-11 16:23:51 -080025constexpr double kRollerVoltage = 12.0;
26constexpr double kCatapultReturnPosition = -0.908;
27} // namespace
milind-u086d7262022-01-19 20:44:18 -080028
29using ::aos::monotonic_clock;
Ravago Jones81e50632022-03-11 16:23:51 -080030using frc971::CreateProfileParameters;
milind-u086d7262022-01-19 20:44:18 -080031using ::frc971::ProfileParametersT;
Ravago Jones81e50632022-03-11 16:23:51 -080032using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
33using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
milind-u086d7262022-01-19 20:44:18 -080034using frc971::control_loops::drivetrain::LocalizerControl;
Ravago Jones81e50632022-03-11 16:23:51 -080035
milind-u086d7262022-01-19 20:44:18 -080036namespace chrono = ::std::chrono;
37
38AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
39 : frc971::autonomous::BaseAutonomousActor(
Ravago Jones81e50632022-03-11 16:23:51 -080040 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
41 localizer_control_sender_(
42 event_loop->MakeSender<
43 ::frc971::control_loops::drivetrain::LocalizerControl>(
44 "/drivetrain")),
45 superstructure_goal_sender_(
46 event_loop->MakeSender<control_loops::superstructure::Goal>(
47 "/superstructure")),
48 superstructure_status_fetcher_(
49 event_loop->MakeFetcher<control_loops::superstructure::Status>(
50 "/superstructure")),
51 joystick_state_fetcher_(
52 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
53 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
54 auto_splines_() {
55 set_max_drivetrain_voltage(12.0);
56 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
57 event_loop->OnRun([this, event_loop]() {
58 replan_timer_->Setup(event_loop->monotonic_now());
59 button_poll_->Setup(event_loop->monotonic_now(), chrono::milliseconds(50));
60 });
61
62 button_poll_ = event_loop->AddTimer([this]() {
63 const aos::monotonic_clock::time_point now =
64 this->event_loop()->context().monotonic_event_time;
65 if (robot_state_fetcher_.Fetch()) {
66 if (robot_state_fetcher_->user_button()) {
67 user_indicated_safe_to_reset_ = true;
68 MaybeSendStartingPosition();
69 }
70 }
71 if (joystick_state_fetcher_.Fetch()) {
72 if (joystick_state_fetcher_->has_alliance() &&
73 (joystick_state_fetcher_->alliance() != alliance_)) {
74 alliance_ = joystick_state_fetcher_->alliance();
75 is_planned_ = false;
76 // Only kick the planning out by 2 seconds. If we end up enabled in that
77 // second, then we will kick it out further based on the code below.
78 replan_timer_->Setup(now + std::chrono::seconds(2));
79 }
80 if (joystick_state_fetcher_->enabled()) {
81 if (!is_planned_) {
82 // Only replan once we've been disabled for 5 seconds.
83 replan_timer_->Setup(now + std::chrono::seconds(5));
84 }
85 }
86 }
87 });
88}
89
90void AutonomousActor::Replan() {
91 LOG(INFO) << "Alliance " << static_cast<int>(alliance_);
92 if (alliance_ == aos::Alliance::kInvalid) {
93 return;
94 }
95 sent_starting_position_ = false;
96 if (FLAGS_spline_auto) {
97 test_spline_ =
98 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
99 std::placeholders::_1, alliance_),
100 SplineDirection::kForward);
101
102 starting_position_ = test_spline_->starting_position();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800103 } else if (FLAGS_rapid_react) {
104 rapid_react_splines_ = {
105 PlanSpline(std::bind(&AutonomousSplines::Spline1, &auto_splines_,
106 std::placeholders::_1, alliance_),
Henry Speiser09e8da92022-03-14 20:58:45 -0700107 SplineDirection::kBackward),
Milind Upadhyaya7793962022-03-11 19:39:36 -0800108 PlanSpline(std::bind(&AutonomousSplines::Spline2, &auto_splines_,
109 std::placeholders::_1, alliance_),
Henry Speisere23d4de2022-04-05 16:47:47 -0700110 SplineDirection::kBackward),
Milind Upadhyaya7793962022-03-11 19:39:36 -0800111 PlanSpline(std::bind(&AutonomousSplines::Spline3, &auto_splines_,
112 std::placeholders::_1, alliance_),
Henry Speisere23d4de2022-04-05 16:47:47 -0700113 SplineDirection::kForward)};
Milind Upadhyaya7793962022-03-11 19:39:36 -0800114 starting_position_ = rapid_react_splines_.value()[0].starting_position();
115 CHECK(starting_position_);
Ravago Jones81e50632022-03-11 16:23:51 -0800116 }
117
118 is_planned_ = true;
119
120 MaybeSendStartingPosition();
121}
122
123void AutonomousActor::MaybeSendStartingPosition() {
124 if (is_planned_ && user_indicated_safe_to_reset_ &&
125 !sent_starting_position_) {
126 CHECK(starting_position_);
127 SendStartingPosition(starting_position_.value());
128 }
129}
milind-u086d7262022-01-19 20:44:18 -0800130
131void AutonomousActor::Reset() {
132 InitializeEncoders();
133 ResetDrivetrain();
Ravago Jones81e50632022-03-11 16:23:51 -0800134 RetractFrontIntake();
135 RetractBackIntake();
136
137 joystick_state_fetcher_.Fetch();
138 CHECK(joystick_state_fetcher_.get() != nullptr)
139 << "Expect at least one JoystickState message before running auto...";
140 alliance_ = joystick_state_fetcher_->alliance();
milind-u086d7262022-01-19 20:44:18 -0800141}
142
143bool AutonomousActor::RunAction(
144 const ::frc971::autonomous::AutonomousActionParams *params) {
145 Reset();
Ravago Jones81e50632022-03-11 16:23:51 -0800146 if (!user_indicated_safe_to_reset_) {
147 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
148 CHECK(starting_position_);
149 SendStartingPosition(starting_position_.value());
150 }
151 // Clear this so that we don't accidentally resend things as soon as we replan
152 // later.
153 user_indicated_safe_to_reset_ = false;
154 is_planned_ = false;
155 starting_position_.reset();
milind-u086d7262022-01-19 20:44:18 -0800156
157 AOS_LOG(INFO, "Params are %d\n", params->mode());
Ravago Jones81e50632022-03-11 16:23:51 -0800158 if (alliance_ == aos::Alliance::kInvalid) {
159 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
160 return false;
161 }
162 if (FLAGS_spline_auto) {
163 SplineAuto();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800164 } else if (FLAGS_rapid_react) {
165 RapidReact();
Ravago Jones81e50632022-03-11 16:23:51 -0800166 }
167
milind-u086d7262022-01-19 20:44:18 -0800168 return true;
169}
170
Ravago Jones81e50632022-03-11 16:23:51 -0800171void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
172 // Set up the starting position for the blue alliance.
173
174 // TODO(james): Resetting the localizer breaks the left/right statespace
175 // controller. That is a bug, but we can fix that later by not resetting.
176 auto builder = localizer_control_sender_.MakeBuilder();
177
178 LocalizerControl::Builder localizer_control_builder =
179 builder.MakeBuilder<LocalizerControl>();
180 localizer_control_builder.add_x(start(0));
181 localizer_control_builder.add_y(start(1));
182 localizer_control_builder.add_theta(start(2));
183 localizer_control_builder.add_theta_uncertainty(0.00001);
184 LOG(INFO) << "User button pressed, x: " << start(0) << " y: " << start(1)
185 << " theta: " << start(2);
186 if (builder.Send(localizer_control_builder.Finish()) !=
187 aos::RawSender::Error::kOk) {
188 AOS_LOG(ERROR, "Failed to reset localizer.\n");
189 }
190}
191
192void AutonomousActor::SplineAuto() {
193 CHECK(test_spline_);
194
195 if (!test_spline_->WaitForPlan()) return;
196 test_spline_->Start();
197
198 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
199}
200
Milind Upadhyaya7793962022-03-11 19:39:36 -0800201void AutonomousActor::RapidReact() {
202 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
203
204 CHECK(rapid_react_splines_);
205
206 auto &splines = *rapid_react_splines_;
207
208 // Tell the superstructure a ball was preloaded
Milind Upadhyaya7793962022-03-11 19:39:36 -0800209 if (!WaitForPreloaded()) return;
Henry Speiser09e8da92022-03-14 20:58:45 -0700210
Henry Speisere23d4de2022-04-05 16:47:47 -0700211 // Fire preloaded ball while driving
Henry Speiser09e8da92022-03-14 20:58:45 -0700212 set_fire_at_will(true);
213 SendSuperstructureGoal();
Milind Upadhyayf35bb112022-03-16 23:08:04 -0700214 if (!WaitForBallsShot()) return;
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700215 LOG(INFO) << "Shot first ball "
216 << chrono::duration<double>(aos::monotonic_clock::now() -
217 start_time)
218 .count()
219 << 's';
Henry Speiser09e8da92022-03-14 20:58:45 -0700220 set_fire_at_will(false);
221 SendSuperstructureGoal();
222
Henry Speisere23d4de2022-04-05 16:47:47 -0700223 // Drive and intake the ball nearest to the starting zone.
224 // Fire while moving.
Henry Speiser09e8da92022-03-14 20:58:45 -0700225 ExtendBackIntake();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800226 if (!splines[0].WaitForPlan()) return;
227 splines[0].Start();
Henry Speisere23d4de2022-04-05 16:47:47 -0700228 // Distance before we don't shoot while moving.
229 if (!splines[0].WaitForSplineDistanceRemaining(0.25)) return;
Milind Upadhyaya7793962022-03-11 19:39:36 -0800230
Milind Upadhyaya7793962022-03-11 19:39:36 -0800231 set_fire_at_will(true);
232 SendSuperstructureGoal();
Henry Speisere23d4de2022-04-05 16:47:47 -0700233
234 if (!splines[0].WaitForSplineDistanceRemaining(0.02)) return;
235
236 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
237
238 // Fire the last ball we picked up when stopped.
239 SendSuperstructureGoal();
240 LOG(INFO) << "Close";
Milind Upadhyayf35bb112022-03-16 23:08:04 -0700241 if (!WaitForBallsShot()) return;
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700242 LOG(INFO) << "Shot first 3 balls "
243 << chrono::duration<double>(aos::monotonic_clock::now() -
244 start_time)
245 .count()
246 << 's';
Milind Upadhyaya7793962022-03-11 19:39:36 -0800247
248 // Drive to the human player station while intaking two balls.
249 // Once is already placed down,
250 // and one will be rolled to the robot by the human player
Henry Speiser09e8da92022-03-14 20:58:45 -0700251 if (!splines[1].WaitForPlan()) return;
252 splines[1].Start();
Henry Speisere23d4de2022-04-05 16:47:47 -0700253
254 std::this_thread::sleep_for(std::chrono::milliseconds(1500));
255
256 set_fire_at_will(false);
257 SendSuperstructureGoal();
258
Henry Speiser09e8da92022-03-14 20:58:45 -0700259 if (!splines[1].WaitForSplineDistanceRemaining(0.02)) return;
Henry Speisere23d4de2022-04-05 16:47:47 -0700260 std::this_thread::sleep_for(std::chrono::milliseconds(500));
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700261 LOG(INFO) << "At balls 4/5 "
262 << chrono::duration<double>(aos::monotonic_clock::now() -
263 start_time)
264 .count()
265 << 's';
Milind Upadhyaya7793962022-03-11 19:39:36 -0800266
267 // Drive to the shooting position
Henry Speiser09e8da92022-03-14 20:58:45 -0700268 if (!splines[2].WaitForPlan()) return;
269 splines[2].Start();
270 if (!splines[2].WaitForSplineDistanceRemaining(2.00)) return;
271 RetractFrontIntake();
272
273 if (!splines[2].WaitForSplineDistanceRemaining(0.02)) return;
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700274 LOG(INFO) << "Shooting last balls "
275 << chrono::duration<double>(aos::monotonic_clock::now() -
276 start_time)
277 .count()
278 << 's';
Milind Upadhyaya7793962022-03-11 19:39:36 -0800279
280 // Fire the two balls once we stopped
281 set_fire_at_will(true);
282 SendSuperstructureGoal();
Milind Upadhyayf35bb112022-03-16 23:08:04 -0700283 if (!WaitForBallsShot()) return;
Milind Upadhyaya7793962022-03-11 19:39:36 -0800284 set_fire_at_will(false);
Henry Speiser09e8da92022-03-14 20:58:45 -0700285 SendSuperstructureGoal();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800286
287 LOG(INFO) << "Took "
288 << chrono::duration<double>(aos::monotonic_clock::now() -
289 start_time)
290 .count()
291 << 's';
292}
293
294[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800295 set_preloaded(true);
296 SendSuperstructureGoal();
297
298 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
299 event_loop()->monotonic_now(),
300 ActorBase::kLoopOffset);
301
302 bool loaded = false;
303 while (!loaded) {
304 if (ShouldCancel()) {
305 return false;
306 }
307
308 phased_loop.SleepUntilNext();
309 superstructure_status_fetcher_.Fetch();
310 CHECK(superstructure_status_fetcher_.get() != nullptr);
311
312 loaded = (superstructure_status_fetcher_->state() ==
313 control_loops::superstructure::SuperstructureState::LOADED);
314 }
315
316 set_preloaded(false);
317 SendSuperstructureGoal();
318
319 return true;
320}
321
Ravago Jones81e50632022-03-11 16:23:51 -0800322void AutonomousActor::SendSuperstructureGoal() {
323 auto builder = superstructure_goal_sender_.MakeBuilder();
324
325 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
326 intake_front_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
327 *builder.fbb(), intake_front_goal_,
328 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
329
330 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
331 intake_back_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
332 *builder.fbb(), intake_back_goal_,
333 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
334
335 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
336 catapult_return_position_offset =
337 CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
338 *builder.fbb(), kCatapultReturnPosition,
339 CreateProfileParameters(*builder.fbb(), 9.0, 50.0));
340
341 superstructure::CatapultGoal::Builder catapult_goal_builder(*builder.fbb());
342 catapult_goal_builder.add_shot_position(0.03);
343 catapult_goal_builder.add_shot_velocity(18.0);
344 catapult_goal_builder.add_return_position(catapult_return_position_offset);
345 flatbuffers::Offset<superstructure::CatapultGoal> catapult_goal_offset =
346 catapult_goal_builder.Finish();
347
348 superstructure::Goal::Builder superstructure_builder =
349 builder.MakeBuilder<superstructure::Goal>();
350
351 superstructure_builder.add_intake_front(intake_front_offset);
352 superstructure_builder.add_intake_back(intake_back_offset);
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700353 superstructure_builder.add_roller_speed_compensation(0.0);
Ravago Jones81e50632022-03-11 16:23:51 -0800354 superstructure_builder.add_roller_speed_front(roller_front_voltage_);
355 superstructure_builder.add_roller_speed_back(roller_back_voltage_);
Milind Upadhyayd86b02c2022-03-13 20:57:46 -0700356 if (requested_intake_.has_value()) {
357 superstructure_builder.add_turret_intake(*requested_intake_);
358 }
Milind Upadhyay29dcc172022-04-02 19:21:30 -0700359 superstructure_builder.add_transfer_roller_speed(transfer_roller_voltage_);
Ravago Jones81e50632022-03-11 16:23:51 -0800360 superstructure_builder.add_catapult(catapult_goal_offset);
361 superstructure_builder.add_fire(fire_);
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800362 superstructure_builder.add_preloaded(preloaded_);
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700363 superstructure_builder.add_auto_aim(true);
Ravago Jones81e50632022-03-11 16:23:51 -0800364
365 if (builder.Send(superstructure_builder.Finish()) !=
366 aos::RawSender::Error::kOk) {
367 AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
368 }
369}
370
371void AutonomousActor::ExtendFrontIntake() {
Milind Upadhyayd86b02c2022-03-13 20:57:46 -0700372 set_requested_intake(RequestedIntake::kFront);
Ravago Jones81e50632022-03-11 16:23:51 -0800373 set_intake_front_goal(kExtendIntakeGoal);
Austin Schuhe1264372022-03-13 20:22:36 -0700374 set_roller_front_voltage(kIntakeRollerVoltage);
Milind Upadhyay29dcc172022-04-02 19:21:30 -0700375 set_transfer_roller_voltage(kRollerVoltage);
Ravago Jones81e50632022-03-11 16:23:51 -0800376 SendSuperstructureGoal();
377}
378
379void AutonomousActor::RetractFrontIntake() {
Milind Upadhyayd86b02c2022-03-13 20:57:46 -0700380 set_requested_intake(std::nullopt);
Ravago Jones81e50632022-03-11 16:23:51 -0800381 set_intake_front_goal(kRetractIntakeGoal);
Austin Schuhe1264372022-03-13 20:22:36 -0700382 set_roller_front_voltage(0.0);
Milind Upadhyay29dcc172022-04-02 19:21:30 -0700383 set_transfer_roller_voltage(0.0);
Ravago Jones81e50632022-03-11 16:23:51 -0800384 SendSuperstructureGoal();
385}
386
387void AutonomousActor::ExtendBackIntake() {
Milind Upadhyayd86b02c2022-03-13 20:57:46 -0700388 set_requested_intake(RequestedIntake::kBack);
Ravago Jones81e50632022-03-11 16:23:51 -0800389 set_intake_back_goal(kExtendIntakeGoal);
Austin Schuhe1264372022-03-13 20:22:36 -0700390 set_roller_back_voltage(kIntakeRollerVoltage);
Milind Upadhyay29dcc172022-04-02 19:21:30 -0700391 set_transfer_roller_voltage(-kRollerVoltage);
Ravago Jones81e50632022-03-11 16:23:51 -0800392 SendSuperstructureGoal();
393}
394
395void AutonomousActor::RetractBackIntake() {
Milind Upadhyayd86b02c2022-03-13 20:57:46 -0700396 set_requested_intake(std::nullopt);
Ravago Jones81e50632022-03-11 16:23:51 -0800397 set_intake_back_goal(kRetractIntakeGoal);
Austin Schuhe1264372022-03-13 20:22:36 -0700398 set_roller_back_voltage(0.0);
Milind Upadhyay29dcc172022-04-02 19:21:30 -0700399 set_transfer_roller_voltage(0.0);
Ravago Jones81e50632022-03-11 16:23:51 -0800400 SendSuperstructureGoal();
401}
402
Milind Upadhyayf35bb112022-03-16 23:08:04 -0700403[[nodiscard]] bool AutonomousActor::WaitForBallsShot() {
Austin Schuh42d7e5f2022-03-16 23:35:09 -0700404 superstructure_status_fetcher_.Fetch();
405 CHECK(superstructure_status_fetcher_.get());
Milind Upadhyayf35bb112022-03-16 23:08:04 -0700406
Ravago Jonesf699d1c2022-03-11 18:39:56 -0800407 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
408 event_loop()->monotonic_now(),
409 ActorBase::kLoopOffset);
410 superstructure_status_fetcher_.Fetch();
411 CHECK(superstructure_status_fetcher_.get() != nullptr);
Henry Speisere23d4de2022-04-05 16:47:47 -0700412
Ravago Jonesf699d1c2022-03-11 18:39:56 -0800413 while (true) {
414 if (ShouldCancel()) {
415 return false;
416 }
417 phased_loop.SleepUntilNext();
418 superstructure_status_fetcher_.Fetch();
419 CHECK(superstructure_status_fetcher_.get() != nullptr);
Henry Speisere23d4de2022-04-05 16:47:47 -0700420
421 if (!superstructure_status_fetcher_->front_intake_has_ball() &&
422 !superstructure_status_fetcher_->back_intake_has_ball() &&
423 superstructure_status_fetcher_->state() ==
424 control_loops::superstructure::SuperstructureState::IDLE) {
Ravago Jonesf699d1c2022-03-11 18:39:56 -0800425 return true;
426 }
427 }
428}
429
milind-u086d7262022-01-19 20:44:18 -0800430} // namespace actors
431} // namespace y2022