blob: 1ee34f73736f2431320dcfebe930383d5fc865c5 [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");
16
milind-u086d7262022-01-19 20:44:18 -080017namespace y2022 {
18namespace actors {
Ravago Jones81e50632022-03-11 16:23:51 -080019namespace {
20constexpr double kExtendIntakeGoal = 0.0;
21constexpr double kRetractIntakeGoal = 1.47;
22constexpr double kRollerVoltage = 12.0;
23constexpr double kCatapultReturnPosition = -0.908;
24} // namespace
milind-u086d7262022-01-19 20:44:18 -080025
26using ::aos::monotonic_clock;
Ravago Jones81e50632022-03-11 16:23:51 -080027using frc971::CreateProfileParameters;
milind-u086d7262022-01-19 20:44:18 -080028using ::frc971::ProfileParametersT;
Ravago Jones81e50632022-03-11 16:23:51 -080029using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
30using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
milind-u086d7262022-01-19 20:44:18 -080031using frc971::control_loops::drivetrain::LocalizerControl;
Ravago Jones81e50632022-03-11 16:23:51 -080032
milind-u086d7262022-01-19 20:44:18 -080033namespace chrono = ::std::chrono;
34
35AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
36 : frc971::autonomous::BaseAutonomousActor(
Ravago Jones81e50632022-03-11 16:23:51 -080037 event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
38 localizer_control_sender_(
39 event_loop->MakeSender<
40 ::frc971::control_loops::drivetrain::LocalizerControl>(
41 "/drivetrain")),
42 superstructure_goal_sender_(
43 event_loop->MakeSender<control_loops::superstructure::Goal>(
44 "/superstructure")),
45 superstructure_status_fetcher_(
46 event_loop->MakeFetcher<control_loops::superstructure::Status>(
47 "/superstructure")),
48 joystick_state_fetcher_(
49 event_loop->MakeFetcher<aos::JoystickState>("/aos")),
50 robot_state_fetcher_(event_loop->MakeFetcher<aos::RobotState>("/aos")),
51 auto_splines_() {
52 set_max_drivetrain_voltage(12.0);
53 replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
54 event_loop->OnRun([this, event_loop]() {
55 replan_timer_->Setup(event_loop->monotonic_now());
56 button_poll_->Setup(event_loop->monotonic_now(), chrono::milliseconds(50));
57 });
58
59 button_poll_ = event_loop->AddTimer([this]() {
60 const aos::monotonic_clock::time_point now =
61 this->event_loop()->context().monotonic_event_time;
62 if (robot_state_fetcher_.Fetch()) {
63 if (robot_state_fetcher_->user_button()) {
64 user_indicated_safe_to_reset_ = true;
65 MaybeSendStartingPosition();
66 }
67 }
68 if (joystick_state_fetcher_.Fetch()) {
69 if (joystick_state_fetcher_->has_alliance() &&
70 (joystick_state_fetcher_->alliance() != alliance_)) {
71 alliance_ = joystick_state_fetcher_->alliance();
72 is_planned_ = false;
73 // Only kick the planning out by 2 seconds. If we end up enabled in that
74 // second, then we will kick it out further based on the code below.
75 replan_timer_->Setup(now + std::chrono::seconds(2));
76 }
77 if (joystick_state_fetcher_->enabled()) {
78 if (!is_planned_) {
79 // Only replan once we've been disabled for 5 seconds.
80 replan_timer_->Setup(now + std::chrono::seconds(5));
81 }
82 }
83 }
84 });
85}
86
87void AutonomousActor::Replan() {
88 LOG(INFO) << "Alliance " << static_cast<int>(alliance_);
89 if (alliance_ == aos::Alliance::kInvalid) {
90 return;
91 }
92 sent_starting_position_ = false;
93 if (FLAGS_spline_auto) {
94 test_spline_ =
95 PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
96 std::placeholders::_1, alliance_),
97 SplineDirection::kForward);
98
99 starting_position_ = test_spline_->starting_position();
100 }
101
102 is_planned_ = true;
103
104 MaybeSendStartingPosition();
105}
106
107void AutonomousActor::MaybeSendStartingPosition() {
108 if (is_planned_ && user_indicated_safe_to_reset_ &&
109 !sent_starting_position_) {
110 CHECK(starting_position_);
111 SendStartingPosition(starting_position_.value());
112 }
113}
milind-u086d7262022-01-19 20:44:18 -0800114
115void AutonomousActor::Reset() {
116 InitializeEncoders();
117 ResetDrivetrain();
Ravago Jones81e50632022-03-11 16:23:51 -0800118 RetractFrontIntake();
119 RetractBackIntake();
120
121 joystick_state_fetcher_.Fetch();
122 CHECK(joystick_state_fetcher_.get() != nullptr)
123 << "Expect at least one JoystickState message before running auto...";
124 alliance_ = joystick_state_fetcher_->alliance();
milind-u086d7262022-01-19 20:44:18 -0800125}
126
127bool AutonomousActor::RunAction(
128 const ::frc971::autonomous::AutonomousActionParams *params) {
129 Reset();
Ravago Jones81e50632022-03-11 16:23:51 -0800130 if (!user_indicated_safe_to_reset_) {
131 AOS_LOG(WARNING, "Didn't send starting position prior to starting auto.");
132 CHECK(starting_position_);
133 SendStartingPosition(starting_position_.value());
134 }
135 // Clear this so that we don't accidentally resend things as soon as we replan
136 // later.
137 user_indicated_safe_to_reset_ = false;
138 is_planned_ = false;
139 starting_position_.reset();
milind-u086d7262022-01-19 20:44:18 -0800140
141 AOS_LOG(INFO, "Params are %d\n", params->mode());
Ravago Jones81e50632022-03-11 16:23:51 -0800142 if (alliance_ == aos::Alliance::kInvalid) {
143 AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
144 return false;
145 }
146 if (FLAGS_spline_auto) {
147 SplineAuto();
148 }
149
milind-u086d7262022-01-19 20:44:18 -0800150 return true;
151}
152
Ravago Jones81e50632022-03-11 16:23:51 -0800153void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
154 // Set up the starting position for the blue alliance.
155
156 // TODO(james): Resetting the localizer breaks the left/right statespace
157 // controller. That is a bug, but we can fix that later by not resetting.
158 auto builder = localizer_control_sender_.MakeBuilder();
159
160 LocalizerControl::Builder localizer_control_builder =
161 builder.MakeBuilder<LocalizerControl>();
162 localizer_control_builder.add_x(start(0));
163 localizer_control_builder.add_y(start(1));
164 localizer_control_builder.add_theta(start(2));
165 localizer_control_builder.add_theta_uncertainty(0.00001);
166 LOG(INFO) << "User button pressed, x: " << start(0) << " y: " << start(1)
167 << " theta: " << start(2);
168 if (builder.Send(localizer_control_builder.Finish()) !=
169 aos::RawSender::Error::kOk) {
170 AOS_LOG(ERROR, "Failed to reset localizer.\n");
171 }
172}
173
174void AutonomousActor::SplineAuto() {
175 CHECK(test_spline_);
176
177 if (!test_spline_->WaitForPlan()) return;
178 test_spline_->Start();
179
180 if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
181}
182
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800183bool AutonomousActor::WaitForPreloaded() {
184 set_preloaded(true);
185 SendSuperstructureGoal();
186
187 ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
188 event_loop()->monotonic_now(),
189 ActorBase::kLoopOffset);
190
191 bool loaded = false;
192 while (!loaded) {
193 if (ShouldCancel()) {
194 return false;
195 }
196
197 phased_loop.SleepUntilNext();
198 superstructure_status_fetcher_.Fetch();
199 CHECK(superstructure_status_fetcher_.get() != nullptr);
200
201 loaded = (superstructure_status_fetcher_->state() ==
202 control_loops::superstructure::SuperstructureState::LOADED);
203 }
204
205 set_preloaded(false);
206 SendSuperstructureGoal();
207
208 return true;
209}
210
Ravago Jones81e50632022-03-11 16:23:51 -0800211void AutonomousActor::SendSuperstructureGoal() {
212 auto builder = superstructure_goal_sender_.MakeBuilder();
213
214 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
215 intake_front_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
216 *builder.fbb(), intake_front_goal_,
217 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
218
219 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
220 intake_back_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
221 *builder.fbb(), intake_back_goal_,
222 CreateProfileParameters(*builder.fbb(), 20.0, 60.0));
223
224 flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
225 catapult_return_position_offset =
226 CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
227 *builder.fbb(), kCatapultReturnPosition,
228 CreateProfileParameters(*builder.fbb(), 9.0, 50.0));
229
230 superstructure::CatapultGoal::Builder catapult_goal_builder(*builder.fbb());
231 catapult_goal_builder.add_shot_position(0.03);
232 catapult_goal_builder.add_shot_velocity(18.0);
233 catapult_goal_builder.add_return_position(catapult_return_position_offset);
234 flatbuffers::Offset<superstructure::CatapultGoal> catapult_goal_offset =
235 catapult_goal_builder.Finish();
236
237 superstructure::Goal::Builder superstructure_builder =
238 builder.MakeBuilder<superstructure::Goal>();
239
240 superstructure_builder.add_intake_front(intake_front_offset);
241 superstructure_builder.add_intake_back(intake_back_offset);
242 superstructure_builder.add_roller_speed_compensation(1.5);
243 superstructure_builder.add_roller_speed_front(roller_front_voltage_);
244 superstructure_builder.add_roller_speed_back(roller_back_voltage_);
245 superstructure_builder.add_transfer_roller_speed(transfer_roller_voltage_);
246 superstructure_builder.add_catapult(catapult_goal_offset);
247 superstructure_builder.add_fire(fire_);
Milind Upadhyay803bbf02022-03-11 17:56:26 -0800248 superstructure_builder.add_preloaded(preloaded_);
Ravago Jones81e50632022-03-11 16:23:51 -0800249 superstructure_builder.add_auto_aim(true);
250
251 if (builder.Send(superstructure_builder.Finish()) !=
252 aos::RawSender::Error::kOk) {
253 AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
254 }
255}
256
257void AutonomousActor::ExtendFrontIntake() {
258 set_intake_front_goal(kExtendIntakeGoal);
259 set_roller_front_voltage(kRollerVoltage);
260 set_transfer_roller_voltage(kRollerVoltage);
261 SendSuperstructureGoal();
262}
263
264void AutonomousActor::RetractFrontIntake() {
265 set_intake_front_goal(kRetractIntakeGoal);
266 set_roller_front_voltage(kRollerVoltage);
267 set_transfer_roller_voltage(0.0);
268 SendSuperstructureGoal();
269}
270
271void AutonomousActor::ExtendBackIntake() {
272 set_intake_back_goal(kExtendIntakeGoal);
273 set_roller_back_voltage(kRollerVoltage);
274 set_transfer_roller_voltage(-kRollerVoltage);
275 SendSuperstructureGoal();
276}
277
278void AutonomousActor::RetractBackIntake() {
279 set_intake_back_goal(kRetractIntakeGoal);
280 set_roller_back_voltage(kRollerVoltage);
281 set_transfer_roller_voltage(0.0);
282 SendSuperstructureGoal();
283}
284
milind-u086d7262022-01-19 20:44:18 -0800285} // namespace actors
286} // namespace y2022