blob: 4d3f3fc0c08b14a25f601c771038e92ba5ec2276 [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 ::frc971::control_loops::drivetrain_queue;
16using ::aos::monotonic_clock;
17namespace chrono = ::std::chrono;
18namespace this_thread = ::std::this_thread;
19
Brian Silvermanf83678c2017-03-11 14:02:26 -080020namespace frc971 {
21namespace autonomous {
Philipp Schrader4bd29b12017-02-22 04:42:27 +000022
23BaseAutonomousActor::BaseAutonomousActor(
Austin Schuh1bf8a212019-05-26 22:13:14 -070024 ::aos::EventLoop *event_loop,
Austin Schuhbcce26a2018-03-26 23:41:24 -070025 const control_loops::drivetrain::DrivetrainConfig<double> &dt_config)
Austin Schuh1bf8a212019-05-26 22:13:14 -070026 : aos::common::actions::ActorBase<AutonomousActionQueueGroup>(
27 event_loop, ".frc971.autonomous.autonomous_action"),
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>(
33 ".y2019.control_loops.drivetrain.target_selector_hint")) {}
Philipp Schrader4bd29b12017-02-22 04:42:27 +000034
35void BaseAutonomousActor::ResetDrivetrain() {
36 LOG(INFO, "resetting the drivetrain\n");
Austin Schuh0aae9242018-03-14 19:49:44 -070037 max_drivetrain_voltage_ = 12.0;
James Kuszmaulc73bb222019-04-07 12:15:35 -070038 goal_spline_handle_ = 0;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000039 drivetrain_queue.goal.MakeWithBuilder()
Austin Schuh78379ea2019-01-04 20:39:45 -080040 .controller_type(0)
Philipp Schrader4bd29b12017-02-22 04:42:27 +000041 .highgear(true)
Austin Schuh2b1fce02018-03-02 20:05:20 -080042 .wheel(0.0)
Philipp Schrader4bd29b12017-02-22 04:42:27 +000043 .throttle(0.0)
44 .left_goal(initial_drivetrain_.left)
Philipp Schrader4bd29b12017-02-22 04:42:27 +000045 .right_goal(initial_drivetrain_.right)
Austin Schuh0aae9242018-03-14 19:49:44 -070046 .max_ss_voltage(max_drivetrain_voltage_)
Philipp Schrader4bd29b12017-02-22 04:42:27 +000047 .Send();
48}
49
50void BaseAutonomousActor::InitializeEncoders() {
51 drivetrain_queue.status.FetchAnother();
52 initial_drivetrain_.left = drivetrain_queue.status->estimated_left_position;
53 initial_drivetrain_.right = drivetrain_queue.status->estimated_right_position;
54}
55
56void BaseAutonomousActor::StartDrive(double distance, double angle,
57 ProfileParameters linear,
58 ProfileParameters angular) {
59 LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
60 {
61 const double dangle = angle * dt_config_.robot_radius;
62 initial_drivetrain_.left += distance - dangle;
63 initial_drivetrain_.right += distance + dangle;
64 }
65
66 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
Austin Schuh78379ea2019-01-04 20:39:45 -080067 drivetrain_message->controller_type = 1;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000068 drivetrain_message->highgear = true;
Austin Schuh2b1fce02018-03-02 20:05:20 -080069 drivetrain_message->wheel = 0.0;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000070 drivetrain_message->throttle = 0.0;
71 drivetrain_message->left_goal = initial_drivetrain_.left;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000072 drivetrain_message->right_goal = initial_drivetrain_.right;
Austin Schuh0aae9242018-03-14 19:49:44 -070073 drivetrain_message->max_ss_voltage = max_drivetrain_voltage_;
Philipp Schrader4bd29b12017-02-22 04:42:27 +000074 drivetrain_message->linear = linear;
75 drivetrain_message->angular = angular;
76
Austin Schuh6bcc2302019-03-23 22:28:06 -070077 LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
Philipp Schrader4bd29b12017-02-22 04:42:27 +000078
79 drivetrain_message.Send();
80}
81
82void BaseAutonomousActor::WaitUntilDoneOrCanceled(
83 ::std::unique_ptr<aos::common::actions::Action> action) {
84 if (!action) {
85 LOG(ERROR, "No action, not waiting\n");
86 return;
87 }
88
89 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -070090 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +000091 ::std::chrono::milliseconds(5) / 2);
92 while (true) {
93 // Poll the running bit and see if we should cancel.
94 phased_loop.SleepUntilNext();
95 if (!action->Running() || ShouldCancel()) {
96 return;
97 }
98 }
99}
100
101bool BaseAutonomousActor::WaitForDriveDone() {
102 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700103 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000104 ::std::chrono::milliseconds(5) / 2);
105
106 while (true) {
107 if (ShouldCancel()) {
108 return false;
109 }
110 phased_loop.SleepUntilNext();
111 drivetrain_queue.status.FetchLatest();
112 if (IsDriveDone()) {
113 return true;
114 }
115 }
116}
117
118bool BaseAutonomousActor::IsDriveDone() {
Brian Silvermanf83678c2017-03-11 14:02:26 -0800119 static constexpr double kPositionTolerance = 0.02;
120 static constexpr double kVelocityTolerance = 0.10;
121 static constexpr double kProfileTolerance = 0.001;
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000122
123 if (drivetrain_queue.status.get()) {
124 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
125 initial_drivetrain_.left) < kProfileTolerance &&
126 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
127 initial_drivetrain_.right) < kProfileTolerance &&
128 ::std::abs(drivetrain_queue.status->estimated_left_position -
129 initial_drivetrain_.left) < kPositionTolerance &&
130 ::std::abs(drivetrain_queue.status->estimated_right_position -
131 initial_drivetrain_.right) < kPositionTolerance &&
132 ::std::abs(drivetrain_queue.status->estimated_left_velocity) <
133 kVelocityTolerance &&
134 ::std::abs(drivetrain_queue.status->estimated_right_velocity) <
135 kVelocityTolerance) {
136 LOG(INFO, "Finished drive\n");
137 return true;
138 }
139 }
140 return false;
141}
142
143bool BaseAutonomousActor::WaitForAboveAngle(double angle) {
144 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700145 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000146 ::std::chrono::milliseconds(5) / 2);
147 while (true) {
148 if (ShouldCancel()) {
149 return false;
150 }
151 phased_loop.SleepUntilNext();
152 drivetrain_queue.status.FetchLatest();
153 if (IsDriveDone()) {
154 return true;
155 }
156 if (drivetrain_queue.status.get()) {
157 if (drivetrain_queue.status->ground_angle > angle) {
158 return true;
159 }
160 }
161 }
162}
163
164bool BaseAutonomousActor::WaitForBelowAngle(double angle) {
165 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700166 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000167 ::std::chrono::milliseconds(5) / 2);
168 while (true) {
169 if (ShouldCancel()) {
170 return false;
171 }
172 phased_loop.SleepUntilNext();
173 drivetrain_queue.status.FetchLatest();
174 if (IsDriveDone()) {
175 return true;
176 }
177 if (drivetrain_queue.status.get()) {
178 if (drivetrain_queue.status->ground_angle < angle) {
179 return true;
180 }
181 }
182 }
183}
184
185bool BaseAutonomousActor::WaitForMaxBy(double angle) {
186 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700187 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000188 ::std::chrono::milliseconds(5) / 2);
189 double max_angle = -M_PI;
190 while (true) {
191 if (ShouldCancel()) {
192 return false;
193 }
194 phased_loop.SleepUntilNext();
195 drivetrain_queue.status.FetchLatest();
196 if (IsDriveDone()) {
197 return true;
198 }
199 if (drivetrain_queue.status.get()) {
200 if (drivetrain_queue.status->ground_angle > max_angle) {
201 max_angle = drivetrain_queue.status->ground_angle;
202 }
203 if (drivetrain_queue.status->ground_angle < max_angle - angle) {
204 return true;
205 }
206 }
207 }
208}
209
210bool BaseAutonomousActor::WaitForDriveNear(double distance, double angle) {
211 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700212 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000213 ::std::chrono::milliseconds(5) / 2);
214 constexpr double kPositionTolerance = 0.02;
215 constexpr double kProfileTolerance = 0.001;
216
Austin Schuhe6af9992018-07-08 15:59:14 -0700217 bool drive_has_been_close = false;
218 bool turn_has_been_close = false;
219 bool printed_first = false;
220
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000221 while (true) {
222 if (ShouldCancel()) {
223 return false;
224 }
225 phased_loop.SleepUntilNext();
226 drivetrain_queue.status.FetchLatest();
227 if (drivetrain_queue.status.get()) {
228 const double left_profile_error =
229 (initial_drivetrain_.left -
230 drivetrain_queue.status->profiled_left_position_goal);
231 const double right_profile_error =
232 (initial_drivetrain_.right -
233 drivetrain_queue.status->profiled_right_position_goal);
234
235 const double left_error =
236 (initial_drivetrain_.left -
237 drivetrain_queue.status->estimated_left_position);
238 const double right_error =
239 (initial_drivetrain_.right -
240 drivetrain_queue.status->estimated_right_position);
241
242 const double profile_distance_to_go =
243 (left_profile_error + right_profile_error) / 2.0;
244 const double profile_angle_to_go =
245 (right_profile_error - left_profile_error) /
246 (dt_config_.robot_radius * 2.0);
247
248 const double distance_to_go = (left_error + right_error) / 2.0;
249 const double angle_to_go =
250 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
251
Austin Schuhe6af9992018-07-08 15:59:14 -0700252 const bool drive_close =
253 ::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
254 ::std::abs(distance_to_go) < distance + kPositionTolerance;
255 const bool turn_close =
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000256 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
Austin Schuhe6af9992018-07-08 15:59:14 -0700257 ::std::abs(angle_to_go) < angle + kPositionTolerance;
258
259 drive_has_been_close |= drive_close;
260 turn_has_been_close |= turn_close;
261 if (drive_has_been_close && !turn_has_been_close && !printed_first) {
262 LOG(INFO, "Drive finished first\n");
263 printed_first = true;
264 } else if (!drive_has_been_close && turn_has_been_close &&
265 !printed_first) {
266 LOG(INFO, "Turn finished first\n");
267 printed_first = true;
268 }
269
270 if (drive_close && turn_close) {
271 LOG(INFO, "Closer than %f < %f distance, %f < %f angle\n",
272 distance_to_go, distance, angle_to_go, angle);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000273 return true;
274 }
275 }
276 }
277}
278
Austin Schuh0aae9242018-03-14 19:49:44 -0700279bool BaseAutonomousActor::WaitForDriveProfileNear(double tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000280 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700281 event_loop()->monotonic_now(),
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000282 ::std::chrono::milliseconds(5) / 2);
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000283 while (true) {
284 if (ShouldCancel()) {
285 return false;
286 }
287 phased_loop.SleepUntilNext();
288 drivetrain_queue.status.FetchLatest();
Austin Schuh0aae9242018-03-14 19:49:44 -0700289
290 const Eigen::Matrix<double, 7, 1> current_error =
291 (Eigen::Matrix<double, 7, 1>()
292 << initial_drivetrain_.left -
293 drivetrain_queue.status->profiled_left_position_goal,
294 0.0, initial_drivetrain_.right -
295 drivetrain_queue.status->profiled_right_position_goal,
296 0.0, 0.0, 0.0, 0.0)
297 .finished();
298 const Eigen::Matrix<double, 2, 1> linear_error =
299 dt_config_.LeftRightToLinear(current_error);
300
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000301 if (drivetrain_queue.status.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700302 if (::std::abs(linear_error(0)) < tolerance) {
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000303 LOG(INFO, "Finished drive\n");
304 return true;
305 }
306 }
307 }
308}
309
Austin Schuh0aae9242018-03-14 19:49:44 -0700310bool BaseAutonomousActor::WaitForDriveProfileDone() {
311 constexpr double kProfileTolerance = 0.001;
312 return WaitForDriveProfileNear(kProfileTolerance);
313}
314
315bool BaseAutonomousActor::WaitForTurnProfileNear(double tolerance) {
Austin Schuh546a0382017-04-16 19:10:18 -0700316 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
Austin Schuhd32b3622019-06-23 18:49:06 -0700317 event_loop()->monotonic_now(),
Austin Schuh546a0382017-04-16 19:10:18 -0700318 ::std::chrono::milliseconds(5) / 2);
Austin Schuh546a0382017-04-16 19:10:18 -0700319 while (true) {
320 if (ShouldCancel()) {
321 return false;
322 }
323 phased_loop.SleepUntilNext();
324 drivetrain_queue.status.FetchLatest();
Austin Schuh0aae9242018-03-14 19:49:44 -0700325
326 const Eigen::Matrix<double, 7, 1> current_error =
327 (Eigen::Matrix<double, 7, 1>()
328 << initial_drivetrain_.left -
329 drivetrain_queue.status->profiled_left_position_goal,
330 0.0, initial_drivetrain_.right -
331 drivetrain_queue.status->profiled_right_position_goal,
332 0.0, 0.0, 0.0, 0.0)
333 .finished();
334 const Eigen::Matrix<double, 2, 1> angular_error =
335 dt_config_.LeftRightToAngular(current_error);
336
Austin Schuh546a0382017-04-16 19:10:18 -0700337 if (drivetrain_queue.status.get()) {
Austin Schuh0aae9242018-03-14 19:49:44 -0700338 if (::std::abs(angular_error(0)) < tolerance) {
339 LOG(INFO, "Finished turn\n");
Austin Schuh546a0382017-04-16 19:10:18 -0700340 return true;
341 }
342 }
343 }
344}
345
Austin Schuh0aae9242018-03-14 19:49:44 -0700346bool BaseAutonomousActor::WaitForTurnProfileDone() {
347 constexpr double kProfileTolerance = 0.001;
348 return WaitForTurnProfileNear(kProfileTolerance);
349}
350
Austin Schuh546a0382017-04-16 19:10:18 -0700351double BaseAutonomousActor::DriveDistanceLeft() {
352 using ::frc971::control_loops::drivetrain_queue;
353 drivetrain_queue.status.FetchLatest();
354 if (drivetrain_queue.status.get()) {
355 const double left_error =
356 (initial_drivetrain_.left -
357 drivetrain_queue.status->estimated_left_position);
358 const double right_error =
359 (initial_drivetrain_.right -
360 drivetrain_queue.status->estimated_right_position);
361
362 return (left_error + right_error) / 2.0;
363 } else {
364 return 0;
365 }
366}
367
James Kuszmaul838040b2019-04-13 15:51:02 -0700368bool BaseAutonomousActor::SplineHandle::SplineDistanceRemaining(
369 double distance) {
370 drivetrain_queue.status.FetchLatest();
371 if (drivetrain_queue.status.get()) {
372 return drivetrain_queue.status->trajectory_logging.is_executing &&
373 drivetrain_queue.status->trajectory_logging.distance_remaining <
374 distance;
375 }
376 return false;
377}
378bool BaseAutonomousActor::SplineHandle::WaitForSplineDistanceRemaining(
379 double distance) {
Austin Schuhd32b3622019-06-23 18:49:06 -0700380 ::aos::time::PhasedLoop phased_loop(
381 ::std::chrono::milliseconds(5),
382 base_autonomous_actor_->event_loop()->monotonic_now(),
383 ::std::chrono::milliseconds(5) / 2);
James Kuszmaul838040b2019-04-13 15:51:02 -0700384 while (true) {
385 if (base_autonomous_actor_->ShouldCancel()) {
386 return false;
387 }
388 phased_loop.SleepUntilNext();
389 if (SplineDistanceRemaining(distance)) {
390 return true;
391 }
392 }
393}
394
James Kuszmaul8bb5df22019-05-01 21:40:08 -0500395void BaseAutonomousActor::LineFollowAtVelocity(double velocity, int hint) {
James Kuszmaul838040b2019-04-13 15:51:02 -0700396 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
397 drivetrain_message->controller_type = 3;
398 // TODO(james): Currently the 4.0 is copied from the
399 // line_follow_drivetrain.cc, but it is somewhat year-specific, so we should
400 // factor it out in some way.
401 drivetrain_message->throttle = velocity / 4.0;
402 drivetrain_message.Send();
Austin Schuhc087b102019-05-12 15:33:12 -0700403 auto target_hint = target_selector_hint_sender_.MakeMessage();
James Kuszmaul8bb5df22019-05-01 21:40:08 -0500404 target_hint->suggested_target = hint;
405 target_hint.Send();
James Kuszmaul838040b2019-04-13 15:51:02 -0700406}
407
Austin Schuh6bcc2302019-03-23 22:28:06 -0700408BaseAutonomousActor::SplineHandle BaseAutonomousActor::PlanSpline(
James Kuszmaulc73bb222019-04-07 12:15:35 -0700409 const ::frc971::MultiSpline &spline, SplineDirection direction) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700410 LOG(INFO, "Planning spline\n");
411
412 int32_t spline_handle = (++spline_handle_) | ((getpid() & 0xFFFF) << 15);
413
414 drivetrain_queue.goal.FetchLatest();
415
416 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
James Kuszmaulc864bcf2019-05-01 20:17:34 -0700417
418 int controller_type = 2;
419 if (drivetrain_queue.goal.get()) {
420 controller_type = drivetrain_queue.goal->controller_type;
421 drivetrain_message->throttle = drivetrain_queue.goal->throttle;
422 }
423 drivetrain_message->controller_type = controller_type;
Austin Schuh6bcc2302019-03-23 22:28:06 -0700424
425 drivetrain_message->spline = spline;
426 drivetrain_message->spline.spline_idx = spline_handle;
427 drivetrain_message->spline_handle = goal_spline_handle_;
James Kuszmaul29e417d2019-04-13 10:03:35 -0700428 drivetrain_message->spline.drive_spline_backwards =
James Kuszmaulc73bb222019-04-07 12:15:35 -0700429 direction == SplineDirection::kBackward;
Austin Schuh6bcc2302019-03-23 22:28:06 -0700430
431 LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
432
433 drivetrain_message.Send();
434
435 return BaseAutonomousActor::SplineHandle(spline_handle, this);
436}
437
438bool BaseAutonomousActor::SplineHandle::IsPlanned() {
439 drivetrain_queue.status.FetchLatest();
Austin Schuhb5b79a52019-05-08 20:32:07 -0700440 LOG_STRUCT(DEBUG, "dts", *drivetrain_queue.status.get());
Austin Schuh6bcc2302019-03-23 22:28:06 -0700441 if (drivetrain_queue.status.get() &&
442 ((drivetrain_queue.status->trajectory_logging.planning_spline_idx ==
443 spline_handle_ &&
444 drivetrain_queue.status->trajectory_logging.planning_state == 3) ||
445 drivetrain_queue.status->trajectory_logging.current_spline_idx ==
446 spline_handle_)) {
447 return true;
448 }
449 return false;
450}
451
452bool BaseAutonomousActor::SplineHandle::WaitForPlan() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700453 ::aos::time::PhasedLoop phased_loop(
454 ::std::chrono::milliseconds(5),
455 base_autonomous_actor_->event_loop()->monotonic_now(),
456 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700457 while (true) {
458 if (base_autonomous_actor_->ShouldCancel()) {
459 return false;
460 }
461 phased_loop.SleepUntilNext();
462 if (IsPlanned()) {
463 return true;
464 }
465 }
466}
467
468void BaseAutonomousActor::SplineHandle::Start() {
469 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
470 drivetrain_message->controller_type = 2;
471
472 LOG(INFO, "Starting spline\n");
473
474 drivetrain_message->spline_handle = spline_handle_;
475 base_autonomous_actor_->goal_spline_handle_ = spline_handle_;
476
477 LOG_STRUCT(DEBUG, "dtg", *drivetrain_message);
478
479 drivetrain_message.Send();
480}
481
482bool BaseAutonomousActor::SplineHandle::IsDone() {
483 drivetrain_queue.status.FetchLatest();
484 LOG_STRUCT(INFO, "dts", *drivetrain_queue.status.get());
485
James Kuszmaulc73bb222019-04-07 12:15:35 -0700486 // We check that the spline we are waiting on is neither currently planning
James Kuszmaul29e417d2019-04-13 10:03:35 -0700487 // nor executing (we check is_executed because it is possible to receive
488 // status messages with is_executing false before the execution has started).
489 // We check for planning so that the user can go straight from starting the
490 // planner to executing without a WaitForPlan in between.
Austin Schuh6bcc2302019-03-23 22:28:06 -0700491 if (drivetrain_queue.status.get() &&
James Kuszmaul29e417d2019-04-13 10:03:35 -0700492 ((!drivetrain_queue.status->trajectory_logging.is_executed &&
493 drivetrain_queue.status->trajectory_logging.current_spline_idx ==
494 spline_handle_) ||
James Kuszmaulc73bb222019-04-07 12:15:35 -0700495 drivetrain_queue.status->trajectory_logging.planning_spline_idx ==
496 spline_handle_)) {
Austin Schuh6bcc2302019-03-23 22:28:06 -0700497 return false;
498 }
499 return true;
500}
501
502bool BaseAutonomousActor::SplineHandle::WaitForDone() {
Austin Schuhd32b3622019-06-23 18:49:06 -0700503 ::aos::time::PhasedLoop phased_loop(
504 ::std::chrono::milliseconds(5),
505 base_autonomous_actor_->event_loop()->monotonic_now(),
506 ::std::chrono::milliseconds(5) / 2);
Austin Schuh6bcc2302019-03-23 22:28:06 -0700507 while (true) {
508 if (base_autonomous_actor_->ShouldCancel()) {
509 return false;
510 }
511 phased_loop.SleepUntilNext();
512 if (IsDone()) {
513 return true;
514 }
515 }
516}
517
Philipp Schrader4bd29b12017-02-22 04:42:27 +0000518} // namespace autonomous
519} // namespace frc971