blob: bb81194e6838ee16f3e0f43b3c56f171501b2ea3 [file] [log] [blame]
Philipp Schrader4bd29b12017-02-22 04:42:27 +00001#include "frc971/autonomous/base_autonomous_actor.h"
2
3#include <inttypes.h>
4
5#include <chrono>
6#include <cmath>
7
John Park33858a32018-09-28 23:05:48 -07008#include "aos/util/phased_loop.h"
9#include "aos/logging/logging.h"
Philipp Schrader4bd29b12017-02-22 04:42:27 +000010
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "frc971/control_loops/control_loops_generated.h"
12#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
13#include "frc971/control_loops/drivetrain/drivetrain_status_generated.h"
14#include "y2019/control_loops/drivetrain/target_selector_generated.h"
Philipp Schrader4bd29b12017-02-22 04:42:27 +000015
Philipp Schrader4bd29b12017-02-22 04:42:27 +000016using ::aos::monotonic_clock;
17namespace chrono = ::std::chrono;
18namespace this_thread = ::std::this_thread;
Alex Perrycb7da4b2019-08-28 19:35:56 -070019namespace drivetrain = frc971::control_loops::drivetrain;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000020
Brian Silvermanf83678c2017-03-11 14:02:26 -080021namespace frc971 {
22namespace autonomous {
Philipp Schrader4bd29b12017-02-22 04:42:27 +000023
24BaseAutonomousActor::BaseAutonomousActor(
Austin Schuh1bf8a212019-05-26 22:13:14 -070025 ::aos::EventLoop *event_loop,
Austin Schuhbcce26a2018-03-26 23:41:24 -070026 const control_loops::drivetrain::DrivetrainConfig<double> &dt_config)
Alex Perrycb7da4b2019-08-28 19:35:56 -070027 : aos::common::actions::ActorBase<Goal>(event_loop, "/autonomous"),
Philipp Schrader4bd29b12017-02-22 04:42:27 +000028 dt_config_(dt_config),
Austin Schuhc087b102019-05-12 15:33:12 -070029 initial_drivetrain_({0.0, 0.0}),
30 target_selector_hint_sender_(
Austin Schuheb99d072019-05-12 21:03:38 -070031 event_loop->MakeSender<
Austin Schuhc087b102019-05-12 15:33:12 -070032 ::y2019::control_loops::drivetrain::TargetSelectorHint>(
Alex Perrycb7da4b2019-08-28 19:35:56 -070033 "/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070034 drivetrain_goal_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070035 event_loop->MakeSender<drivetrain::Goal>("/drivetrain")),
James Kuszmaul75a18c52021-03-10 22:02:07 -080036 spline_goal_sender_(
37 event_loop->MakeSender<drivetrain::SplineGoal>("/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070038 drivetrain_status_fetcher_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070039 event_loop->MakeFetcher<drivetrain::Status>("/drivetrain")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -070040 drivetrain_goal_fetcher_(
Austin Schuh094d09b2020-11-20 23:26:52 -080041 event_loop->MakeFetcher<drivetrain::Goal>("/drivetrain")) {
42 event_loop->SetRuntimeRealtimePriority(29);
43}
Philipp Schrader4bd29b12017-02-22 04:42:27 +000044
45void BaseAutonomousActor::ResetDrivetrain() {
Austin Schuhf257f3c2019-10-27 21:00:43 -070046 AOS_LOG(INFO, "resetting the drivetrain\n");
Austin Schuh0aae9242018-03-14 19:49:44 -070047 max_drivetrain_voltage_ = 12.0;
James Kuszmaulc73bb222019-04-07 12:15:35 -070048 goal_spline_handle_ = 0;
Austin Schuhbd0a40f2019-06-30 14:56:31 -070049
Alex Perrycb7da4b2019-08-28 19:35:56 -070050 auto builder = drivetrain_goal_sender_.MakeBuilder();
51
52 drivetrain::Goal::Builder goal_builder =
53 builder.MakeBuilder<drivetrain::Goal>();
Austin Schuh872723c2019-12-25 14:38:09 -080054 goal_builder.add_controller_type(drivetrain::ControllerType::POLYDRIVE);
Alex Perrycb7da4b2019-08-28 19:35:56 -070055 goal_builder.add_highgear(true);
56 goal_builder.add_wheel(0.0);
57 goal_builder.add_throttle(0.0);
58 goal_builder.add_left_goal(initial_drivetrain_.left);
59 goal_builder.add_right_goal(initial_drivetrain_.right);
60 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
61 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +000062}
63
64void BaseAutonomousActor::InitializeEncoders() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -070065 // Spin until we get a message.
66 WaitUntil([this]() { return drivetrain_status_fetcher_.Fetch(); });
67
68 initial_drivetrain_.left =
Alex Perrycb7da4b2019-08-28 19:35:56 -070069 drivetrain_status_fetcher_->estimated_left_position();
Austin Schuhbd0a40f2019-06-30 14:56:31 -070070 initial_drivetrain_.right =
Alex Perrycb7da4b2019-08-28 19:35:56 -070071 drivetrain_status_fetcher_->estimated_right_position();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000072}
73
74void BaseAutonomousActor::StartDrive(double distance, double angle,
Alex Perrycb7da4b2019-08-28 19:35:56 -070075 ProfileParametersT linear,
76 ProfileParametersT angular) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070077 AOS_LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000078 {
79 const double dangle = angle * dt_config_.robot_radius;
80 initial_drivetrain_.left += distance - dangle;
81 initial_drivetrain_.right += distance + dangle;
82 }
83
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 auto builder = drivetrain_goal_sender_.MakeBuilder();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000085
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 auto linear_offset = ProfileParameters::Pack(*builder.fbb(), &linear);
87 auto angular_offset = ProfileParameters::Pack(*builder.fbb(), &angular);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000088
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 drivetrain::Goal::Builder goal_builder =
90 builder.MakeBuilder<drivetrain::Goal>();
91
Austin Schuh872723c2019-12-25 14:38:09 -080092 goal_builder.add_controller_type(drivetrain::ControllerType::MOTION_PROFILE);
Alex Perrycb7da4b2019-08-28 19:35:56 -070093 goal_builder.add_highgear(true);
94 goal_builder.add_wheel(0.0);
95 goal_builder.add_throttle(0.0);
96 goal_builder.add_left_goal(initial_drivetrain_.left);
97 goal_builder.add_right_goal(initial_drivetrain_.right);
98 goal_builder.add_max_ss_voltage(max_drivetrain_voltage_);
99 goal_builder.add_linear(linear_offset);
100 goal_builder.add_angular(angular_offset);
101
102 builder.Send(goal_builder.Finish());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000103}
104
105void BaseAutonomousActor::WaitUntilDoneOrCanceled(
106 ::std::unique_ptr<aos::common::actions::Action> action) {
107 if (!action) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700108 AOS_LOG(ERROR, "No action, not waiting\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000109 return;
110 }
111
112 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700113 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000114 ::std::chrono::milliseconds(5) / 2);
115 while (true) {
116 // Poll the running bit and see if we should cancel.
117 phased_loop.SleepUntilNext();
118 if (!action->Running() || ShouldCancel()) {
119 return;
120 }
121 }
122}
123
124bool BaseAutonomousActor::WaitForDriveDone() {
125 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700126 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000127 ::std::chrono::milliseconds(5) / 2);
128
129 while (true) {
130 if (ShouldCancel()) {
131 return false;
132 }
133 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700134 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000135 if (IsDriveDone()) {
136 return true;
137 }
138 }
139}
140
141bool BaseAutonomousActor::IsDriveDone() {
Brian Silvermanf83678c2017-03-11 14:02:26 -0800142 static constexpr double kPositionTolerance = 0.02;
143 static constexpr double kVelocityTolerance = 0.10;
144 static constexpr double kProfileTolerance = 0.001;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000145
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700146 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700147 if (::std::abs(drivetrain_status_fetcher_->profiled_left_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000148 initial_drivetrain_.left) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700149 ::std::abs(drivetrain_status_fetcher_->profiled_right_position_goal() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000150 initial_drivetrain_.right) < kProfileTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700151 ::std::abs(drivetrain_status_fetcher_->estimated_left_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000152 initial_drivetrain_.left) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700153 ::std::abs(drivetrain_status_fetcher_->estimated_right_position() -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000154 initial_drivetrain_.right) < kPositionTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700155 ::std::abs(drivetrain_status_fetcher_->estimated_left_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000156 kVelocityTolerance &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700157 ::std::abs(drivetrain_status_fetcher_->estimated_right_velocity()) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000158 kVelocityTolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700159 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000160 return true;
161 }
162 }
163 return false;
164}
165
166bool BaseAutonomousActor::WaitForAboveAngle(double angle) {
167 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700168 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000169 ::std::chrono::milliseconds(5) / 2);
170 while (true) {
171 if (ShouldCancel()) {
172 return false;
173 }
174 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700175 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000176 if (IsDriveDone()) {
177 return true;
178 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700179 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700180 if (drivetrain_status_fetcher_->ground_angle() > angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000181 return true;
182 }
183 }
184 }
185}
186
187bool BaseAutonomousActor::WaitForBelowAngle(double angle) {
188 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700189 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000190 ::std::chrono::milliseconds(5) / 2);
191 while (true) {
192 if (ShouldCancel()) {
193 return false;
194 }
195 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700196 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000197 if (IsDriveDone()) {
198 return true;
199 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700200 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700201 if (drivetrain_status_fetcher_->ground_angle() < angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000202 return true;
203 }
204 }
205 }
206}
207
208bool BaseAutonomousActor::WaitForMaxBy(double angle) {
209 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700210 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000211 ::std::chrono::milliseconds(5) / 2);
212 double max_angle = -M_PI;
213 while (true) {
214 if (ShouldCancel()) {
215 return false;
216 }
217 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700218 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000219 if (IsDriveDone()) {
220 return true;
221 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700222 if (drivetrain_status_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700223 if (drivetrain_status_fetcher_->ground_angle() > max_angle) {
224 max_angle = drivetrain_status_fetcher_->ground_angle();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000225 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700226 if (drivetrain_status_fetcher_->ground_angle() < max_angle - angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000227 return true;
228 }
229 }
230 }
231}
232
233bool BaseAutonomousActor::WaitForDriveNear(double distance, double angle) {
234 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700235 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000236 ::std::chrono::milliseconds(5) / 2);
237 constexpr double kPositionTolerance = 0.02;
238 constexpr double kProfileTolerance = 0.001;
239
Austin Schuhe6af9992018-07-08 15:59:14 -0700240 bool drive_has_been_close = false;
241 bool turn_has_been_close = false;
242 bool printed_first = false;
243
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000244 while (true) {
245 if (ShouldCancel()) {
246 return false;
247 }
248 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700249 drivetrain_status_fetcher_.Fetch();
250 if (drivetrain_status_fetcher_.get()) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000251 const double left_profile_error =
252 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700253 drivetrain_status_fetcher_->profiled_left_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000254 const double right_profile_error =
255 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700256 drivetrain_status_fetcher_->profiled_right_position_goal());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000257
258 const double left_error =
259 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700260 drivetrain_status_fetcher_->estimated_left_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000261 const double right_error =
262 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700263 drivetrain_status_fetcher_->estimated_right_position());
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000264
265 const double profile_distance_to_go =
266 (left_profile_error + right_profile_error) / 2.0;
267 const double profile_angle_to_go =
268 (right_profile_error - left_profile_error) /
269 (dt_config_.robot_radius * 2.0);
270
271 const double distance_to_go = (left_error + right_error) / 2.0;
272 const double angle_to_go =
273 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
274
Austin Schuhe6af9992018-07-08 15:59:14 -0700275 const bool drive_close =
276 ::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
277 ::std::abs(distance_to_go) < distance + kPositionTolerance;
278 const bool turn_close =
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000279 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
Austin Schuhe6af9992018-07-08 15:59:14 -0700280 ::std::abs(angle_to_go) < angle + kPositionTolerance;
281
282 drive_has_been_close |= drive_close;
283 turn_has_been_close |= turn_close;
284 if (drive_has_been_close && !turn_has_been_close && !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700285 AOS_LOG(INFO, "Drive finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700286 printed_first = true;
287 } else if (!drive_has_been_close && turn_has_been_close &&
288 !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700289 AOS_LOG(INFO, "Turn finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700290 printed_first = true;
291 }
292
293 if (drive_close && turn_close) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700294 AOS_LOG(INFO, "Closer than %f < %f distance, %f < %f angle\n",
295 distance_to_go, distance, angle_to_go, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000296 return true;
297 }
298 }
299 }
300}
301
Austin Schuh0aae9242018-03-14 19:49:44 -0700302bool BaseAutonomousActor::WaitForDriveProfileNear(double tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000303 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700304 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000305 ::std::chrono::milliseconds(5) / 2);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000306 while (true) {
307 if (ShouldCancel()) {
308 return false;
309 }
310 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700311 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700312
313 const Eigen::Matrix<double, 7, 1> current_error =
314 (Eigen::Matrix<double, 7, 1>()
315 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700316 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700317 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700318 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700319 0.0, 0.0, 0.0, 0.0)
320 .finished();
321 const Eigen::Matrix<double, 2, 1> linear_error =
322 dt_config_.LeftRightToLinear(current_error);
323
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700324 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700325 if (::std::abs(linear_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700326 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000327 return true;
328 }
329 }
330 }
331}
332
Austin Schuh0aae9242018-03-14 19:49:44 -0700333bool BaseAutonomousActor::WaitForDriveProfileDone() {
334 constexpr double kProfileTolerance = 0.001;
335 return WaitForDriveProfileNear(kProfileTolerance);
336}
337
338bool BaseAutonomousActor::WaitForTurnProfileNear(double tolerance) {
Austin Schuh546a0382017-04-16 19:10:18 -0700339 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700340 event_loop()->monotonic_now(),
Austin Schuh546a0382017-04-16 19:10:18 -0700341 ::std::chrono::milliseconds(5) / 2);
Austin Schuh546a0382017-04-16 19:10:18 -0700342 while (true) {
343 if (ShouldCancel()) {
344 return false;
345 }
346 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700347 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700348
349 const Eigen::Matrix<double, 7, 1> current_error =
350 (Eigen::Matrix<double, 7, 1>()
351 << initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700352 drivetrain_status_fetcher_->profiled_left_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700353 0.0, initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700354 drivetrain_status_fetcher_->profiled_right_position_goal(),
Austin Schuh0aae9242018-03-14 19:49:44 -0700355 0.0, 0.0, 0.0, 0.0)
356 .finished();
357 const Eigen::Matrix<double, 2, 1> angular_error =
358 dt_config_.LeftRightToAngular(current_error);
359
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700360 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700361 if (::std::abs(angular_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700362 AOS_LOG(INFO, "Finished turn\n");
Austin Schuh546a0382017-04-16 19:10:18 -0700363 return true;
364 }
365 }
366 }
367}
368
Austin Schuh0aae9242018-03-14 19:49:44 -0700369bool BaseAutonomousActor::WaitForTurnProfileDone() {
370 constexpr double kProfileTolerance = 0.001;
371 return WaitForTurnProfileNear(kProfileTolerance);
372}
373
Austin Schuh546a0382017-04-16 19:10:18 -0700374double BaseAutonomousActor::DriveDistanceLeft() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700375 drivetrain_status_fetcher_.Fetch();
376 if (drivetrain_status_fetcher_.get()) {
Austin Schuh546a0382017-04-16 19:10:18 -0700377 const double left_error =
378 (initial_drivetrain_.left -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700379 drivetrain_status_fetcher_->estimated_left_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700380 const double right_error =
381 (initial_drivetrain_.right -
Alex Perrycb7da4b2019-08-28 19:35:56 -0700382 drivetrain_status_fetcher_->estimated_right_position());
Austin Schuh546a0382017-04-16 19:10:18 -0700383
384 return (left_error + right_error) / 2.0;
385 } else {
386 return 0;
387 }
388}
389
James Kuszmaul838040b2019-04-13 15:51:02 -0700390bool BaseAutonomousActor::SplineHandle::SplineDistanceRemaining(
391 double distance) {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700392 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
393 if (base_autonomous_actor_->drivetrain_status_fetcher_.get()) {
394 return base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700395 ->trajectory_logging()
396 ->is_executing() &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700397 base_autonomous_actor_->drivetrain_status_fetcher_
Alex Perrycb7da4b2019-08-28 19:35:56 -0700398 ->trajectory_logging()
399 ->distance_remaining() < distance;
James Kuszmaul838040b2019-04-13 15:51:02 -0700400 }
401 return false;
402}
403bool BaseAutonomousActor::SplineHandle::WaitForSplineDistanceRemaining(
404 double distance) {
Austin Schuhd32b3622019-06-23 18:49:06 -0700405 ::aos::time::PhasedLoop phased_loop(
406 ::std::chrono::milliseconds(5),
407 base_autonomous_actor_->event_loop()->monotonic_now(),
408 ::std::chrono::milliseconds(5) / 2);
James Kuszmaul838040b2019-04-13 15:51:02 -0700409 while (true) {
410 if (base_autonomous_actor_->ShouldCancel()) {
411 return false;
412 }
413 phased_loop.SleepUntilNext();
414 if (SplineDistanceRemaining(distance)) {
415 return true;
416 }
417 }
418}
419
Alex Perrycb7da4b2019-08-28 19:35:56 -0700420void BaseAutonomousActor::LineFollowAtVelocity(
421 double velocity, y2019::control_loops::drivetrain::SelectionHint hint) {
422 {
423 auto builder = drivetrain_goal_sender_.MakeBuilder();
424 drivetrain::Goal::Builder goal_builder =
425 builder.MakeBuilder<drivetrain::Goal>();
426 goal_builder.add_controller_type(
Austin Schuh872723c2019-12-25 14:38:09 -0800427 drivetrain::ControllerType::SPLINE_FOLLOWER);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700428 // TODO(james): Currently the 4.0 is copied from the
429 // line_follow_drivetrain.cc, but it is somewhat year-specific, so we should
430 // factor it out in some way.
431 goal_builder.add_throttle(velocity / 4.0);
432 builder.Send(goal_builder.Finish());
433 }
434
435 {
436 auto builder = target_selector_hint_sender_.MakeBuilder();
437 ::y2019::control_loops::drivetrain::TargetSelectorHint::Builder
438 target_hint_builder = builder.MakeBuilder<
439 ::y2019::control_loops::drivetrain::TargetSelectorHint>();
440
441 target_hint_builder.add_suggested_target(hint);
442 builder.Send(target_hint_builder.Finish());
443 }
James Kuszmaul838040b2019-04-13 15:51:02 -0700444}
445
Austin Schuh6bcc2302019-03-23 22:28:06 -0700446BaseAutonomousActor::SplineHandle BaseAutonomousActor::PlanSpline(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700447 std::function<flatbuffers::Offset<frc971::MultiSpline>(
James Kuszmaul75a18c52021-03-10 22:02:07 -0800448 aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
449 *builder)> &&multispline_builder,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700450 SplineDirection direction) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700451 AOS_LOG(INFO, "Planning spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700452
453 int32_t spline_handle = (++spline_handle_) | ((getpid() & 0xFFFF) << 15);
454
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700455 drivetrain_goal_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700456
James Kuszmaul75a18c52021-03-10 22:02:07 -0800457 auto builder = spline_goal_sender_.MakeBuilder();
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700458
Alex Perrycb7da4b2019-08-28 19:35:56 -0700459 flatbuffers::Offset<frc971::MultiSpline> multispline_offset =
460 multispline_builder(&builder);
461
462 drivetrain::SplineGoal::Builder spline_builder =
463 builder.MakeBuilder<drivetrain::SplineGoal>();
464 spline_builder.add_spline_idx(spline_handle);
465 spline_builder.add_drive_spline_backwards(direction ==
466 SplineDirection::kBackward);
467 spline_builder.add_spline(multispline_offset);
468
James Kuszmaul75a18c52021-03-10 22:02:07 -0800469 builder.Send(spline_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700470
471 return BaseAutonomousActor::SplineHandle(spline_handle, this);
472}
473
474bool BaseAutonomousActor::SplineHandle::IsPlanned() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700475 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700476 VLOG(1) << aos::FlatbufferToJson(
477 base_autonomous_actor_->drivetrain_status_fetcher_.get());
478
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700479 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
James Kuszmaul75a18c52021-03-10 22:02:07 -0800480 base_autonomous_actor_->drivetrain_status_fetcher_.get()
481 ->has_trajectory_logging() &&
482 base_autonomous_actor_->drivetrain_status_fetcher_.get()
483 ->trajectory_logging()
484 ->has_available_splines()) {
485 const flatbuffers::Vector<int> *splines =
486 base_autonomous_actor_->drivetrain_status_fetcher_.get()
487 ->trajectory_logging()
488 ->available_splines();
489
490 return std::find(splines->begin(), splines->end(), spline_handle_) !=
491 splines->end();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700492 }
493 return false;
494}
495
496bool BaseAutonomousActor::SplineHandle::WaitForPlan() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700497 ::aos::time::PhasedLoop phased_loop(
498 ::std::chrono::milliseconds(5),
499 base_autonomous_actor_->event_loop()->monotonic_now(),
500 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700501 while (true) {
502 if (base_autonomous_actor_->ShouldCancel()) {
503 return false;
504 }
505 phased_loop.SleepUntilNext();
506 if (IsPlanned()) {
507 return true;
508 }
509 }
510}
511
512void BaseAutonomousActor::SplineHandle::Start() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700513 auto builder = base_autonomous_actor_->drivetrain_goal_sender_.MakeBuilder();
514 drivetrain::Goal::Builder goal_builder =
515 builder.MakeBuilder<drivetrain::Goal>();
Austin Schuh872723c2019-12-25 14:38:09 -0800516 goal_builder.add_controller_type(drivetrain::ControllerType::SPLINE_FOLLOWER);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700517
Austin Schuhf257f3c2019-10-27 21:00:43 -0700518 AOS_LOG(INFO, "Starting spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700519
Alex Perrycb7da4b2019-08-28 19:35:56 -0700520 goal_builder.add_spline_handle(spline_handle_);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700521 base_autonomous_actor_->goal_spline_handle_ = spline_handle_;
522
Alex Perrycb7da4b2019-08-28 19:35:56 -0700523 builder.Send(goal_builder.Finish());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700524}
525
526bool BaseAutonomousActor::SplineHandle::IsDone() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700527 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700528
James Kuszmaulc73bb222019-04-07 12:15:35 -0700529 // We check that the spline we are waiting on is neither currently planning
James Kuszmaul29e417d2019-04-13 10:03:35 -0700530 // nor executing (we check is_executed because it is possible to receive
531 // status messages with is_executing false before the execution has started).
532 // We check for planning so that the user can go straight from starting the
533 // planner to executing without a WaitForPlan in between.
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700534 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
Alex Perrycb7da4b2019-08-28 19:35:56 -0700535 ((!base_autonomous_actor_->drivetrain_status_fetcher_
536 ->trajectory_logging()
537 ->is_executed() &&
538 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging()
539 ->current_spline_idx() == spline_handle_) ||
James Kuszmaul75a18c52021-03-10 22:02:07 -0800540 IsPlanned())) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700541 return false;
542 }
543 return true;
544}
545
546bool BaseAutonomousActor::SplineHandle::WaitForDone() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700547 ::aos::time::PhasedLoop phased_loop(
548 ::std::chrono::milliseconds(5),
549 base_autonomous_actor_->event_loop()->monotonic_now(),
550 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700551 while (true) {
552 if (base_autonomous_actor_->ShouldCancel()) {
553 return false;
554 }
555 phased_loop.SleepUntilNext();
556 if (IsDone()) {
557 return true;
558 }
559 }
560}
561
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000562} // namespace autonomous
563} // namespace frc971