blob: 5194b2d0fca43a3ef9a78772c6413faee9c79f2e [file] [log] [blame]
Comran Morshede68e3732016-03-12 14:12:11 +00001#include "y2016/actors/autonomous_actor.h"
2
3#include <inttypes.h>
4
Austin Schuh8aec1ed2016-05-01 13:29:20 -07005#include <chrono>
Comran Morshedb134e772016-03-16 21:05:05 +00006#include <cmath>
7
Comran Morshede68e3732016-03-12 14:12:11 +00008#include "aos/common/util/phased_loop.h"
9#include "aos/common/logging/logging.h"
Comran Morshed435f1112016-03-12 14:20:45 +000010
11#include "frc971/control_loops/drivetrain/drivetrain.q.h"
12#include "y2016/control_loops/drivetrain/drivetrain_base.h"
Austin Schuhf59b8ee2016-03-19 21:31:36 -070013#include "y2016/control_loops/shooter/shooter.q.h"
Comran Morshedb134e772016-03-16 21:05:05 +000014#include "y2016/control_loops/superstructure/superstructure.q.h"
15#include "y2016/actors/autonomous_action.q.h"
Austin Schuh23b21802016-04-03 21:18:56 -070016#include "y2016/queues/ball_detector.q.h"
Austin Schuhf59b8ee2016-03-19 21:31:36 -070017#include "y2016/vision/vision.q.h"
Comran Morshede68e3732016-03-12 14:12:11 +000018
19namespace y2016 {
20namespace actors {
Comran Morshed435f1112016-03-12 14:20:45 +000021using ::frc971::control_loops::drivetrain_queue;
Austin Schuhf2a50ba2016-12-24 16:16:26 -080022using ::aos::monotonic_clock;
23namespace chrono = ::std::chrono;
24namespace this_thread = ::std::this_thread;
Comran Morshed435f1112016-03-12 14:20:45 +000025
26namespace {
Austin Schuhf59b8ee2016-03-19 21:31:36 -070027const ProfileParameters kSlowDrive = {0.8, 2.5};
28const ProfileParameters kLowBarDrive = {1.3, 2.5};
29const ProfileParameters kMoatDrive = {1.2, 3.5};
30const ProfileParameters kRealignDrive = {2.0, 2.5};
31const ProfileParameters kRockWallDrive = {0.8, 2.5};
Comran Morshed435f1112016-03-12 14:20:45 +000032const ProfileParameters kFastDrive = {3.0, 2.5};
33
Austin Schuhf59b8ee2016-03-19 21:31:36 -070034const ProfileParameters kSlowTurn = {0.8, 3.0};
Comran Morshed435f1112016-03-12 14:20:45 +000035const ProfileParameters kFastTurn = {3.0, 10.0};
Austin Schuhe4ec49c2016-04-24 19:07:15 -070036const ProfileParameters kStealTurn = {4.0, 15.0};
Austin Schuh23b21802016-04-03 21:18:56 -070037const ProfileParameters kSwerveTurn = {2.0, 7.0};
38const ProfileParameters kFinishTurn = {2.0, 5.0};
39
40const ProfileParameters kTwoBallLowDrive = {1.7, 3.5};
41const ProfileParameters kTwoBallFastDrive = {3.0, 1.5};
42const ProfileParameters kTwoBallReturnDrive = {3.0, 1.9};
Austin Schuhe4ec49c2016-04-24 19:07:15 -070043const ProfileParameters kTwoBallReturnSlow = {3.0, 2.5};
Austin Schuh23b21802016-04-03 21:18:56 -070044const ProfileParameters kTwoBallBallPickup = {2.0, 1.75};
Austin Schuhe4ec49c2016-04-24 19:07:15 -070045const ProfileParameters kTwoBallBallPickupAccel = {2.0, 2.5};
Austin Schuhf2a50ba2016-12-24 16:16:26 -080046
47double DoubleSeconds(monotonic_clock::duration duration) {
48 return ::std::chrono::duration_cast<::std::chrono::duration<double>>(duration)
49 .count();
50}
Comran Morshed435f1112016-03-12 14:20:45 +000051} // namespace
Comran Morshede68e3732016-03-12 14:12:11 +000052
53AutonomousActor::AutonomousActor(actors::AutonomousActionQueueGroup *s)
Comran Morshed435f1112016-03-12 14:20:45 +000054 : aos::common::actions::ActorBase<actors::AutonomousActionQueueGroup>(s),
Comran Morshedb134e772016-03-16 21:05:05 +000055 dt_config_(control_loops::drivetrain::GetDrivetrainConfig()),
56 initial_drivetrain_({0.0, 0.0}) {}
Comran Morshed435f1112016-03-12 14:20:45 +000057
58void AutonomousActor::ResetDrivetrain() {
59 LOG(INFO, "resetting the drivetrain\n");
60 drivetrain_queue.goal.MakeWithBuilder()
61 .control_loop_driving(false)
62 .highgear(true)
63 .steering(0.0)
64 .throttle(0.0)
Comran Morshedb134e772016-03-16 21:05:05 +000065 .left_goal(initial_drivetrain_.left)
Comran Morshed435f1112016-03-12 14:20:45 +000066 .left_velocity_goal(0)
Comran Morshedb134e772016-03-16 21:05:05 +000067 .right_goal(initial_drivetrain_.right)
Comran Morshed435f1112016-03-12 14:20:45 +000068 .right_velocity_goal(0)
69 .Send();
70}
71
72void AutonomousActor::StartDrive(double distance, double angle,
73 ProfileParameters linear,
74 ProfileParameters angular) {
75 {
Austin Schuh23b21802016-04-03 21:18:56 -070076 LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Comran Morshed435f1112016-03-12 14:20:45 +000077 {
78 const double dangle = angle * dt_config_.robot_radius;
Comran Morshedb134e772016-03-16 21:05:05 +000079 initial_drivetrain_.left += distance - dangle;
80 initial_drivetrain_.right += distance + dangle;
Comran Morshed435f1112016-03-12 14:20:45 +000081 }
82
Comran Morshedb134e772016-03-16 21:05:05 +000083 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
Comran Morshed435f1112016-03-12 14:20:45 +000084 drivetrain_message->control_loop_driving = true;
85 drivetrain_message->highgear = true;
86 drivetrain_message->steering = 0.0;
87 drivetrain_message->throttle = 0.0;
Comran Morshedb134e772016-03-16 21:05:05 +000088 drivetrain_message->left_goal = initial_drivetrain_.left;
Comran Morshed435f1112016-03-12 14:20:45 +000089 drivetrain_message->left_velocity_goal = 0;
Comran Morshedb134e772016-03-16 21:05:05 +000090 drivetrain_message->right_goal = initial_drivetrain_.right;
Comran Morshed435f1112016-03-12 14:20:45 +000091 drivetrain_message->right_velocity_goal = 0;
92 drivetrain_message->linear = linear;
93 drivetrain_message->angular = angular;
94
95 LOG_STRUCT(DEBUG, "drivetrain_goal", *drivetrain_message);
96
97 drivetrain_message.Send();
98 }
99}
100
101void AutonomousActor::InitializeEncoders() {
102 drivetrain_queue.status.FetchAnother();
Comran Morshedb134e772016-03-16 21:05:05 +0000103 initial_drivetrain_.left = drivetrain_queue.status->estimated_left_position;
104 initial_drivetrain_.right = drivetrain_queue.status->estimated_right_position;
Comran Morshed435f1112016-03-12 14:20:45 +0000105}
106
107void AutonomousActor::WaitUntilDoneOrCanceled(
108 ::std::unique_ptr<aos::common::actions::Action> action) {
109 if (!action) {
110 LOG(ERROR, "No action, not waiting\n");
111 return;
112 }
113
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700114 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
115 ::std::chrono::milliseconds(5) / 2);
Comran Morshed435f1112016-03-12 14:20:45 +0000116 while (true) {
117 // Poll the running bit and see if we should cancel.
118 phased_loop.SleepUntilNext();
119 if (!action->Running() || ShouldCancel()) {
120 return;
121 }
122 }
123}
124
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700125constexpr double kDoNotTurnCare = 2.0;
126
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700127bool AutonomousActor::WaitForDriveNear(double distance, double angle) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700128 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
129 ::std::chrono::milliseconds(5) / 2);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700130 constexpr double kPositionTolerance = 0.02;
131 constexpr double kProfileTolerance = 0.001;
132
133 while (true) {
134 if (ShouldCancel()) {
135 return false;
136 }
137 phased_loop.SleepUntilNext();
138 drivetrain_queue.status.FetchLatest();
139 if (drivetrain_queue.status.get()) {
140 const double left_profile_error =
141 (initial_drivetrain_.left -
142 drivetrain_queue.status->profiled_left_position_goal);
143 const double right_profile_error =
144 (initial_drivetrain_.right -
145 drivetrain_queue.status->profiled_right_position_goal);
146
147 const double left_error =
148 (initial_drivetrain_.left -
149 drivetrain_queue.status->estimated_left_position);
150 const double right_error =
151 (initial_drivetrain_.right -
152 drivetrain_queue.status->estimated_right_position);
153
154 const double profile_distance_to_go =
155 (left_profile_error + right_profile_error) / 2.0;
156 const double profile_angle_to_go =
157 (right_profile_error - left_profile_error) /
158 (dt_config_.robot_radius * 2.0);
159
160 const double distance_to_go = (left_error + right_error) / 2.0;
161 const double angle_to_go =
162 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
163
164 if (::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
165 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
166 ::std::abs(distance_to_go) < distance + kPositionTolerance &&
167 ::std::abs(angle_to_go) < angle + kPositionTolerance) {
168 LOG(INFO, "Closer than %f distance, %f angle\n", distance, angle);
169 return true;
170 }
171 }
172 }
173}
174
Austin Schuh23b21802016-04-03 21:18:56 -0700175bool AutonomousActor::WaitForDriveProfileDone() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700176 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
177 ::std::chrono::milliseconds(5) / 2);
Austin Schuh23b21802016-04-03 21:18:56 -0700178 constexpr double kProfileTolerance = 0.001;
179
180 while (true) {
181 if (ShouldCancel()) {
182 return false;
183 }
184 phased_loop.SleepUntilNext();
185 drivetrain_queue.status.FetchLatest();
186 if (drivetrain_queue.status.get()) {
187 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
188 initial_drivetrain_.left) < kProfileTolerance &&
189 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
190 initial_drivetrain_.right) < kProfileTolerance) {
191 LOG(INFO, "Finished drive\n");
192 return true;
193 }
194 }
195 }
196}
197
Austin Schuh3e4a5272016-04-20 20:11:00 -0700198bool AutonomousActor::WaitForMaxBy(double angle) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700199 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
200 ::std::chrono::milliseconds(5) / 2);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700201 double max_angle = -M_PI;
202 while (true) {
203 if (ShouldCancel()) {
204 return false;
205 }
206 phased_loop.SleepUntilNext();
207 drivetrain_queue.status.FetchLatest();
208 if (IsDriveDone()) {
209 return true;
210 }
211 if (drivetrain_queue.status.get()) {
212 if (drivetrain_queue.status->ground_angle > max_angle) {
213 max_angle = drivetrain_queue.status->ground_angle;
214 }
215 if (drivetrain_queue.status->ground_angle < max_angle - angle) {
216 return true;
217 }
218 }
219 }
220}
221
222bool AutonomousActor::WaitForAboveAngle(double angle) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700223 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
224 ::std::chrono::milliseconds(5) / 2);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700225 while (true) {
226 if (ShouldCancel()) {
227 return false;
228 }
229 phased_loop.SleepUntilNext();
230 drivetrain_queue.status.FetchLatest();
231 if (IsDriveDone()) {
232 return true;
233 }
234 if (drivetrain_queue.status.get()) {
235 if (drivetrain_queue.status->ground_angle > angle) {
236 return true;
237 }
238 }
239 }
240}
241
242bool AutonomousActor::WaitForBelowAngle(double angle) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700243 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
244 ::std::chrono::milliseconds(5) / 2);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700245 while (true) {
246 if (ShouldCancel()) {
247 return false;
248 }
249 phased_loop.SleepUntilNext();
250 drivetrain_queue.status.FetchLatest();
251 if (IsDriveDone()) {
252 return true;
253 }
254 if (drivetrain_queue.status.get()) {
255 if (drivetrain_queue.status->ground_angle < angle) {
256 return true;
257 }
258 }
259 }
260}
261
262bool AutonomousActor::IsDriveDone() {
Comran Morshed435f1112016-03-12 14:20:45 +0000263 constexpr double kPositionTolerance = 0.02;
264 constexpr double kVelocityTolerance = 0.10;
265 constexpr double kProfileTolerance = 0.001;
266
Austin Schuh3e4a5272016-04-20 20:11:00 -0700267 if (drivetrain_queue.status.get()) {
268 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
269 initial_drivetrain_.left) < kProfileTolerance &&
270 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
271 initial_drivetrain_.right) < kProfileTolerance &&
272 ::std::abs(drivetrain_queue.status->estimated_left_position -
273 initial_drivetrain_.left) < kPositionTolerance &&
274 ::std::abs(drivetrain_queue.status->estimated_right_position -
275 initial_drivetrain_.right) < kPositionTolerance &&
276 ::std::abs(drivetrain_queue.status->estimated_left_velocity) <
277 kVelocityTolerance &&
278 ::std::abs(drivetrain_queue.status->estimated_right_velocity) <
279 kVelocityTolerance) {
280 LOG(INFO, "Finished drive\n");
281 return true;
282 }
283 }
284 return false;
285}
286
287bool AutonomousActor::WaitForDriveDone() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700288 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
289 ::std::chrono::milliseconds(5) / 2);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700290
Comran Morshed435f1112016-03-12 14:20:45 +0000291 while (true) {
292 if (ShouldCancel()) {
293 return false;
294 }
295 phased_loop.SleepUntilNext();
296 drivetrain_queue.status.FetchLatest();
Austin Schuh3e4a5272016-04-20 20:11:00 -0700297 if (IsDriveDone()) {
298 return true;
Comran Morshed435f1112016-03-12 14:20:45 +0000299 }
300 }
301}
Comran Morshede68e3732016-03-12 14:12:11 +0000302
Comran Morshedb134e772016-03-16 21:05:05 +0000303void AutonomousActor::MoveSuperstructure(
304 double intake, double shoulder, double wrist,
305 const ProfileParameters intake_params,
306 const ProfileParameters shoulder_params,
Austin Schuh23b21802016-04-03 21:18:56 -0700307 const ProfileParameters wrist_params, bool traverse_up,
308 double roller_power) {
Comran Morshedb134e772016-03-16 21:05:05 +0000309 superstructure_goal_ = {intake, shoulder, wrist};
310
311 auto new_superstructure_goal =
312 ::y2016::control_loops::superstructure_queue.goal.MakeMessage();
313
314 new_superstructure_goal->angle_intake = intake;
315 new_superstructure_goal->angle_shoulder = shoulder;
316 new_superstructure_goal->angle_wrist = wrist;
317
318 new_superstructure_goal->max_angular_velocity_intake =
319 intake_params.max_velocity;
320 new_superstructure_goal->max_angular_velocity_shoulder =
321 shoulder_params.max_velocity;
322 new_superstructure_goal->max_angular_velocity_wrist =
323 wrist_params.max_velocity;
324
325 new_superstructure_goal->max_angular_acceleration_intake =
326 intake_params.max_acceleration;
327 new_superstructure_goal->max_angular_acceleration_shoulder =
328 shoulder_params.max_acceleration;
329 new_superstructure_goal->max_angular_acceleration_wrist =
330 wrist_params.max_acceleration;
331
Austin Schuh23b21802016-04-03 21:18:56 -0700332 new_superstructure_goal->voltage_top_rollers = roller_power;
333 new_superstructure_goal->voltage_bottom_rollers = roller_power;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700334
335 new_superstructure_goal->traverse_unlatched = true;
336 new_superstructure_goal->traverse_down = !traverse_up;
Diana Vandenberg9cc9ab62016-04-20 21:27:47 -0700337 new_superstructure_goal->voltage_climber = 0.0;
338 new_superstructure_goal->unfold_climber = false;
Comran Morshedb134e772016-03-16 21:05:05 +0000339
340 if (!new_superstructure_goal.Send()) {
341 LOG(ERROR, "Sending superstructure goal failed.\n");
342 }
343}
344
Austin Schuh23b21802016-04-03 21:18:56 -0700345void AutonomousActor::OpenShooter() {
346 shooter_speed_ = 0.0;
347
348 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
349 .angular_velocity(shooter_speed_)
350 .clamp_open(true)
351 .push_to_shooter(false)
352 .force_lights_on(false)
353 .Send()) {
354 LOG(ERROR, "Sending shooter goal failed.\n");
355 }
356}
357
358void AutonomousActor::CloseShooter() {
359 shooter_speed_ = 0.0;
360
361 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
362 .angular_velocity(shooter_speed_)
363 .clamp_open(false)
364 .push_to_shooter(false)
365 .force_lights_on(false)
366 .Send()) {
367 LOG(ERROR, "Sending shooter goal failed.\n");
368 }
369}
370
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700371void AutonomousActor::SetShooterSpeed(double speed) {
372 shooter_speed_ = speed;
373
374 // In auto, we want to have the lights on whenever possible since we have no
375 // hope of a human aligning the robot.
376 bool force_lights_on = shooter_speed_ > 1.0;
377
378 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
379 .angular_velocity(shooter_speed_)
380 .clamp_open(false)
381 .push_to_shooter(false)
382 .force_lights_on(force_lights_on)
383 .Send()) {
384 LOG(ERROR, "Sending shooter goal failed.\n");
385 }
386}
387
388void AutonomousActor::Shoot() {
389 uint32_t initial_shots = 0;
390
391 control_loops::shooter::shooter_queue.status.FetchLatest();
392 if (control_loops::shooter::shooter_queue.status.get()) {
393 initial_shots = control_loops::shooter::shooter_queue.status->shots;
394 }
395
396 // In auto, we want to have the lights on whenever possible since we have no
397 // hope of a human aligning the robot.
398 bool force_lights_on = shooter_speed_ > 1.0;
399
400 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
401 .angular_velocity(shooter_speed_)
402 .clamp_open(false)
403 .push_to_shooter(true)
404 .force_lights_on(force_lights_on)
405 .Send()) {
406 LOG(ERROR, "Sending shooter goal failed.\n");
407 }
408
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700409 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
410 ::std::chrono::milliseconds(5) / 2);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700411 while (true) {
412 if (ShouldCancel()) return;
413
414 // Wait for the shot count to change so we know when the shot is complete.
415 control_loops::shooter::shooter_queue.status.FetchLatest();
416 if (control_loops::shooter::shooter_queue.status.get()) {
417 if (initial_shots < control_loops::shooter::shooter_queue.status->shots) {
418 return;
419 }
420 }
421 phased_loop.SleepUntilNext();
422 }
423}
424
425void AutonomousActor::WaitForShooterSpeed() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700426 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
427 ::std::chrono::milliseconds(5) / 2);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700428 while (true) {
429 if (ShouldCancel()) return;
430
431 control_loops::shooter::shooter_queue.status.FetchLatest();
432 if (control_loops::shooter::shooter_queue.status.get()) {
433 if (control_loops::shooter::shooter_queue.status->left.ready &&
434 control_loops::shooter::shooter_queue.status->right.ready) {
435 return;
436 }
437 }
438 phased_loop.SleepUntilNext();
439 }
440}
441
442void AutonomousActor::AlignWithVisionGoal() {
443 actors::VisionAlignActionParams params;
444 vision_action_ = ::std::move(actors::MakeVisionAlignAction(params));
445 vision_action_->Start();
446}
447
Austin Schuh23b21802016-04-03 21:18:56 -0700448void AutonomousActor::WaitForAlignedWithVision(
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800449 chrono::nanoseconds align_duration) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700450 bool vision_valid = false;
451 double last_angle = 0.0;
452 int ready_to_fire = 0;
453
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700454 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
455 ::std::chrono::milliseconds(5) / 2);
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800456 monotonic_clock::time_point end_time =
457 monotonic_clock::now() + align_duration;
458 while (end_time > monotonic_clock::now()) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700459 if (ShouldCancel()) break;
460
461 ::y2016::vision::vision_status.FetchLatest();
462 if (::y2016::vision::vision_status.get()) {
463 vision_valid = (::y2016::vision::vision_status->left_image_valid &&
464 ::y2016::vision::vision_status->right_image_valid);
465 last_angle = ::y2016::vision::vision_status->horizontal_angle;
466 }
467
468 drivetrain_queue.status.FetchLatest();
469 drivetrain_queue.goal.FetchLatest();
470
471 if (drivetrain_queue.status.get() && drivetrain_queue.goal.get()) {
472 const double left_goal = drivetrain_queue.goal->left_goal;
473 const double right_goal = drivetrain_queue.goal->right_goal;
474 const double left_current =
475 drivetrain_queue.status->estimated_left_position;
476 const double right_current =
477 drivetrain_queue.status->estimated_right_position;
478 const double left_velocity =
479 drivetrain_queue.status->estimated_left_velocity;
480 const double right_velocity =
481 drivetrain_queue.status->estimated_right_velocity;
482
483 if (vision_valid && ::std::abs(last_angle) < 0.02 &&
484 ::std::abs((left_goal - right_goal) -
485 (left_current - right_current)) /
486 dt_config_.robot_radius / 2.0 <
487 0.02 &&
488 ::std::abs(left_velocity - right_velocity) < 0.01) {
489 ++ready_to_fire;
490 } else {
491 ready_to_fire = 0;
492 }
Austin Schuh3e4a5272016-04-20 20:11:00 -0700493 if (ready_to_fire > 15) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700494 break;
Austin Schuh23b21802016-04-03 21:18:56 -0700495 LOG(INFO, "Vision align success!\n");
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700496 }
497 }
498 phased_loop.SleepUntilNext();
499 }
500
501 vision_action_->Cancel();
502 WaitUntilDoneOrCanceled(::std::move(vision_action_));
Austin Schuh23b21802016-04-03 21:18:56 -0700503 LOG(INFO, "Done waiting for vision\n");
504}
505
506bool AutonomousActor::IntakeDone() {
507 control_loops::superstructure_queue.status.FetchAnother();
508
509 constexpr double kProfileError = 1e-5;
510 constexpr double kEpsilon = 0.15;
511
512 if (control_loops::superstructure_queue.status->state < 12 ||
513 control_loops::superstructure_queue.status->state == 16) {
514 LOG(ERROR, "Superstructure no longer running, aborting action\n");
515 return true;
516 }
517
518 if (::std::abs(control_loops::superstructure_queue.status->intake.goal_angle -
519 superstructure_goal_.intake) < kProfileError &&
520 ::std::abs(control_loops::superstructure_queue.status->intake
521 .goal_angular_velocity) < kProfileError) {
522 LOG(DEBUG, "Profile done.\n");
523 if (::std::abs(control_loops::superstructure_queue.status->intake.angle -
524 superstructure_goal_.intake) < kEpsilon &&
525 ::std::abs(control_loops::superstructure_queue.status->intake
526 .angular_velocity) < kEpsilon) {
527 LOG(INFO, "Near goal, done.\n");
528 return true;
529 }
530 }
531 return false;
532}
533
534bool AutonomousActor::SuperstructureProfileDone() {
535 constexpr double kProfileError = 1e-5;
536 return ::std::abs(
537 control_loops::superstructure_queue.status->intake.goal_angle -
538 superstructure_goal_.intake) < kProfileError &&
539 ::std::abs(
540 control_loops::superstructure_queue.status->shoulder.goal_angle -
541 superstructure_goal_.shoulder) < kProfileError &&
542 ::std::abs(
543 control_loops::superstructure_queue.status->wrist.goal_angle -
544 superstructure_goal_.wrist) < kProfileError &&
545 ::std::abs(control_loops::superstructure_queue.status->intake
546 .goal_angular_velocity) < kProfileError &&
547 ::std::abs(control_loops::superstructure_queue.status->shoulder
548 .goal_angular_velocity) < kProfileError &&
549 ::std::abs(control_loops::superstructure_queue.status->wrist
550 .goal_angular_velocity) < kProfileError;
551}
552
553bool AutonomousActor::SuperstructureDone() {
554 control_loops::superstructure_queue.status.FetchAnother();
555
556 constexpr double kEpsilon = 0.03;
557
558 if (control_loops::superstructure_queue.status->state < 12 ||
559 control_loops::superstructure_queue.status->state == 16) {
560 LOG(ERROR, "Superstructure no longer running, aborting action\n");
561 return true;
562 }
563
564 if (SuperstructureProfileDone()) {
565 LOG(DEBUG, "Profile done.\n");
566 if (::std::abs(control_loops::superstructure_queue.status->intake.angle -
567 superstructure_goal_.intake) < (kEpsilon + 0.1) &&
568 ::std::abs(control_loops::superstructure_queue.status->shoulder.angle -
569 superstructure_goal_.shoulder) < (kEpsilon + 0.05) &&
570 ::std::abs(control_loops::superstructure_queue.status->wrist.angle -
571 superstructure_goal_.wrist) < (kEpsilon + 0.01) &&
572 ::std::abs(control_loops::superstructure_queue.status->intake
573 .angular_velocity) < (kEpsilon + 0.1) &&
574 ::std::abs(control_loops::superstructure_queue.status->shoulder
575 .angular_velocity) < (kEpsilon + 0.10) &&
576 ::std::abs(control_loops::superstructure_queue.status->wrist
577 .angular_velocity) < (kEpsilon + 0.05)) {
578 LOG(INFO, "Near goal, done.\n");
579 return true;
580 }
581 }
582 return false;
583}
584
585void AutonomousActor::WaitForIntake() {
586 while (true) {
587 if (ShouldCancel()) return;
588 if (IntakeDone()) return;
589 }
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700590}
591
Comran Morshedb134e772016-03-16 21:05:05 +0000592void AutonomousActor::WaitForSuperstructure() {
593 while (true) {
594 if (ShouldCancel()) return;
Austin Schuh23b21802016-04-03 21:18:56 -0700595 if (SuperstructureDone()) return;
596 }
597}
Comran Morshedb134e772016-03-16 21:05:05 +0000598
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700599void AutonomousActor::WaitForSuperstructureProfile() {
600 while (true) {
601 if (ShouldCancel()) return;
602 control_loops::superstructure_queue.status.FetchAnother();
603
604 if (control_loops::superstructure_queue.status->state < 12 ||
605 control_loops::superstructure_queue.status->state == 16) {
606 LOG(ERROR, "Superstructure no longer running, aborting action\n");
607 return;
608 }
609
610 if (SuperstructureProfileDone()) return;
611 }
612}
613
Austin Schuh23b21802016-04-03 21:18:56 -0700614void AutonomousActor::WaitForSuperstructureLow() {
615 while (true) {
616 if (ShouldCancel()) return;
617 control_loops::superstructure_queue.status.FetchAnother();
Comran Morshedb134e772016-03-16 21:05:05 +0000618
619 if (control_loops::superstructure_queue.status->state < 12 ||
620 control_loops::superstructure_queue.status->state == 16) {
621 LOG(ERROR, "Superstructure no longer running, aborting action\n");
622 return;
623 }
Austin Schuh23b21802016-04-03 21:18:56 -0700624 if (SuperstructureProfileDone()) return;
625 if (control_loops::superstructure_queue.status->shoulder.angle < 0.1) {
626 return;
Comran Morshedb134e772016-03-16 21:05:05 +0000627 }
628 }
629}
Austin Schuh23b21802016-04-03 21:18:56 -0700630void AutonomousActor::BackLongShotLowBarTwoBall() {
631 LOG(INFO, "Expanding for back long shot\n");
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700632 MoveSuperstructure(0.00, M_PI / 2.0 - 0.2, -0.55, {7.0, 40.0}, {4.0, 6.0},
Austin Schuh23b21802016-04-03 21:18:56 -0700633 {10.0, 25.0}, false, 0.0);
634}
635
636void AutonomousActor::BackLongShotTwoBall() {
637 LOG(INFO, "Expanding for back long shot\n");
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700638 MoveSuperstructure(0.00, M_PI / 2.0 - 0.2, -0.55, {7.0, 40.0}, {4.0, 6.0},
639 {10.0, 25.0}, false, 0.0);
640}
641
642void AutonomousActor::BackLongShotTwoBallFinish() {
643 LOG(INFO, "Expanding for back long shot\n");
Adam Snaidera16f1072016-10-04 11:01:05 -0700644 MoveSuperstructure(
645 0.00, M_PI / 2.0 - 0.2, -0.625 + 0.03, {7.0, 40.0},
646 {4.0, 6.0},
647 {10.0, 25.0}, false, 0.0);
Austin Schuh23b21802016-04-03 21:18:56 -0700648}
649
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700650void AutonomousActor::BackLongShot() {
651 LOG(INFO, "Expanding for back long shot\n");
Austin Schuh23b21802016-04-03 21:18:56 -0700652 MoveSuperstructure(0.80, M_PI / 2.0 - 0.2, -0.62, {7.0, 40.0}, {4.0, 6.0},
653 {10.0, 25.0}, false, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700654}
655
656void AutonomousActor::BackMiddleShot() {
657 LOG(INFO, "Expanding for back middle shot\n");
658 MoveSuperstructure(-0.05, M_PI / 2.0 - 0.2, -0.665, {7.0, 40.0}, {4.0, 10.0},
Austin Schuh23b21802016-04-03 21:18:56 -0700659 {10.0, 25.0}, false, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700660}
661
Austin Schuh3e4a5272016-04-20 20:11:00 -0700662void AutonomousActor::FrontLongShot() {
663 LOG(INFO, "Expanding for front long shot\n");
664 MoveSuperstructure(0.80, M_PI / 2.0 + 0.1, M_PI + 0.41 + 0.02, {7.0, 40.0},
665 {4.0, 6.0}, {10.0, 25.0}, false, 0.0);
666}
667
668void AutonomousActor::FrontMiddleShot() {
669 LOG(INFO, "Expanding for front middle shot\n");
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700670 MoveSuperstructure(-0.05, M_PI / 2.0 + 0.1, M_PI + 0.44, {7.0, 40.0},
Austin Schuh3e4a5272016-04-20 20:11:00 -0700671 {4.0, 10.0}, {10.0, 25.0}, true, 0.0);
672}
673
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700674void AutonomousActor::TuckArm(bool low_bar, bool traverse_down) {
675 MoveSuperstructure(low_bar ? -0.05 : 2.0, -0.010, 0.0, {7.0, 40.0},
Austin Schuh23b21802016-04-03 21:18:56 -0700676 {4.0, 10.0}, {10.0, 25.0}, !traverse_down, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700677}
678
Austin Schuh3e4a5272016-04-20 20:11:00 -0700679void AutonomousActor::DoFullShot() {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700680 if (ShouldCancel()) return;
681 // Make sure that the base is aligned with the base.
682 LOG(INFO, "Waiting for the superstructure\n");
683 WaitForSuperstructure();
Austin Schuh3e4a5272016-04-20 20:11:00 -0700684
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800685 this_thread::sleep_for(chrono::milliseconds(500));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700686
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700687 if (ShouldCancel()) return;
688 LOG(INFO, "Triggering the vision actor\n");
689 AlignWithVisionGoal();
690
691 // Wait for the drive base to be aligned with the target and make sure that
692 // the shooter is up to speed.
693 LOG(INFO, "Waiting for vision to be aligned\n");
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800694 WaitForAlignedWithVision(chrono::milliseconds(2000));
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700695 if (ShouldCancel()) return;
696 LOG(INFO, "Waiting for shooter to be up to speed\n");
697 WaitForShooterSpeed();
698 if (ShouldCancel()) return;
699
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800700 this_thread::sleep_for(chrono::milliseconds(300));
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700701 LOG(INFO, "Shoot!\n");
702 Shoot();
703
704 // Turn off the shooter and fold up the superstructure.
705 if (ShouldCancel()) return;
706 LOG(INFO, "Stopping shooter\n");
707 SetShooterSpeed(0.0);
708 LOG(INFO, "Folding superstructure back down\n");
709 TuckArm(false, false);
710
711 // Wait for everything to be folded up.
712 LOG(INFO, "Waiting for superstructure to be folded back down\n");
Austin Schuh3e4a5272016-04-20 20:11:00 -0700713 WaitForSuperstructureLow();
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700714}
715
716void AutonomousActor::LowBarDrive() {
717 TuckArm(false, true);
718 StartDrive(-5.5, 0.0, kLowBarDrive, kSlowTurn);
719
720 if (!WaitForDriveNear(5.3, 0.0)) return;
721 TuckArm(true, true);
722
723 if (!WaitForDriveNear(5.0, 0.0)) return;
724
725 StartDrive(0.0, 0.0, kLowBarDrive, kSlowTurn);
726
727 if (!WaitForDriveNear(3.0, 0.0)) return;
728
729 StartDrive(0.0, 0.0, kLowBarDrive, kSlowTurn);
730
731 if (!WaitForDriveNear(1.0, 0.0)) return;
732
Austin Schuh15b5f6a2016-03-26 19:43:56 -0700733 StartDrive(0, -M_PI / 4.0 - 0.2, kLowBarDrive, kSlowTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700734}
735
Austin Schuh3e4a5272016-04-20 20:11:00 -0700736void AutonomousActor::TippyDrive(double goal_distance, double tip_distance,
737 double below, double above) {
738 StartDrive(goal_distance, 0.0, kMoatDrive, kSlowTurn);
739 if (!WaitForBelowAngle(below)) return;
740 if (!WaitForAboveAngle(above)) return;
741 // Ok, we are good now. Compensate by moving the goal by the error.
742 // Should be here at 2.7
743 drivetrain_queue.status.FetchLatest();
744 if (drivetrain_queue.status.get()) {
745 const double left_error =
746 (initial_drivetrain_.left -
747 drivetrain_queue.status->estimated_left_position);
748 const double right_error =
749 (initial_drivetrain_.right -
750 drivetrain_queue.status->estimated_right_position);
751 const double distance_to_go = (left_error + right_error) / 2.0;
752 const double distance_compensation =
753 goal_distance - tip_distance - distance_to_go;
754 LOG(INFO, "Going %f further at the bump\n", distance_compensation);
755 StartDrive(distance_compensation, 0.0, kMoatDrive, kSlowTurn);
756 }
757}
758
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700759void AutonomousActor::MiddleDrive() {
760 TuckArm(false, false);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700761 TippyDrive(3.65, 2.7, -0.2, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700762 if (!WaitForDriveDone()) return;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700763}
764
765void AutonomousActor::OneFromMiddleDrive(bool left) {
Austin Schuh3e4a5272016-04-20 20:11:00 -0700766 const double kTurnAngle = left ? -0.41 : 0.41;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700767 TuckArm(false, false);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700768 TippyDrive(4.05, 2.7, -0.2, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700769
770 if (!WaitForDriveDone()) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700771 StartDrive(0.0, kTurnAngle, kRealignDrive, kFastTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700772}
773
774void AutonomousActor::TwoFromMiddleDrive() {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700775 TuckArm(false, false);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700776 constexpr double kDriveDistance = 5.10;
777 TippyDrive(kDriveDistance, 2.7, -0.2, 0.0);
778
779 if (!WaitForDriveNear(kDriveDistance - 3.0, 2.0)) return;
780 StartDrive(0, -M_PI / 2 - 0.10, kMoatDrive, kFastTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700781
782 if (!WaitForDriveDone()) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700783 StartDrive(0, M_PI / 3 + 0.35, kMoatDrive, kFastTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700784}
Comran Morshedb134e772016-03-16 21:05:05 +0000785
Austin Schuh23b21802016-04-03 21:18:56 -0700786void AutonomousActor::CloseIfBall() {
787 ::y2016::sensors::ball_detector.FetchLatest();
788 if (::y2016::sensors::ball_detector.get()) {
789 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
790 if (ball_detected) {
791 CloseShooter();
792 }
793 }
794}
795
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700796void AutonomousActor::WaitForBallOrDriveDone() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700797 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
798 ::std::chrono::milliseconds(5) / 2);
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700799 while (true) {
800 if (ShouldCancel()) {
801 return;
802 }
803 phased_loop.SleepUntilNext();
804 drivetrain_queue.status.FetchLatest();
805 if (IsDriveDone()) {
806 return;
807 }
808
809 ::y2016::sensors::ball_detector.FetchLatest();
810 if (::y2016::sensors::ball_detector.get()) {
811 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
812 if (ball_detected) {
813 return;
814 }
815 }
816 }
817}
818
Austin Schuh23b21802016-04-03 21:18:56 -0700819void AutonomousActor::WaitForBall() {
820 while (true) {
821 ::y2016::sensors::ball_detector.FetchAnother();
822 if (::y2016::sensors::ball_detector.get()) {
823 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
824 if (ball_detected) {
825 return;
826 }
827 if (ShouldCancel()) return;
828 }
829 }
830}
831
Austin Schuh3e4a5272016-04-20 20:11:00 -0700832void AutonomousActor::TwoBallAuto() {
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800833 monotonic_clock::time_point start_time = monotonic_clock::now();
Austin Schuh3e4a5272016-04-20 20:11:00 -0700834 OpenShooter();
835 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 60.0}, {4.0, 10.0}, {10.0, 25.0},
836 false, 12.0);
837 if (ShouldCancel()) return;
838 LOG(INFO, "Waiting for the intake to come down.\n");
839
840 WaitForIntake();
841 LOG(INFO, "Intake done at %f seconds, starting to drive\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800842 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700843 if (ShouldCancel()) return;
844 const double kDriveDistance = 5.05;
845 StartDrive(-kDriveDistance, 0.0, kTwoBallLowDrive, kSlowTurn);
846
847 StartDrive(0.0, 0.4, kTwoBallLowDrive, kSwerveTurn);
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700848 if (!WaitForDriveNear(kDriveDistance - 0.5, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700849
Austin Schuh295c2d92016-05-01 12:28:04 -0700850 // Check if the ball is there.
851 bool first_ball_there = true;
852 ::y2016::sensors::ball_detector.FetchLatest();
853 if (::y2016::sensors::ball_detector.get()) {
854 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
855 first_ball_there = ball_detected;
856 LOG(INFO, "Saw the ball: %d at %f\n", first_ball_there,
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800857 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh295c2d92016-05-01 12:28:04 -0700858 }
Austin Schuh3e4a5272016-04-20 20:11:00 -0700859 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 40.0}, {4.0, 10.0}, {10.0, 25.0},
860 false, 0.0);
861 LOG(INFO, "Shutting off rollers at %f seconds, starting to straighten out\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800862 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700863 StartDrive(0.0, -0.4, kTwoBallLowDrive, kSwerveTurn);
864 MoveSuperstructure(-0.05, -0.010, 0.0, {8.0, 40.0}, {4.0, 10.0}, {10.0, 25.0},
865 false, 0.0);
866 CloseShooter();
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700867 if (!WaitForDriveNear(kDriveDistance - 2.4, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700868
869 // We are now under the low bar. Start lifting.
870 BackLongShotLowBarTwoBall();
871 LOG(INFO, "Spinning up the shooter wheels\n");
872 SetShooterSpeed(640.0);
873 StartDrive(0.0, 0.0, kTwoBallFastDrive, kSwerveTurn);
874
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700875 if (!WaitForDriveNear(1.50, kDoNotTurnCare)) return;
876 constexpr double kShootTurnAngle = -M_PI / 4.0 - 0.05;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700877 StartDrive(0, kShootTurnAngle, kTwoBallFastDrive, kFinishTurn);
878 BackLongShotTwoBall();
879
880 if (!WaitForDriveDone()) return;
881 LOG(INFO, "First shot done driving at %f seconds\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800882 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700883
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700884 WaitForSuperstructureProfile();
Austin Schuh3e4a5272016-04-20 20:11:00 -0700885
886 if (ShouldCancel()) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700887 AlignWithVisionGoal();
888
889 WaitForShooterSpeed();
890 if (ShouldCancel()) return;
891
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800892 constexpr chrono::milliseconds kVisionExtra{0};
893 WaitForAlignedWithVision(chrono::milliseconds(500) + kVisionExtra);
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700894 BackLongShotTwoBallFinish();
895 WaitForSuperstructureProfile();
896 if (ShouldCancel()) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700897 LOG(INFO, "Shoot!\n");
Austin Schuh295c2d92016-05-01 12:28:04 -0700898 if (first_ball_there) {
899 Shoot();
900 } else {
901 LOG(INFO, "Nah, not shooting\n");
902 }
Austin Schuh3e4a5272016-04-20 20:11:00 -0700903
904 LOG(INFO, "First shot at %f seconds\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800905 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700906 if (ShouldCancel()) return;
907
908 SetShooterSpeed(0.0);
909 LOG(INFO, "Folding superstructure back down\n");
910 TuckArm(true, true);
911
912 // Undo vision move.
913 StartDrive(0.0, 0.0, kTwoBallFastDrive, kFinishTurn);
914 if (!WaitForDriveDone()) return;
915
916 constexpr double kBackDrive = 3.09 - 0.4;
917 StartDrive(kBackDrive, 0.0, kTwoBallReturnDrive, kSlowTurn);
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700918 if (!WaitForDriveNear(kBackDrive - 0.19, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700919 StartDrive(0, -kShootTurnAngle, kTwoBallReturnDrive, kSwerveTurn);
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700920 if (!WaitForDriveNear(1.0, kDoNotTurnCare)) return;
921 StartDrive(0, 0, kTwoBallReturnSlow, kSwerveTurn);
Austin Schuh3e4a5272016-04-20 20:11:00 -0700922
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700923 if (!WaitForDriveNear(0.06, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700924 LOG(INFO, "At Low Bar %f\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800925 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700926
927 OpenShooter();
928 constexpr double kSecondBallAfterBarDrive = 2.10;
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700929 StartDrive(kSecondBallAfterBarDrive, 0.0, kTwoBallBallPickupAccel, kSlowTurn);
930 if (!WaitForDriveNear(kSecondBallAfterBarDrive - 0.5, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700931 constexpr double kBallSmallWallTurn = -0.11;
932 StartDrive(0, kBallSmallWallTurn, kTwoBallBallPickup, kFinishTurn);
933
934 MoveSuperstructure(0.03, -0.010, 0.0, {8.0, 60.0}, {4.0, 10.0}, {10.0, 25.0},
935 false, 12.0);
936
937 if (!WaitForDriveProfileDone()) return;
938
939 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 60.0}, {4.0, 10.0}, {10.0, 25.0},
940 false, 12.0);
941
942 LOG(INFO, "Done backing up %f\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800943 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700944
945 constexpr double kDriveBackDistance = 5.15 - 0.4;
946 StartDrive(-kDriveBackDistance, 0.0, kTwoBallLowDrive, kFinishTurn);
947 CloseIfBall();
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700948 if (!WaitForDriveNear(kDriveBackDistance - 0.75, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700949
950 StartDrive(0.0, -kBallSmallWallTurn, kTwoBallLowDrive, kFinishTurn);
951 LOG(INFO, "Straightening up at %f\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800952 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700953
954 CloseIfBall();
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700955 if (!WaitForDriveNear(kDriveBackDistance - 2.3, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700956
957 ::y2016::sensors::ball_detector.FetchLatest();
958 if (::y2016::sensors::ball_detector.get()) {
959 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
960 if (!ball_detected) {
961 if (!WaitForDriveDone()) return;
962 LOG(INFO, "Aborting, no ball %f\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800963 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700964 return;
965 }
966 }
967 CloseShooter();
968
969 BackLongShotLowBarTwoBall();
970 LOG(INFO, "Spinning up the shooter wheels\n");
971 SetShooterSpeed(640.0);
972 StartDrive(0.0, 0.0, kTwoBallFastDrive, kSwerveTurn);
973
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700974 if (!WaitForDriveNear(1.80, kDoNotTurnCare)) return;
Austin Schuh3e4a5272016-04-20 20:11:00 -0700975 StartDrive(0, kShootTurnAngle, kTwoBallFastDrive, kFinishTurn);
976 BackLongShotTwoBall();
977
978 if (!WaitForDriveDone()) return;
979 LOG(INFO, "Second shot done driving at %f seconds\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800980 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -0700981 WaitForSuperstructure();
Austin Schuh3e4a5272016-04-20 20:11:00 -0700982 AlignWithVisionGoal();
983 if (ShouldCancel()) return;
984
985 WaitForShooterSpeed();
986 if (ShouldCancel()) return;
987
988 // 2.2 with 0.4 of vision.
989 // 1.8 without any vision.
990 LOG(INFO, "Going to vision align at %f\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800991 DoubleSeconds(monotonic_clock::now() - start_time));
992 WaitForAlignedWithVision(
993 (start_time + chrono::milliseconds(13500) + kVisionExtra * 2) -
994 monotonic_clock::now());
Austin Schuhe4ec49c2016-04-24 19:07:15 -0700995 BackLongShotTwoBallFinish();
996 WaitForSuperstructureProfile();
997 if (ShouldCancel()) return;
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800998 LOG(INFO, "Shoot at %f\n",
999 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -07001000 Shoot();
1001
1002 LOG(INFO, "Second shot at %f seconds\n",
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001003 DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -07001004 if (ShouldCancel()) return;
1005
1006 SetShooterSpeed(0.0);
1007 LOG(INFO, "Folding superstructure back down\n");
1008 TuckArm(true, false);
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001009 LOG(INFO, "Shot %f\n", DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -07001010
1011 WaitForSuperstructureLow();
1012
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001013 LOG(INFO, "Done %f\n", DoubleSeconds(monotonic_clock::now() - start_time));
Austin Schuh3e4a5272016-04-20 20:11:00 -07001014}
1015
Austin Schuhe4ec49c2016-04-24 19:07:15 -07001016void AutonomousActor::StealAndMoveOverBy(double distance) {
1017 OpenShooter();
1018 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 60.0}, {4.0, 10.0}, {10.0, 25.0},
1019 true, 12.0);
1020 if (ShouldCancel()) return;
1021 LOG(INFO, "Waiting for the intake to come down.\n");
1022
1023 WaitForIntake();
1024 if (ShouldCancel()) return;
1025 StartDrive(-distance, M_PI / 2.0, kFastDrive, kStealTurn);
1026 WaitForBallOrDriveDone();
1027 if (ShouldCancel()) return;
1028 MoveSuperstructure(1.0, -0.010, 0.0, {8.0, 60.0}, {4.0, 10.0}, {10.0, 25.0},
1029 true, 12.0);
1030
1031 if (!WaitForDriveDone()) return;
1032 StartDrive(0.0, M_PI / 2.0, kFastDrive, kStealTurn);
1033 if (!WaitForDriveDone()) return;
1034}
1035
Comran Morshede68e3732016-03-12 14:12:11 +00001036bool AutonomousActor::RunAction(const actors::AutonomousActionParams &params) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001037 monotonic_clock::time_point start_time = monotonic_clock::now();
Comran Morshede68e3732016-03-12 14:12:11 +00001038 LOG(INFO, "Starting autonomous action with mode %" PRId32 "\n", params.mode);
1039
Comran Morshed435f1112016-03-12 14:20:45 +00001040 InitializeEncoders();
1041 ResetDrivetrain();
1042
Austin Schuh295c2d92016-05-01 12:28:04 -07001043 switch (params.mode) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001044 case 0:
1045 LowBarDrive();
Austin Schuh3e4a5272016-04-20 20:11:00 -07001046 if (!WaitForDriveDone()) return true;
1047 // Get the superstructure to unfold and get ready for shooting.
1048 LOG(INFO, "Unfolding superstructure\n");
1049 FrontLongShot();
1050
1051 // Spin up the shooter wheels.
1052 LOG(INFO, "Spinning up the shooter wheels\n");
1053 SetShooterSpeed(640.0);
1054
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001055 break;
1056 case 1:
1057 TwoFromMiddleDrive();
Austin Schuh3e4a5272016-04-20 20:11:00 -07001058 if (!WaitForDriveDone()) return true;
1059 // Get the superstructure to unfold and get ready for shooting.
1060 LOG(INFO, "Unfolding superstructure\n");
1061 FrontMiddleShot();
1062
1063 // Spin up the shooter wheels.
1064 LOG(INFO, "Spinning up the shooter wheels\n");
1065 SetShooterSpeed(600.0);
1066
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001067 break;
1068 case 2:
1069 OneFromMiddleDrive(true);
Austin Schuh3e4a5272016-04-20 20:11:00 -07001070 if (!WaitForDriveDone()) return true;
1071 // Get the superstructure to unfold and get ready for shooting.
1072 LOG(INFO, "Unfolding superstructure\n");
1073 FrontMiddleShot();
1074
1075 // Spin up the shooter wheels.
1076 LOG(INFO, "Spinning up the shooter wheels\n");
1077 SetShooterSpeed(600.0);
1078
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001079 break;
1080 case 3:
1081 MiddleDrive();
Austin Schuh3e4a5272016-04-20 20:11:00 -07001082 if (!WaitForDriveDone()) return true;
1083 // Get the superstructure to unfold and get ready for shooting.
1084 LOG(INFO, "Unfolding superstructure\n");
1085 FrontMiddleShot();
1086
1087 // Spin up the shooter wheels.
1088 LOG(INFO, "Spinning up the shooter wheels\n");
1089 SetShooterSpeed(600.0);
1090
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001091 break;
1092 case 4:
1093 OneFromMiddleDrive(false);
Austin Schuh3e4a5272016-04-20 20:11:00 -07001094 if (!WaitForDriveDone()) return true;
1095 // Get the superstructure to unfold and get ready for shooting.
1096 LOG(INFO, "Unfolding superstructure\n");
1097 FrontMiddleShot();
1098
1099 // Spin up the shooter wheels.
1100 LOG(INFO, "Spinning up the shooter wheels\n");
1101 SetShooterSpeed(600.0);
1102
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001103 break;
Austin Schuh3e4a5272016-04-20 20:11:00 -07001104 case 5:
Campbell Crowley9ed61a52016-11-05 17:13:07 -07001105 case 15:
Austin Schuh3e4a5272016-04-20 20:11:00 -07001106 TwoBallAuto();
Austin Schuh23b21802016-04-03 21:18:56 -07001107 return true;
Austin Schuh3e4a5272016-04-20 20:11:00 -07001108 break;
Austin Schuhe4ec49c2016-04-24 19:07:15 -07001109 case 6:
1110 StealAndMoveOverBy(3.10 + 2 * 52 * 2.54 / 100.0);
1111 if (ShouldCancel()) return true;
1112
1113 TwoFromMiddleDrive();
1114 if (!WaitForDriveDone()) return true;
1115 // Get the superstructure to unfold and get ready for shooting.
1116 LOG(INFO, "Unfolding superstructure\n");
1117 FrontMiddleShot();
1118
1119 // Spin up the shooter wheels.
1120 LOG(INFO, "Spinning up the shooter wheels\n");
1121 SetShooterSpeed(600.0);
1122
1123 break;
1124 case 7:
1125 StealAndMoveOverBy(2.95 + 52 * 2.54 / 100.0);
1126 if (ShouldCancel()) return true;
1127
1128 OneFromMiddleDrive(true);
1129 if (!WaitForDriveDone()) return true;
1130 // Get the superstructure to unfold and get ready for shooting.
1131 LOG(INFO, "Unfolding superstructure\n");
1132 FrontMiddleShot();
1133
1134 // Spin up the shooter wheels.
1135 LOG(INFO, "Spinning up the shooter wheels\n");
1136 SetShooterSpeed(600.0);
1137
1138 break;
1139 case 8: {
1140 StealAndMoveOverBy(2.95);
1141 if (ShouldCancel()) return true;
1142
1143 MiddleDrive();
1144 if (!WaitForDriveDone()) return true;
1145 // Get the superstructure to unfold and get ready for shooting.
1146 LOG(INFO, "Unfolding superstructure\n");
1147 FrontMiddleShot();
1148
1149 // Spin up the shooter wheels.
1150 LOG(INFO, "Spinning up the shooter wheels\n");
1151 SetShooterSpeed(600.0);
1152
1153 } break;
1154 case 9: {
1155 StealAndMoveOverBy(1.70);
1156 if (ShouldCancel()) return true;
1157
1158 OneFromMiddleDrive(false);
1159 if (!WaitForDriveDone()) return true;
1160 // Get the superstructure to unfold and get ready for shooting.
1161 LOG(INFO, "Unfolding superstructure\n");
1162 FrontMiddleShot();
1163
1164 // Spin up the shooter wheels.
1165 LOG(INFO, "Spinning up the shooter wheels\n");
1166 SetShooterSpeed(600.0);
1167
1168 } break;
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001169 default:
Austin Schuh6c9bc622016-03-26 19:44:12 -07001170 LOG(ERROR, "Invalid auto mode %d\n", params.mode);
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001171 return true;
1172 }
Comran Morshed435f1112016-03-12 14:20:45 +00001173
Austin Schuh3e4a5272016-04-20 20:11:00 -07001174 DoFullShot();
1175
1176 StartDrive(0.5, 0.0, kMoatDrive, kFastTurn);
Comran Morshed435f1112016-03-12 14:20:45 +00001177 if (!WaitForDriveDone()) return true;
1178
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001179 LOG(INFO, "Done %f\n", DoubleSeconds(monotonic_clock::now() - start_time));
Comran Morshed435f1112016-03-12 14:20:45 +00001180
Austin Schuh8aec1ed2016-05-01 13:29:20 -07001181 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
1182 ::std::chrono::milliseconds(5) / 2);
Austin Schuhf59b8ee2016-03-19 21:31:36 -07001183
Comran Morshed435f1112016-03-12 14:20:45 +00001184 while (!ShouldCancel()) {
1185 phased_loop.SleepUntilNext();
Comran Morshede68e3732016-03-12 14:12:11 +00001186 }
Comran Morshed435f1112016-03-12 14:20:45 +00001187 LOG(DEBUG, "Done running\n");
Comran Morshede68e3732016-03-12 14:12:11 +00001188
1189 return true;
1190}
1191
1192::std::unique_ptr<AutonomousAction> MakeAutonomousAction(
1193 const ::y2016::actors::AutonomousActionParams &params) {
1194 return ::std::unique_ptr<AutonomousAction>(
1195 new AutonomousAction(&::y2016::actors::autonomous_action, params));
1196}
1197
1198} // namespace actors
1199} // namespace y2016