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