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