blob: fd42a567738f872921761f5923aff43f575505f5 [file] [log] [blame]
Niko Sohmers3860f8a2024-01-12 21:05:19 -08001#include "y2024/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 "y2024/autonomous/auto_splines.h"
11#include "y2024/constants.h"
12#include "y2024/control_loops/drivetrain/drivetrain_base.h"
13
14DEFINE_bool(spline_auto, false, "Run simple test S-spline auto mode.");
15
16namespace y2024 {
17namespace autonomous {
18
19using ::frc971::ProfileParametersT;
20
21ProfileParametersT MakeProfileParameters(float max_velocity,
22 float max_acceleration) {
23 ProfileParametersT result;
24 result.max_velocity = max_velocity;
25 result.max_acceleration = max_acceleration;
26 return result;
27}
28
29using ::aos::monotonic_clock;
30using frc971::CreateProfileParameters;
31using ::frc971::ProfileParametersT;
32using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
33using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
34using frc971::control_loops::drivetrain::LocalizerControl;
35namespace chrono = ::std::chrono;
36
37AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
38 : frc971::autonomous::BaseAutonomousActor(
39 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
40 localizer_control_sender_(
41 event_loop->MakeSender<
42 ::frc971::control_loops::drivetrain::LocalizerControl>(
43 "/drivetrain")),
44 joystick_state_fetcher_(
45 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
46 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
47 auto_splines_(),
48 superstructure_goal_sender_(
49 event_loop->MakeSender<::y2024::control_loops::superstructure::Goal>(
50 "/superstructure")),
51 superstructure_status_fetcher_(
52 event_loop
53 ->MakeFetcher<::y2024::control_loops::superstructure::Status>(
54 "/superstructure")) {
55 drivetrain_status_fetcher_.Fetch();
56 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
57
58 event_loop->OnRun([this, event_loop]() {
59 replan_timer_->Schedule(event_loop->monotonic_now());
60 button_poll_->Schedule(event_loop->monotonic_now(),
61 chrono::milliseconds(50));
62 });
63
64 // TODO(james): Really need to refactor this code since we keep using it.
65 button_poll_ = event_loop->AddTimer([this]() {
66 const aos::monotonic_clock::time_point now =
67 this->event_loop()->context().monotonic_event_time;
68 if (robot_state_fetcher_.Fetch()) {
69 if (robot_state_fetcher_->user_button()) {
70 user_indicated_safe_to_reset_ = true;
71 MaybeSendStartingPosition();
72 }
73 }
74 if (joystick_state_fetcher_.Fetch()) {
75 if (joystick_state_fetcher_->has_alliance() &&
76 (joystick_state_fetcher_->alliance() != alliance_)) {
77 alliance_ = joystick_state_fetcher_->alliance();
78 is_planned_ = false;
79 // Only kick the planning out by 2 seconds. If we end up enabled in
80 // that second, then we will kick it out further based on the code
81 // below.
82 replan_timer_->Schedule(now + std::chrono::seconds(2));
83 }
84 if (joystick_state_fetcher_->enabled()) {
85 if (!is_planned_) {
86 // Only replan once we've been disabled for 5 seconds.
87 replan_timer_->Schedule(now + std::chrono::seconds(5));
88 }
89 }
90 }
91 });
92}
93
94void AutonomousActor::Replan() {
95 if (!drivetrain_status_fetcher_.Fetch()) {
96 replan_timer_->Schedule(event_loop()->monotonic_now() + chrono::seconds(1));
97 AOS_LOG(INFO, "Drivetrain not up, replanning in 1 second");
98 return;
99 }
100
101 if (alliance_ == aos::Alliance::kInvalid) {
102 return;
103 }
104 sent_starting_position_ = false;
105 if (FLAGS_spline_auto) {
106 test_spline_ =
107 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
108 std::placeholders::_1, alliance_),
109 SplineDirection::kForward);
110
111 starting_position_ = test_spline_->starting_position();
112 }
113
114 is_planned_ = true;
115
116 MaybeSendStartingPosition();
117}
118
119void AutonomousActor::MaybeSendStartingPosition() {
120 if (is_planned_ && user_indicated_safe_to_reset_ &&
121 !sent_starting_position_) {
122 CHECK(starting_position_);
123 SendStartingPosition(starting_position_.value());
124 }
125}
126
127void AutonomousActor::Reset() {
128 InitializeEncoders();
129 ResetDrivetrain();
130
131 joystick_state_fetcher_.Fetch();
132 CHECK(joystick_state_fetcher_.get() != nullptr)
133 << "Expect at least one JoystickState message before running auto...";
134 alliance_ = joystick_state_fetcher_->alliance();
135 preloaded_ = false;
136}
137
138bool AutonomousActor::RunAction(
139 const ::frc971::autonomous::AutonomousActionParams *params) {
140 Reset();
141
142 AOS_LOG(INFO, "Params are %d\n", params->mode());
143
144 if (!user_indicated_safe_to_reset_) {
145 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
146 CHECK(starting_position_);
147 SendStartingPosition(starting_position_.value());
148 }
149 // Clear this so that we don't accidentally resend things as soon as we
150 // replan later.
151 user_indicated_safe_to_reset_ = false;
152 is_planned_ = false;
153 starting_position_.reset();
154
155 AOS_LOG(INFO, "Params are %d\n", params->mode());
156 if (alliance_ == aos::Alliance::kInvalid) {
157 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
158 return false;
159 }
160 if (FLAGS_spline_auto) {
161 SplineAuto();
162 } else {
163 AOS_LOG(WARNING, "No auto mode selected.");
164 }
165 return true;
166}
167
168void AutonomousActor::SplineAuto() {
169 CHECK(test_spline_);
170
171 if (!test_spline_->WaitForPlan()) return;
172 test_spline_->Start();
173
174 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
175}
176
177void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
178 // Set up the starting position for the blue alliance.
179
180 auto builder = localizer_control_sender_.MakeBuilder();
181
182 LocalizerControl::Builder localizer_control_builder =
183 builder.MakeBuilder<LocalizerControl>();
184 localizer_control_builder.add_x(start(0));
185 localizer_control_builder.add_y(start(1));
186 localizer_control_builder.add_theta(start(2));
187 localizer_control_builder.add_theta_uncertainty(0.00001);
188 AOS_LOG(INFO, "User button pressed, x: %f y: %f theta: %f", start(0),
189 start(1), start(2));
190 if (builder.Send(localizer_control_builder.Finish()) !=
191 aos::RawSender::Error::kOk) {
192 AOS_LOG(ERROR, "Failed to reset localizer.\n");
193 }
194}
195} // namespace autonomous
196} // namespace y2024