blob: 367e8495ff029bd46b8c388a6836ba2394b5bb2d [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
11#include "frc971/control_loops/drivetrain/drivetrain.q.h"
James Kuszmaul8bb5df22019-05-01 21:40:08 -050012#include "frc971/control_loops/drivetrain/localizer.q.h"
13#include "y2019/control_loops/drivetrain/target_selector.q.h"
Philipp Schrader4bd29b12017-02-22 04:42:27 +000014
Philipp Schrader4bd29b12017-02-22 04:42:27 +000015using ::aos::monotonic_clock;
16namespace chrono = ::std::chrono;
17namespace this_thread = ::std::this_thread;
18
Brian Silvermanf83678c2017-03-11 14:02:26 -080019namespace frc971 {
20namespace autonomous {
Philipp Schrader4bd29b12017-02-22 04:42:27 +000021
22BaseAutonomousActor::BaseAutonomousActor(
Austin Schuh1bf8a212019-05-26 22:13:14 -070023 ::aos::EventLoop *event_loop,
Austin Schuhbcce26a2018-03-26 23:41:24 -070024 const control_loops::drivetrain::DrivetrainConfig<double> &dt_config)
Austin Schuh1bf8a212019-05-26 22:13:14 -070025 : aos::common::actions::ActorBase<AutonomousActionQueueGroup>(
26 event_loop, ".frc971.autonomous.autonomous_action"),
Philipp Schrader4bd29b12017-02-22 04:42:27 +000027 dt_config_(dt_config),
Austin Schuhc087b102019-05-12 15:33:12 -070028 initial_drivetrain_({0.0, 0.0}),
29 target_selector_hint_sender_(
Austin Schuheb99d072019-05-12 21:03:38 -070030 event_loop->MakeSender<
Austin Schuhc087b102019-05-12 15:33:12 -070031 ::y2019::control_loops::drivetrain::TargetSelectorHint>(
Austin Schuhbd0a40f2019-06-30 14:56:31 -070032 ".y2019.control_loops.drivetrain.target_selector_hint")),
33 drivetrain_goal_sender_(
34 event_loop
35 ->MakeSender<::frc971::control_loops::DrivetrainQueue::Goal>(
36 ".frc971.control_loops.drivetrain_queue.goal")),
37 drivetrain_status_fetcher_(
38 event_loop
39 ->MakeFetcher<::frc971::control_loops::DrivetrainQueue::Status>(
40 ".frc971.control_loops.drivetrain_queue.status")),
41 drivetrain_goal_fetcher_(
42 event_loop
43 ->MakeFetcher<::frc971::control_loops::DrivetrainQueue::Goal>(
44 ".frc971.control_loops.drivetrain_queue.goal")) {}
Philipp Schrader4bd29b12017-02-22 04:42:27 +000045
46void BaseAutonomousActor::ResetDrivetrain() {
Austin Schuhf257f3c2019-10-27 21:00:43 -070047 AOS_LOG(INFO, "resetting the drivetrain\n");
Austin Schuh0aae9242018-03-14 19:49:44 -070048 max_drivetrain_voltage_ = 12.0;
James Kuszmaulc73bb222019-04-07 12:15:35 -070049 goal_spline_handle_ = 0;
Austin Schuhbd0a40f2019-06-30 14:56:31 -070050
51 auto drivetrain_goal_message = drivetrain_goal_sender_.MakeMessage();
52 drivetrain_goal_message->controller_type = 0;
53 drivetrain_goal_message->highgear = true;
54 drivetrain_goal_message->wheel = 0.0;
55 drivetrain_goal_message->throttle = 0.0;
56 drivetrain_goal_message->left_goal = initial_drivetrain_.left;
57 drivetrain_goal_message->right_goal = initial_drivetrain_.right;
58 drivetrain_goal_message->max_ss_voltage = max_drivetrain_voltage_;
59 drivetrain_goal_message.Send();
Philipp Schrader4bd29b12017-02-22 04:42:27 +000060}
61
62void BaseAutonomousActor::InitializeEncoders() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -070063 // Spin until we get a message.
64 WaitUntil([this]() { return drivetrain_status_fetcher_.Fetch(); });
65
66 initial_drivetrain_.left =
67 drivetrain_status_fetcher_->estimated_left_position;
68 initial_drivetrain_.right =
69 drivetrain_status_fetcher_->estimated_right_position;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000070}
71
72void BaseAutonomousActor::StartDrive(double distance, double angle,
73 ProfileParameters linear,
74 ProfileParameters angular) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070075 AOS_LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000076 {
77 const double dangle = angle * dt_config_.robot_radius;
78 initial_drivetrain_.left += distance - dangle;
79 initial_drivetrain_.right += distance + dangle;
80 }
81
Austin Schuhbd0a40f2019-06-30 14:56:31 -070082 auto drivetrain_message = drivetrain_goal_sender_.MakeMessage();
Austin Schuh78379ea2019-01-04 20:39:45 -080083 drivetrain_message->controller_type = 1;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000084 drivetrain_message->highgear = true;
Austin Schuh2b1fce02018-03-02 20:05:20 -080085 drivetrain_message->wheel = 0.0;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000086 drivetrain_message->throttle = 0.0;
87 drivetrain_message->left_goal = initial_drivetrain_.left;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000088 drivetrain_message->right_goal = initial_drivetrain_.right;
Austin Schuh0aae9242018-03-14 19:49:44 -070089 drivetrain_message->max_ss_voltage = max_drivetrain_voltage_;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000090 drivetrain_message->linear = linear;
91 drivetrain_message->angular = angular;
92
Austin Schuhf257f3c2019-10-27 21:00:43 -070093 AOS_LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000094
95 drivetrain_message.Send();
96}
97
98void BaseAutonomousActor::WaitUntilDoneOrCanceled(
99 ::std::unique_ptr<aos::common::actions::Action> action) {
100 if (!action) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700101 AOS_LOG(ERROR, "No action, not waiting\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000102 return;
103 }
104
105 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700106 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000107 ::std::chrono::milliseconds(5) / 2);
108 while (true) {
109 // Poll the running bit and see if we should cancel.
110 phased_loop.SleepUntilNext();
111 if (!action->Running() || ShouldCancel()) {
112 return;
113 }
114 }
115}
116
117bool BaseAutonomousActor::WaitForDriveDone() {
118 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700119 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000120 ::std::chrono::milliseconds(5) / 2);
121
122 while (true) {
123 if (ShouldCancel()) {
124 return false;
125 }
126 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700127 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000128 if (IsDriveDone()) {
129 return true;
130 }
131 }
132}
133
134bool BaseAutonomousActor::IsDriveDone() {
Brian Silvermanf83678c2017-03-11 14:02:26 -0800135 static constexpr double kPositionTolerance = 0.02;
136 static constexpr double kVelocityTolerance = 0.10;
137 static constexpr double kProfileTolerance = 0.001;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000138
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700139 if (drivetrain_status_fetcher_.get()) {
140 if (::std::abs(drivetrain_status_fetcher_->profiled_left_position_goal -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000141 initial_drivetrain_.left) < kProfileTolerance &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700142 ::std::abs(drivetrain_status_fetcher_->profiled_right_position_goal -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000143 initial_drivetrain_.right) < kProfileTolerance &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700144 ::std::abs(drivetrain_status_fetcher_->estimated_left_position -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000145 initial_drivetrain_.left) < kPositionTolerance &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700146 ::std::abs(drivetrain_status_fetcher_->estimated_right_position -
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000147 initial_drivetrain_.right) < kPositionTolerance &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700148 ::std::abs(drivetrain_status_fetcher_->estimated_left_velocity) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000149 kVelocityTolerance &&
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700150 ::std::abs(drivetrain_status_fetcher_->estimated_right_velocity) <
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000151 kVelocityTolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700152 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000153 return true;
154 }
155 }
156 return false;
157}
158
159bool BaseAutonomousActor::WaitForAboveAngle(double angle) {
160 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700161 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000162 ::std::chrono::milliseconds(5) / 2);
163 while (true) {
164 if (ShouldCancel()) {
165 return false;
166 }
167 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700168 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000169 if (IsDriveDone()) {
170 return true;
171 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700172 if (drivetrain_status_fetcher_.get()) {
173 if (drivetrain_status_fetcher_->ground_angle > angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000174 return true;
175 }
176 }
177 }
178}
179
180bool BaseAutonomousActor::WaitForBelowAngle(double angle) {
181 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700182 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000183 ::std::chrono::milliseconds(5) / 2);
184 while (true) {
185 if (ShouldCancel()) {
186 return false;
187 }
188 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700189 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000190 if (IsDriveDone()) {
191 return true;
192 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700193 if (drivetrain_status_fetcher_.get()) {
194 if (drivetrain_status_fetcher_->ground_angle < angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000195 return true;
196 }
197 }
198 }
199}
200
201bool BaseAutonomousActor::WaitForMaxBy(double angle) {
202 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700203 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000204 ::std::chrono::milliseconds(5) / 2);
205 double max_angle = -M_PI;
206 while (true) {
207 if (ShouldCancel()) {
208 return false;
209 }
210 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700211 drivetrain_status_fetcher_.Fetch();
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000212 if (IsDriveDone()) {
213 return true;
214 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700215 if (drivetrain_status_fetcher_.get()) {
216 if (drivetrain_status_fetcher_->ground_angle > max_angle) {
217 max_angle = drivetrain_status_fetcher_->ground_angle;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000218 }
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700219 if (drivetrain_status_fetcher_->ground_angle < max_angle - angle) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000220 return true;
221 }
222 }
223 }
224}
225
226bool BaseAutonomousActor::WaitForDriveNear(double distance, double angle) {
227 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700228 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000229 ::std::chrono::milliseconds(5) / 2);
230 constexpr double kPositionTolerance = 0.02;
231 constexpr double kProfileTolerance = 0.001;
232
Austin Schuhe6af9992018-07-08 15:59:14 -0700233 bool drive_has_been_close = false;
234 bool turn_has_been_close = false;
235 bool printed_first = false;
236
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000237 while (true) {
238 if (ShouldCancel()) {
239 return false;
240 }
241 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700242 drivetrain_status_fetcher_.Fetch();
243 if (drivetrain_status_fetcher_.get()) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000244 const double left_profile_error =
245 (initial_drivetrain_.left -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700246 drivetrain_status_fetcher_->profiled_left_position_goal);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000247 const double right_profile_error =
248 (initial_drivetrain_.right -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700249 drivetrain_status_fetcher_->profiled_right_position_goal);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000250
251 const double left_error =
252 (initial_drivetrain_.left -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700253 drivetrain_status_fetcher_->estimated_left_position);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000254 const double right_error =
255 (initial_drivetrain_.right -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700256 drivetrain_status_fetcher_->estimated_right_position);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000257
258 const double profile_distance_to_go =
259 (left_profile_error + right_profile_error) / 2.0;
260 const double profile_angle_to_go =
261 (right_profile_error - left_profile_error) /
262 (dt_config_.robot_radius * 2.0);
263
264 const double distance_to_go = (left_error + right_error) / 2.0;
265 const double angle_to_go =
266 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
267
Austin Schuhe6af9992018-07-08 15:59:14 -0700268 const bool drive_close =
269 ::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
270 ::std::abs(distance_to_go) < distance + kPositionTolerance;
271 const bool turn_close =
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000272 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
Austin Schuhe6af9992018-07-08 15:59:14 -0700273 ::std::abs(angle_to_go) < angle + kPositionTolerance;
274
275 drive_has_been_close |= drive_close;
276 turn_has_been_close |= turn_close;
277 if (drive_has_been_close && !turn_has_been_close && !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700278 AOS_LOG(INFO, "Drive finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700279 printed_first = true;
280 } else if (!drive_has_been_close && turn_has_been_close &&
281 !printed_first) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700282 AOS_LOG(INFO, "Turn finished first\n");
Austin Schuhe6af9992018-07-08 15:59:14 -0700283 printed_first = true;
284 }
285
286 if (drive_close && turn_close) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700287 AOS_LOG(INFO, "Closer than %f < %f distance, %f < %f angle\n",
288 distance_to_go, distance, angle_to_go, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000289 return true;
290 }
291 }
292 }
293}
294
Austin Schuh0aae9242018-03-14 19:49:44 -0700295bool BaseAutonomousActor::WaitForDriveProfileNear(double tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000296 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700297 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000298 ::std::chrono::milliseconds(5) / 2);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000299 while (true) {
300 if (ShouldCancel()) {
301 return false;
302 }
303 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700304 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700305
306 const Eigen::Matrix<double, 7, 1> current_error =
307 (Eigen::Matrix<double, 7, 1>()
308 << initial_drivetrain_.left -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700309 drivetrain_status_fetcher_->profiled_left_position_goal,
Austin Schuh0aae9242018-03-14 19:49:44 -0700310 0.0, initial_drivetrain_.right -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700311 drivetrain_status_fetcher_->profiled_right_position_goal,
Austin Schuh0aae9242018-03-14 19:49:44 -0700312 0.0, 0.0, 0.0, 0.0)
313 .finished();
314 const Eigen::Matrix<double, 2, 1> linear_error =
315 dt_config_.LeftRightToLinear(current_error);
316
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700317 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700318 if (::std::abs(linear_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700319 AOS_LOG(INFO, "Finished drive\n");
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000320 return true;
321 }
322 }
323 }
324}
325
Austin Schuh0aae9242018-03-14 19:49:44 -0700326bool BaseAutonomousActor::WaitForDriveProfileDone() {
327 constexpr double kProfileTolerance = 0.001;
328 return WaitForDriveProfileNear(kProfileTolerance);
329}
330
331bool BaseAutonomousActor::WaitForTurnProfileNear(double tolerance) {
Austin Schuh546a0382017-04-16 19:10:18 -0700332 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700333 event_loop()->monotonic_now(),
Austin Schuh546a0382017-04-16 19:10:18 -0700334 ::std::chrono::milliseconds(5) / 2);
Austin Schuh546a0382017-04-16 19:10:18 -0700335 while (true) {
336 if (ShouldCancel()) {
337 return false;
338 }
339 phased_loop.SleepUntilNext();
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700340 drivetrain_status_fetcher_.Fetch();
Austin Schuh0aae9242018-03-14 19:49:44 -0700341
342 const Eigen::Matrix<double, 7, 1> current_error =
343 (Eigen::Matrix<double, 7, 1>()
344 << initial_drivetrain_.left -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700345 drivetrain_status_fetcher_->profiled_left_position_goal,
Austin Schuh0aae9242018-03-14 19:49:44 -0700346 0.0, initial_drivetrain_.right -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700347 drivetrain_status_fetcher_->profiled_right_position_goal,
Austin Schuh0aae9242018-03-14 19:49:44 -0700348 0.0, 0.0, 0.0, 0.0)
349 .finished();
350 const Eigen::Matrix<double, 2, 1> angular_error =
351 dt_config_.LeftRightToAngular(current_error);
352
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700353 if (drivetrain_status_fetcher_.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700354 if (::std::abs(angular_error(0)) < tolerance) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700355 AOS_LOG(INFO, "Finished turn\n");
Austin Schuh546a0382017-04-16 19:10:18 -0700356 return true;
357 }
358 }
359 }
360}
361
Austin Schuh0aae9242018-03-14 19:49:44 -0700362bool BaseAutonomousActor::WaitForTurnProfileDone() {
363 constexpr double kProfileTolerance = 0.001;
364 return WaitForTurnProfileNear(kProfileTolerance);
365}
366
Austin Schuh546a0382017-04-16 19:10:18 -0700367double BaseAutonomousActor::DriveDistanceLeft() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700368 drivetrain_status_fetcher_.Fetch();
369 if (drivetrain_status_fetcher_.get()) {
Austin Schuh546a0382017-04-16 19:10:18 -0700370 const double left_error =
371 (initial_drivetrain_.left -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700372 drivetrain_status_fetcher_->estimated_left_position);
Austin Schuh546a0382017-04-16 19:10:18 -0700373 const double right_error =
374 (initial_drivetrain_.right -
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700375 drivetrain_status_fetcher_->estimated_right_position);
Austin Schuh546a0382017-04-16 19:10:18 -0700376
377 return (left_error + right_error) / 2.0;
378 } else {
379 return 0;
380 }
381}
382
James Kuszmaul838040b2019-04-13 15:51:02 -0700383bool BaseAutonomousActor::SplineHandle::SplineDistanceRemaining(
384 double distance) {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700385 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
386 if (base_autonomous_actor_->drivetrain_status_fetcher_.get()) {
387 return base_autonomous_actor_->drivetrain_status_fetcher_
388 ->trajectory_logging.is_executing &&
389 base_autonomous_actor_->drivetrain_status_fetcher_
390 ->trajectory_logging.distance_remaining < distance;
James Kuszmaul838040b2019-04-13 15:51:02 -0700391 }
392 return false;
393}
394bool BaseAutonomousActor::SplineHandle::WaitForSplineDistanceRemaining(
395 double distance) {
Austin Schuhd32b3622019-06-23 18:49:06 -0700396 ::aos::time::PhasedLoop phased_loop(
397 ::std::chrono::milliseconds(5),
398 base_autonomous_actor_->event_loop()->monotonic_now(),
399 ::std::chrono::milliseconds(5) / 2);
James Kuszmaul838040b2019-04-13 15:51:02 -0700400 while (true) {
401 if (base_autonomous_actor_->ShouldCancel()) {
402 return false;
403 }
404 phased_loop.SleepUntilNext();
405 if (SplineDistanceRemaining(distance)) {
406 return true;
407 }
408 }
409}
410
James Kuszmaul8bb5df22019-05-01 21:40:08 -0500411void BaseAutonomousActor::LineFollowAtVelocity(double velocity, int hint) {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700412 auto drivetrain_message = drivetrain_goal_sender_.MakeMessage();
James Kuszmaul838040b2019-04-13 15:51:02 -0700413 drivetrain_message->controller_type = 3;
414 // TODO(james): Currently the 4.0 is copied from the
415 // line_follow_drivetrain.cc, but it is somewhat year-specific, so we should
416 // factor it out in some way.
417 drivetrain_message->throttle = velocity / 4.0;
418 drivetrain_message.Send();
Austin Schuhc087b102019-05-12 15:33:12 -0700419 auto target_hint = target_selector_hint_sender_.MakeMessage();
James Kuszmaul8bb5df22019-05-01 21:40:08 -0500420 target_hint->suggested_target = hint;
421 target_hint.Send();
James Kuszmaul838040b2019-04-13 15:51:02 -0700422}
423
Austin Schuh6bcc2302019-03-23 22:28:06 -0700424BaseAutonomousActor::SplineHandle BaseAutonomousActor::PlanSpline(
James Kuszmaulc73bb222019-04-07 12:15:35 -0700425 const ::frc971::MultiSpline &spline, SplineDirection direction) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700426 AOS_LOG(INFO, "Planning spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700427
428 int32_t spline_handle = (++spline_handle_) | ((getpid() & 0xFFFF) << 15);
429
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700430 drivetrain_goal_fetcher_.Fetch();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700431
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700432 auto drivetrain_message =
433 drivetrain_goal_sender_.MakeMessage();
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700434
435 int controller_type = 2;
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700436 if (drivetrain_goal_fetcher_.get()) {
437 controller_type = drivetrain_goal_fetcher_->controller_type;
438 drivetrain_message->throttle = drivetrain_goal_fetcher_->throttle;
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700439 }
440 drivetrain_message->controller_type = controller_type;
Austin Schuh6bcc2302019-03-23 22:28:06 -0700441
442 drivetrain_message->spline = spline;
443 drivetrain_message->spline.spline_idx = spline_handle;
444 drivetrain_message->spline_handle = goal_spline_handle_;
James Kuszmaul29e417d2019-04-13 10:03:35 -0700445 drivetrain_message->spline.drive_spline_backwards =
James Kuszmaulc73bb222019-04-07 12:15:35 -0700446 direction == SplineDirection::kBackward;
Austin Schuh6bcc2302019-03-23 22:28:06 -0700447
Austin Schuhf257f3c2019-10-27 21:00:43 -0700448 AOS_LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700449
450 drivetrain_message.Send();
451
452 return BaseAutonomousActor::SplineHandle(spline_handle, this);
453}
454
455bool BaseAutonomousActor::SplineHandle::IsPlanned() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700456 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Austin Schuhf257f3c2019-10-27 21:00:43 -0700457 AOS_LOG_STRUCT(DEBUG, "dts",
458 *(base_autonomous_actor_->drivetrain_status_fetcher_.get()));
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700459 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
460 ((base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
461 .planning_spline_idx == spline_handle_ &&
462 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
463 .planning_state == 3) ||
464 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
465 .current_spline_idx == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700466 return true;
467 }
468 return false;
469}
470
471bool BaseAutonomousActor::SplineHandle::WaitForPlan() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700472 ::aos::time::PhasedLoop phased_loop(
473 ::std::chrono::milliseconds(5),
474 base_autonomous_actor_->event_loop()->monotonic_now(),
475 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700476 while (true) {
477 if (base_autonomous_actor_->ShouldCancel()) {
478 return false;
479 }
480 phased_loop.SleepUntilNext();
481 if (IsPlanned()) {
482 return true;
483 }
484 }
485}
486
487void BaseAutonomousActor::SplineHandle::Start() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700488 auto drivetrain_message =
489 base_autonomous_actor_->drivetrain_goal_sender_.MakeMessage();
Austin Schuh6bcc2302019-03-23 22:28:06 -0700490 drivetrain_message->controller_type = 2;
491
Austin Schuhf257f3c2019-10-27 21:00:43 -0700492 AOS_LOG(INFO, "Starting spline\n");
Austin Schuh6bcc2302019-03-23 22:28:06 -0700493
494 drivetrain_message->spline_handle = spline_handle_;
495 base_autonomous_actor_->goal_spline_handle_ = spline_handle_;
496
Austin Schuhf257f3c2019-10-27 21:00:43 -0700497 AOS_LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700498
499 drivetrain_message.Send();
500}
501
502bool BaseAutonomousActor::SplineHandle::IsDone() {
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700503 base_autonomous_actor_->drivetrain_status_fetcher_.Fetch();
Austin Schuhf257f3c2019-10-27 21:00:43 -0700504 AOS_LOG_STRUCT(INFO, "dts",
505 *(base_autonomous_actor_->drivetrain_status_fetcher_.get()));
Austin Schuh6bcc2302019-03-23 22:28:06 -0700506
James Kuszmaulc73bb222019-04-07 12:15:35 -0700507 // We check that the spline we are waiting on is neither currently planning
James Kuszmaul29e417d2019-04-13 10:03:35 -0700508 // nor executing (we check is_executed because it is possible to receive
509 // status messages with is_executing false before the execution has started).
510 // We check for planning so that the user can go straight from starting the
511 // planner to executing without a WaitForPlan in between.
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700512 if (base_autonomous_actor_->drivetrain_status_fetcher_.get() &&
513 ((!base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
514 .is_executed &&
515 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
516 .current_spline_idx == spline_handle_) ||
517 base_autonomous_actor_->drivetrain_status_fetcher_->trajectory_logging
518 .planning_spline_idx == spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700519 return false;
520 }
521 return true;
522}
523
524bool BaseAutonomousActor::SplineHandle::WaitForDone() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700525 ::aos::time::PhasedLoop phased_loop(
526 ::std::chrono::milliseconds(5),
527 base_autonomous_actor_->event_loop()->monotonic_now(),
528 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700529 while (true) {
530 if (base_autonomous_actor_->ShouldCancel()) {
531 return false;
532 }
533 phased_loop.SleepUntilNext();
534 if (IsDone()) {
535 return true;
536 }
537 }
538}
539
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000540} // namespace autonomous
541} // namespace frc971