blob: bf4fd1395cb9fc870d14d03bdbb0da4e8e1d69f5 [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");
Milind Upadhyaya7793962022-03-11 19:39:36 -080016DEFINE_bool(rapid_react, false,
17 "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 {
22constexpr double kExtendIntakeGoal = 0.0;
23constexpr double kRetractIntakeGoal = 1.47;
24constexpr double kRollerVoltage = 12.0;
25constexpr double kCatapultReturnPosition = -0.908;
26} // namespace
milind-u086d7262022-01-19 20:44:18 -080027
28using ::aos::monotonic_clock;
Ravago Jones81e50632022-03-11 16:23:51 -080029using frc971::CreateProfileParameters;
milind-u086d7262022-01-19 20:44:18 -080030using ::frc971::ProfileParametersT;
Ravago Jones81e50632022-03-11 16:23:51 -080031using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
32using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
milind-u086d7262022-01-19 20:44:18 -080033using frc971::control_loops::drivetrain::LocalizerControl;
Ravago Jones81e50632022-03-11 16:23:51 -080034
milind-u086d7262022-01-19 20:44:18 -080035namespace chrono = ::std::chrono;
36
37AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
38 : frc971::autonomous::BaseAutonomousActor(
Ravago Jones81e50632022-03-11 16:23:51 -080039 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
40 localizer_control_sender_(
41 event_loop->MakeSender<
42 ::frc971::control_loops::drivetrain::LocalizerControl>(
43 "/drivetrain")),
44 superstructure_goal_sender_(
45 event_loop->MakeSender<control_loops::superstructure::Goal>(
46 "/superstructure")),
47 superstructure_status_fetcher_(
48 event_loop->MakeFetcher<control_loops::superstructure::Status>(
49 "/superstructure")),
50 joystick_state_fetcher_(
51 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
52 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
53 auto_splines_() {
54 set_max_drivetrain_voltage(12.0);
55 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
56 event_loop->OnRun([this, event_loop]() {
57 replan_timer_->Setup(event_loop->monotonic_now());
58 button_poll_->Setup(event_loop->monotonic_now(), chrono::milliseconds(50));
59 });
60
61 button_poll_ = event_loop->AddTimer([this]() {
62 const aos::monotonic_clock::time_point now =
63 this->event_loop()->context().monotonic_event_time;
64 if (robot_state_fetcher_.Fetch()) {
65 if (robot_state_fetcher_->user_button()) {
66 user_indicated_safe_to_reset_ = true;
67 MaybeSendStartingPosition();
68 }
69 }
70 if (joystick_state_fetcher_.Fetch()) {
71 if (joystick_state_fetcher_->has_alliance() &&
72 (joystick_state_fetcher_->alliance() != alliance_)) {
73 alliance_ = joystick_state_fetcher_->alliance();
74 is_planned_ = false;
75 // Only kick the planning out by 2 seconds. If we end up enabled in that
76 // second, then we will kick it out further based on the code below.
77 replan_timer_->Setup(now + std::chrono::seconds(2));
78 }
79 if (joystick_state_fetcher_->enabled()) {
80 if (!is_planned_) {
81 // Only replan once we've been disabled for 5 seconds.
82 replan_timer_->Setup(now + std::chrono::seconds(5));
83 }
84 }
85 }
86 });
87}
88
89void AutonomousActor::Replan() {
90 LOG(INFO) << "Alliance " << static_cast<int>(alliance_);
91 if (alliance_ == aos::Alliance::kInvalid) {
92 return;
93 }
94 sent_starting_position_ = false;
95 if (FLAGS_spline_auto) {
96 test_spline_ =
97 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
98 std::placeholders::_1, alliance_),
99 SplineDirection::kForward);
100
101 starting_position_ = test_spline_->starting_position();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800102 } else if (FLAGS_rapid_react) {
103 rapid_react_splines_ = {
104 PlanSpline(std::bind(&AutonomousSplines::Spline1, &auto_splines_,
105 std::placeholders::_1, alliance_),
106 SplineDirection::kForward),
107 PlanSpline(std::bind(&AutonomousSplines::Spline2, &auto_splines_,
108 std::placeholders::_1, alliance_),
109 SplineDirection::kForward),
110 PlanSpline(std::bind(&AutonomousSplines::Spline3, &auto_splines_,
111 std::placeholders::_1, alliance_),
112 SplineDirection::kForward),
113 PlanSpline(std::bind(&AutonomousSplines::Spline4, &auto_splines_,
114 std::placeholders::_1, alliance_),
115 SplineDirection::kBackward),
116 PlanSpline(std::bind(&AutonomousSplines::Spline5, &auto_splines_,
117 std::placeholders::_1, alliance_),
118 SplineDirection::kBackward)};
119 starting_position_ = rapid_react_splines_.value()[0].starting_position();
120 CHECK(starting_position_);
Ravago Jones81e50632022-03-11 16:23:51 -0800121 }
122
123 is_planned_ = true;
124
125 MaybeSendStartingPosition();
126}
127
128void AutonomousActor::MaybeSendStartingPosition() {
129 if (is_planned_ && user_indicated_safe_to_reset_ &&
130 !sent_starting_position_) {
131 CHECK(starting_position_);
132 SendStartingPosition(starting_position_.value());
133 }
134}
milind-u086d7262022-01-19 20:44:18 -0800135
136void AutonomousActor::Reset() {
137 InitializeEncoders();
138 ResetDrivetrain();
Ravago Jones81e50632022-03-11 16:23:51 -0800139 RetractFrontIntake();
140 RetractBackIntake();
141
142 joystick_state_fetcher_.Fetch();
143 CHECK(joystick_state_fetcher_.get() != nullptr)
144 << "Expect at least one JoystickState message before running auto...";
145 alliance_ = joystick_state_fetcher_->alliance();
milind-u086d7262022-01-19 20:44:18 -0800146}
147
148bool AutonomousActor::RunAction(
149 const ::frc971::autonomous::AutonomousActionParams *params) {
150 Reset();
Ravago Jones81e50632022-03-11 16:23:51 -0800151 if (!user_indicated_safe_to_reset_) {
152 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
153 CHECK(starting_position_);
154 SendStartingPosition(starting_position_.value());
155 }
156 // Clear this so that we don't accidentally resend things as soon as we replan
157 // later.
158 user_indicated_safe_to_reset_ = false;
159 is_planned_ = false;
160 starting_position_.reset();
milind-u086d7262022-01-19 20:44:18 -0800161
162 AOS_LOG(INFO, "Params are %d\n", params->mode());
Ravago Jones81e50632022-03-11 16:23:51 -0800163 if (alliance_ == aos::Alliance::kInvalid) {
164 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
165 return false;
166 }
167 if (FLAGS_spline_auto) {
168 SplineAuto();
Milind Upadhyaya7793962022-03-11 19:39:36 -0800169 } else if (FLAGS_rapid_react) {
170 RapidReact();
Ravago Jones81e50632022-03-11 16:23:51 -0800171 }
172
milind-u086d7262022-01-19 20:44:18 -0800173 return true;
174}
175
Ravago Jones81e50632022-03-11 16:23:51 -0800176void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
177 // Set up the starting position for the blue alliance.
178
179 // TODO(james): Resetting the localizer breaks the left/right statespace
180 // controller. That is a bug, but we can fix that later by not resetting.
181 auto builder = localizer_control_sender_.MakeBuilder();
182
183 LocalizerControl::Builder localizer_control_builder =
184 builder.MakeBuilder<LocalizerControl>();
185 localizer_control_builder.add_x(start(0));
186 localizer_control_builder.add_y(start(1));
187 localizer_control_builder.add_theta(start(2));
188 localizer_control_builder.add_theta_uncertainty(0.00001);
189 LOG(INFO) << "User button pressed, x: " << start(0) << " y: " << start(1)
190 << " theta: " << start(2);
191 if (builder.Send(localizer_control_builder.Finish()) !=
192 aos::RawSender::Error::kOk) {
193 AOS_LOG(ERROR, "Failed to reset localizer.\n");
194 }
195}
196
197void AutonomousActor::SplineAuto() {
198 CHECK(test_spline_);
199
200 if (!test_spline_->WaitForPlan()) return;
201 test_spline_->Start();
202
203 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
204}
205
Milind Upadhyaya7793962022-03-11 19:39:36 -0800206void AutonomousActor::RapidReact() {
207 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
208
209 CHECK(rapid_react_splines_);
210
211 auto &splines = *rapid_react_splines_;
212
213 // Tell the superstructure a ball was preloaded
214
215 if (!WaitForPreloaded()) return;
216 // Drive and intake the 2nd ball
217 ExtendFrontIntake();
218 if (!splines[0].WaitForPlan()) return;
219 splines[0].Start();
220 if (!splines[0].WaitForSplineDistanceRemaining(0.02)) return;
221
222 // Fire the two balls once we stopped
223 set_fire_at_will(true);
224 SendSuperstructureGoal();
225 if (!WaitForBallsShot(2)) return;
226 set_fire_at_will(false);
227
228 // Drive and intake the 3rd ball
229 if (!splines[1].WaitForPlan()) return;
230 splines[1].Start();
231 if (!splines[1].WaitForSplineDistanceRemaining(0.02)) return;
232
233 // Fire the 3rd once we stopped.
234 set_fire_at_will(true);
235 SendSuperstructureGoal();
236 if (!WaitForBallsShot(1)) return;
237 set_fire_at_will(false);
238
239 // Drive to the human player station while intaking two balls.
240 // Once is already placed down,
241 // and one will be rolled to the robot by the human player
242 if (!splines[2].WaitForPlan()) return;
243 splines[2].Start();
244 if (!splines[2].WaitForSplineDistanceRemaining(0.02)) return;
245
246 // Drive to the shooting position
247 if (!splines[3].WaitForPlan()) return;
248 splines[3].Start();
249 if (!splines[3].WaitForSplineDistanceRemaining(0.02)) return;
250
251 // Fire the two balls once we stopped
252 set_fire_at_will(true);
253 SendSuperstructureGoal();
254 if (!WaitForBallsShot(2)) return;
255 set_fire_at_will(false);
256
257 // Done intaking
258 RetractFrontIntake();
259
260 // Drive to the middle of the field to get ready for teleop
261 if (!splines[4].WaitForPlan()) return;
262 splines[4].Start();
263 if (!splines[4].WaitForSplineDistanceRemaining(0.02)) return;
264
265 LOG(INFO) << "Took "
266 << chrono::duration<double>(aos::monotonic_clock::now() -
267 start_time)
268 .count()
269 << 's';
270}
271
272[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800273 set_preloaded(true);
274 SendSuperstructureGoal();
275
276 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
277 event_loop()->monotonic_now(),
278 ActorBase::kLoopOffset);
279
280 bool loaded = false;
281 while (!loaded) {
282 if (ShouldCancel()) {
283 return false;
284 }
285
286 phased_loop.SleepUntilNext();
287 superstructure_status_fetcher_.Fetch();
288 CHECK(superstructure_status_fetcher_.get() != nullptr);
289
290 loaded = (superstructure_status_fetcher_->state() ==
291 control_loops::superstructure::SuperstructureState::LOADED);
292 }
293
294 set_preloaded(false);
295 SendSuperstructureGoal();
296
297 return true;
298}
299
Ravago Jones81e50632022-03-11 16:23:51 -0800300void AutonomousActor::SendSuperstructureGoal() {
301 auto builder = superstructure_goal_sender_.MakeBuilder();
302
303 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
304 intake_front_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
305 *builder.fbb(), intake_front_goal_,
306 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
307
308 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
309 intake_back_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
310 *builder.fbb(), intake_back_goal_,
311 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
312
313 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
314 catapult_return_position_offset =
315 CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
316 *builder.fbb(), kCatapultReturnPosition,
317 CreateProfileParameters(*builder.fbb(), 9.0, 50.0));
318
319 superstructure::CatapultGoal::Builder catapult_goal_builder(*builder.fbb());
320 catapult_goal_builder.add_shot_position(0.03);
321 catapult_goal_builder.add_shot_velocity(18.0);
322 catapult_goal_builder.add_return_position(catapult_return_position_offset);
323 flatbuffers::Offset<superstructure::CatapultGoal> catapult_goal_offset =
324 catapult_goal_builder.Finish();
325
326 superstructure::Goal::Builder superstructure_builder =
327 builder.MakeBuilder<superstructure::Goal>();
328
329 superstructure_builder.add_intake_front(intake_front_offset);
330 superstructure_builder.add_intake_back(intake_back_offset);
331 superstructure_builder.add_roller_speed_compensation(1.5);
332 superstructure_builder.add_roller_speed_front(roller_front_voltage_);
333 superstructure_builder.add_roller_speed_back(roller_back_voltage_);
Milind Upadhyayb1a74ea2022-03-09 20:34:35 -0800334 superstructure_builder.add_transfer_roller_speed_front(
335 transfer_roller_front_voltage_);
336 superstructure_builder.add_transfer_roller_speed_back(
337 transfer_roller_back_voltage_);
Ravago Jones81e50632022-03-11 16:23:51 -0800338 superstructure_builder.add_catapult(catapult_goal_offset);
339 superstructure_builder.add_fire(fire_);
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800340 superstructure_builder.add_preloaded(preloaded_);
Ravago Jones81e50632022-03-11 16:23:51 -0800341 superstructure_builder.add_auto_aim(true);
342
343 if (builder.Send(superstructure_builder.Finish()) !=
344 aos::RawSender::Error::kOk) {
345 AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
346 }
347}
348
349void AutonomousActor::ExtendFrontIntake() {
350 set_intake_front_goal(kExtendIntakeGoal);
351 set_roller_front_voltage(kRollerVoltage);
Milind Upadhyayb1a74ea2022-03-09 20:34:35 -0800352 set_transfer_roller_front_voltage(kRollerVoltage);
353 set_transfer_roller_back_voltage(-kRollerVoltage);
Ravago Jones81e50632022-03-11 16:23:51 -0800354 SendSuperstructureGoal();
355}
356
357void AutonomousActor::RetractFrontIntake() {
358 set_intake_front_goal(kRetractIntakeGoal);
359 set_roller_front_voltage(kRollerVoltage);
Milind Upadhyayb1a74ea2022-03-09 20:34:35 -0800360 set_transfer_roller_front_voltage(0.0);
361 set_transfer_roller_back_voltage(0.0);
Ravago Jones81e50632022-03-11 16:23:51 -0800362 SendSuperstructureGoal();
363}
364
365void AutonomousActor::ExtendBackIntake() {
366 set_intake_back_goal(kExtendIntakeGoal);
367 set_roller_back_voltage(kRollerVoltage);
Milind Upadhyayb1a74ea2022-03-09 20:34:35 -0800368 set_transfer_roller_back_voltage(kRollerVoltage);
369 set_transfer_roller_front_voltage(-kRollerVoltage);
Ravago Jones81e50632022-03-11 16:23:51 -0800370 SendSuperstructureGoal();
371}
372
373void AutonomousActor::RetractBackIntake() {
374 set_intake_back_goal(kRetractIntakeGoal);
375 set_roller_back_voltage(kRollerVoltage);
Milind Upadhyayb1a74ea2022-03-09 20:34:35 -0800376 set_transfer_roller_front_voltage(0.0);
377 set_transfer_roller_back_voltage(0.0);
Ravago Jones81e50632022-03-11 16:23:51 -0800378 SendSuperstructureGoal();
379}
380
Milind Upadhyaya7793962022-03-11 19:39:36 -0800381[[nodiscard]] bool AutonomousActor::WaitForBallsShot(int num_wanted) {
Ravago Jonesf699d1c2022-03-11 18:39:56 -0800382 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
383 event_loop()->monotonic_now(),
384 ActorBase::kLoopOffset);
385 superstructure_status_fetcher_.Fetch();
386 CHECK(superstructure_status_fetcher_.get() != nullptr);
387 int initial_balls = superstructure_status_fetcher_->shot_count();
388 LOG(INFO) << "Waiting for balls, started with " << initial_balls;
389 while (true) {
390 if (ShouldCancel()) {
391 return false;
392 }
393 phased_loop.SleepUntilNext();
394 superstructure_status_fetcher_.Fetch();
395 CHECK(superstructure_status_fetcher_.get() != nullptr);
396 if (superstructure_status_fetcher_->shot_count() - initial_balls >=
397 num_wanted) {
398 return true;
399 }
400 }
401}
402
milind-u086d7262022-01-19 20:44:18 -0800403} // namespace actors
404} // namespace y2022