blob: 5166ac86aa8577aa768721a52282157b9806ca77 [file] [log] [blame]
Ariv Diggi0af59c02023-10-07 13:15:39 -07001#include "y2023_bot3/autonomous/autonomous_actor.h"
2
3#include <chrono>
4#include <cinttypes>
5#include <cmath>
6
Austin Schuh99f7c6a2024-06-25 22:07:44 -07007#include "absl/flags/flag.h"
8
Ariv Diggi0af59c02023-10-07 13:15:39 -07009#include "aos/logging/logging.h"
10#include "aos/util/math.h"
11#include "frc971/control_loops/drivetrain/localizer_generated.h"
12#include "y2023_bot3/autonomous/auto_splines.h"
13#include "y2023_bot3/constants.h"
14#include "y2023_bot3/control_loops/drivetrain/drivetrain_base.h"
15
Austin Schuh99f7c6a2024-06-25 22:07:44 -070016ABSL_FLAG(bool, spline_auto, false, "Run simple test S-spline auto mode.");
17ABSL_FLAG(bool, charged_up, true,
18 "If true run charged up autonomous mode. 2 Piece non-cable side");
19ABSL_FLAG(bool, charged_up_middle, false,
20 "If true run charged up middle autonomous mode. Starts middle, "
21 "places cube mid, mobility");
22ABSL_FLAG(bool, one_piece, false,
23 "End charged_up autonomous after first cube is placed.");
Ariv Diggi0af59c02023-10-07 13:15:39 -070024
Stephan Pleinesf63bde82024-01-13 15:59:33 -080025namespace y2023_bot3::autonomous {
Ariv Diggi0af59c02023-10-07 13:15:39 -070026
27using ::frc971::ProfileParametersT;
28
29ProfileParametersT MakeProfileParameters(float max_velocity,
30 float max_acceleration) {
31 ProfileParametersT result;
32 result.max_velocity = max_velocity;
33 result.max_acceleration = max_acceleration;
34 return result;
35}
36
37using ::aos::monotonic_clock;
38using frc971::CreateProfileParameters;
39using ::frc971::ProfileParametersT;
40using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
41using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
42using frc971::control_loops::drivetrain::LocalizerControl;
43namespace chrono = ::std::chrono;
44
45AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
46 : frc971::autonomous::BaseAutonomousActor(
47 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
48 localizer_control_sender_(
49 event_loop->MakeSender<
50 ::frc971::control_loops::drivetrain::LocalizerControl>(
51 "/drivetrain")),
52 joystick_state_fetcher_(
53 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
54 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
55 auto_splines_(),
56 superstructure_goal_sender_(
57 event_loop
58 ->MakeSender<::y2023_bot3::control_loops::superstructure::Goal>(
59 "/superstructure")),
60 superstructure_status_fetcher_(
61 event_loop->MakeFetcher<
62 ::y2023_bot3::control_loops::superstructure::Status>(
63 "/superstructure")) {
64 drivetrain_status_fetcher_.Fetch();
65 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
66
67 event_loop->OnRun([this, event_loop]() {
68 replan_timer_->Schedule(event_loop->monotonic_now());
69 button_poll_->Schedule(event_loop->monotonic_now(),
70 chrono::milliseconds(50));
71 });
72
73 // TODO(james): Really need to refactor this code since we keep using it.
74 button_poll_ = event_loop->AddTimer([this]() {
75 const aos::monotonic_clock::time_point now =
76 this->event_loop()->context().monotonic_event_time;
77 if (robot_state_fetcher_.Fetch()) {
78 if (robot_state_fetcher_->user_button()) {
79 user_indicated_safe_to_reset_ = true;
80 MaybeSendStartingPosition();
81 }
82 }
83 if (joystick_state_fetcher_.Fetch()) {
84 if (joystick_state_fetcher_->has_alliance() &&
85 (joystick_state_fetcher_->alliance() != alliance_)) {
86 alliance_ = joystick_state_fetcher_->alliance();
87 is_planned_ = false;
88 // Only kick the planning out by 2 seconds. If we end up enabled in
89 // that second, then we will kick it out further based on the code
90 // below.
91 replan_timer_->Schedule(now + std::chrono::seconds(2));
92 }
93 if (joystick_state_fetcher_->enabled()) {
94 if (!is_planned_) {
95 // Only replan once we've been disabled for 5 seconds.
96 replan_timer_->Schedule(now + std::chrono::seconds(5));
97 }
98 }
99 }
100 });
101}
102
103void AutonomousActor::Replan() {
104 if (!drivetrain_status_fetcher_.Fetch()) {
105 replan_timer_->Schedule(event_loop()->monotonic_now() + chrono::seconds(1));
106 AOS_LOG(INFO, "Drivetrain not up, replanning in 1 second");
107 return;
108 }
109
110 if (alliance_ == aos::Alliance::kInvalid) {
111 return;
112 }
113 sent_starting_position_ = false;
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700114 if (absl::GetFlag(FLAGS_spline_auto)) {
Ariv Diggi0af59c02023-10-07 13:15:39 -0700115 test_spline_ =
116 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
117 std::placeholders::_1, alliance_),
118 SplineDirection::kForward);
119
120 starting_position_ = test_spline_->starting_position();
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700121 } else if (absl::GetFlag(FLAGS_charged_up)) {
Filip Kujawaef687152023-11-14 22:11:32 -0800122 charged_up_splines_ = {
123 PlanSpline(std::bind(&AutonomousSplines::Spline1, &auto_splines_,
124 std::placeholders::_1, alliance_),
125 SplineDirection::kBackward),
126 PlanSpline(std::bind(&AutonomousSplines::Spline2, &auto_splines_,
127 std::placeholders::_1, alliance_),
128 SplineDirection::kForward),
129 PlanSpline(std::bind(&AutonomousSplines::Spline3, &auto_splines_,
130 std::placeholders::_1, alliance_),
131 SplineDirection::kBackward),
132 PlanSpline(std::bind(&AutonomousSplines::Spline4, &auto_splines_,
133 std::placeholders::_1, alliance_),
134 SplineDirection::kForward)};
135 starting_position_ = charged_up_splines_.value()[0].starting_position();
136 CHECK(starting_position_);
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700137 } else if (absl::GetFlag(FLAGS_charged_up_middle)) {
Filip Kujawaef687152023-11-14 22:11:32 -0800138 charged_up_middle_splines_ = {
139 PlanSpline(std::bind(&AutonomousSplines::SplineMiddle1, &auto_splines_,
140 std::placeholders::_1, alliance_),
141 SplineDirection::kForward)};
Ariv Diggi0af59c02023-10-07 13:15:39 -0700142 }
143 is_planned_ = true;
144
145 MaybeSendStartingPosition();
Filip Kujawaef687152023-11-14 22:11:32 -0800146} // namespace autonomous
Ariv Diggi0af59c02023-10-07 13:15:39 -0700147
148void AutonomousActor::MaybeSendStartingPosition() {
149 if (is_planned_ && user_indicated_safe_to_reset_ &&
150 !sent_starting_position_) {
151 CHECK(starting_position_);
152 SendStartingPosition(starting_position_.value());
153 }
154}
155
156void AutonomousActor::Reset() {
157 InitializeEncoders();
158 ResetDrivetrain();
159
160 joystick_state_fetcher_.Fetch();
161 CHECK(joystick_state_fetcher_.get() != nullptr)
162 << "Expect at least one JoystickState message before running auto...";
163 alliance_ = joystick_state_fetcher_->alliance();
164
Ariv Diggi0af59c02023-10-07 13:15:39 -0700165 SendSuperstructureGoal();
166}
167
168bool AutonomousActor::RunAction(
169 const ::frc971::autonomous::AutonomousActionParams *params) {
170 Reset();
171
172 AOS_LOG(INFO, "Params are %d\n", params->mode());
173
174 if (!user_indicated_safe_to_reset_) {
175 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
176 CHECK(starting_position_);
177 SendStartingPosition(starting_position_.value());
178 }
179 // Clear this so that we don't accidentally resend things as soon as we
180 // replan later.
181 user_indicated_safe_to_reset_ = false;
182 is_planned_ = false;
183 starting_position_.reset();
184
185 AOS_LOG(INFO, "Params are %d\n", params->mode());
186 if (alliance_ == aos::Alliance::kInvalid) {
187 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
188 return false;
189 }
190
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700191 if (absl::GetFlag(FLAGS_charged_up)) {
Filip Kujawaef687152023-11-14 22:11:32 -0800192 ChargedUp();
193 } else {
194 AOS_LOG(INFO, "No autonomous mode selected.");
195 return false;
196 }
197
Ariv Diggi0af59c02023-10-07 13:15:39 -0700198 return true;
199}
200
201void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
202 // Set up the starting position for the blue alliance.
203
204 auto builder = localizer_control_sender_.MakeBuilder();
205
206 LocalizerControl::Builder localizer_control_builder =
207 builder.MakeBuilder<LocalizerControl>();
208 localizer_control_builder.add_x(start(0));
209 localizer_control_builder.add_y(start(1));
210 localizer_control_builder.add_theta(start(2));
211 localizer_control_builder.add_theta_uncertainty(0.00001);
212 AOS_LOG(INFO, "User button pressed, x: %f y: %f theta: %f", start(0),
213 start(1), start(2));
214 if (builder.Send(localizer_control_builder.Finish()) !=
215 aos::RawSender::Error::kOk) {
216 AOS_LOG(ERROR, "Failed to reset localizer.\n");
217 }
218}
219
Filip Kujawaef687152023-11-14 22:11:32 -0800220// Charged Up 2 Game Object Autonomous (non-cable side)
221void AutonomousActor::ChargedUp() {
222 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
223
224 CHECK(charged_up_splines_);
225
226 auto &splines = *charged_up_splines_;
227
Filip Kujawaef687152023-11-14 22:11:32 -0800228 // Drive to second cube
229 if (!splines[0].WaitForPlan()) {
230 return;
231 }
232 splines[0].Start();
233
Filip Kujawaef687152023-11-14 22:11:32 -0800234 if (!splines[1].WaitForPlan()) {
235 return;
236 }
237 splines[1].Start();
Filip Kujawaef687152023-11-14 22:11:32 -0800238
Filip Kujawaef687152023-11-14 22:11:32 -0800239 if (!splines[1].WaitForSplineDistanceRemaining(0.1)) return;
240
Filip Kujawaef687152023-11-14 22:11:32 -0800241 // Drive to third cube
242 if (!splines[2].WaitForPlan()) {
243 return;
244 }
245 splines[2].Start();
246
Filip Kujawaef687152023-11-14 22:11:32 -0800247 if (!splines[2].WaitForSplineDistanceRemaining(0.02)) {
248 return;
249 }
250
251 AOS_LOG(
252 INFO, "Got there %lf s\n",
253 aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
254
255 // Drive back to grid
256 if (!splines[3].WaitForPlan()) {
257 return;
258 }
259 splines[3].Start();
260 std::this_thread::sleep_for(chrono::milliseconds(600));
261
Filip Kujawaef687152023-11-14 22:11:32 -0800262 if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
Filip Kujawaef687152023-11-14 22:11:32 -0800263}
264
265// Charged Up Place and Mobility Autonomous (middle)
266void AutonomousActor::ChargedUpMiddle() {
Filip Kujawaef687152023-11-14 22:11:32 -0800267 CHECK(charged_up_middle_splines_);
268
269 auto &splines = *charged_up_middle_splines_;
270
271 AOS_LOG(INFO, "Going to preload");
272
Filip Kujawaef687152023-11-14 22:11:32 -0800273 if (!splines[0].WaitForPlan()) {
274 return;
275 }
276 splines[0].Start();
277}
278
Ariv Diggi0af59c02023-10-07 13:15:39 -0700279void AutonomousActor::SendSuperstructureGoal() {
280 auto builder = superstructure_goal_sender_.MakeBuilder();
281
282 control_loops::superstructure::Goal::Builder superstructure_builder =
283 builder.MakeBuilder<control_loops::superstructure::Goal>();
284
285 if (builder.Send(superstructure_builder.Finish()) !=
286 aos::RawSender::Error::kOk) {
287 AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
288 }
289}
290
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800291} // namespace y2023_bot3::autonomous