blob: 50bab3bd0fe98a72c36ecd811045f01d12716c3c [file] [log] [blame]
Comran Morshede68e3732016-03-12 14:12:11 +00001#include "y2016/actors/autonomous_actor.h"
2
3#include <inttypes.h>
4
Comran Morshedb134e772016-03-16 21:05:05 +00005#include <cmath>
6
Comran Morshede68e3732016-03-12 14:12:11 +00007#include "aos/common/util/phased_loop.h"
8#include "aos/common/logging/logging.h"
Comran Morshed435f1112016-03-12 14:20:45 +00009
10#include "frc971/control_loops/drivetrain/drivetrain.q.h"
11#include "y2016/control_loops/drivetrain/drivetrain_base.h"
Austin Schuhf59b8ee2016-03-19 21:31:36 -070012#include "y2016/control_loops/shooter/shooter.q.h"
Comran Morshedb134e772016-03-16 21:05:05 +000013#include "y2016/control_loops/superstructure/superstructure.q.h"
14#include "y2016/actors/autonomous_action.q.h"
Austin Schuh23b21802016-04-03 21:18:56 -070015#include "y2016/queues/ball_detector.q.h"
Austin Schuhf59b8ee2016-03-19 21:31:36 -070016#include "y2016/vision/vision.q.h"
Comran Morshede68e3732016-03-12 14:12:11 +000017
18namespace y2016 {
19namespace actors {
Comran Morshed435f1112016-03-12 14:20:45 +000020using ::frc971::control_loops::drivetrain_queue;
21
22namespace {
Austin Schuhf59b8ee2016-03-19 21:31:36 -070023const ProfileParameters kSlowDrive = {0.8, 2.5};
24const ProfileParameters kLowBarDrive = {1.3, 2.5};
25const ProfileParameters kMoatDrive = {1.2, 3.5};
26const ProfileParameters kRealignDrive = {2.0, 2.5};
27const ProfileParameters kRockWallDrive = {0.8, 2.5};
Comran Morshed435f1112016-03-12 14:20:45 +000028const ProfileParameters kFastDrive = {3.0, 2.5};
29
Austin Schuhf59b8ee2016-03-19 21:31:36 -070030const ProfileParameters kSlowTurn = {0.8, 3.0};
Comran Morshed435f1112016-03-12 14:20:45 +000031const ProfileParameters kFastTurn = {3.0, 10.0};
Austin Schuh23b21802016-04-03 21:18:56 -070032const ProfileParameters kSwerveTurn = {2.0, 7.0};
33const ProfileParameters kFinishTurn = {2.0, 5.0};
34
35const ProfileParameters kTwoBallLowDrive = {1.7, 3.5};
36const ProfileParameters kTwoBallFastDrive = {3.0, 1.5};
37const ProfileParameters kTwoBallReturnDrive = {3.0, 1.9};
38const ProfileParameters kTwoBallBallPickup = {2.0, 1.75};
Austin Schuhf59b8ee2016-03-19 21:31:36 -070039
40const double kDistanceShort = 0.25;
Comran Morshed435f1112016-03-12 14:20:45 +000041} // namespace
Comran Morshede68e3732016-03-12 14:12:11 +000042
43AutonomousActor::AutonomousActor(actors::AutonomousActionQueueGroup *s)
Comran Morshed435f1112016-03-12 14:20:45 +000044 : aos::common::actions::ActorBase<actors::AutonomousActionQueueGroup>(s),
Comran Morshedb134e772016-03-16 21:05:05 +000045 dt_config_(control_loops::drivetrain::GetDrivetrainConfig()),
46 initial_drivetrain_({0.0, 0.0}) {}
Comran Morshed435f1112016-03-12 14:20:45 +000047
48void AutonomousActor::ResetDrivetrain() {
49 LOG(INFO, "resetting the drivetrain\n");
50 drivetrain_queue.goal.MakeWithBuilder()
51 .control_loop_driving(false)
52 .highgear(true)
53 .steering(0.0)
54 .throttle(0.0)
Comran Morshedb134e772016-03-16 21:05:05 +000055 .left_goal(initial_drivetrain_.left)
Comran Morshed435f1112016-03-12 14:20:45 +000056 .left_velocity_goal(0)
Comran Morshedb134e772016-03-16 21:05:05 +000057 .right_goal(initial_drivetrain_.right)
Comran Morshed435f1112016-03-12 14:20:45 +000058 .right_velocity_goal(0)
59 .Send();
60}
61
62void AutonomousActor::StartDrive(double distance, double angle,
63 ProfileParameters linear,
64 ProfileParameters angular) {
65 {
Austin Schuh23b21802016-04-03 21:18:56 -070066 LOG(INFO, "Driving distance %f, angle %f\n", distance, angle);
Comran Morshed435f1112016-03-12 14:20:45 +000067 {
68 const double dangle = angle * dt_config_.robot_radius;
Comran Morshedb134e772016-03-16 21:05:05 +000069 initial_drivetrain_.left += distance - dangle;
70 initial_drivetrain_.right += distance + dangle;
Comran Morshed435f1112016-03-12 14:20:45 +000071 }
72
Comran Morshedb134e772016-03-16 21:05:05 +000073 auto drivetrain_message = drivetrain_queue.goal.MakeMessage();
Comran Morshed435f1112016-03-12 14:20:45 +000074 drivetrain_message->control_loop_driving = true;
75 drivetrain_message->highgear = true;
76 drivetrain_message->steering = 0.0;
77 drivetrain_message->throttle = 0.0;
Comran Morshedb134e772016-03-16 21:05:05 +000078 drivetrain_message->left_goal = initial_drivetrain_.left;
Comran Morshed435f1112016-03-12 14:20:45 +000079 drivetrain_message->left_velocity_goal = 0;
Comran Morshedb134e772016-03-16 21:05:05 +000080 drivetrain_message->right_goal = initial_drivetrain_.right;
Comran Morshed435f1112016-03-12 14:20:45 +000081 drivetrain_message->right_velocity_goal = 0;
82 drivetrain_message->linear = linear;
83 drivetrain_message->angular = angular;
84
85 LOG_STRUCT(DEBUG, "drivetrain_goal", *drivetrain_message);
86
87 drivetrain_message.Send();
88 }
89}
90
91void AutonomousActor::InitializeEncoders() {
92 drivetrain_queue.status.FetchAnother();
Comran Morshedb134e772016-03-16 21:05:05 +000093 initial_drivetrain_.left = drivetrain_queue.status->estimated_left_position;
94 initial_drivetrain_.right = drivetrain_queue.status->estimated_right_position;
Comran Morshed435f1112016-03-12 14:20:45 +000095}
96
97void AutonomousActor::WaitUntilDoneOrCanceled(
98 ::std::unique_ptr<aos::common::actions::Action> action) {
99 if (!action) {
100 LOG(ERROR, "No action, not waiting\n");
101 return;
102 }
103
104 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
105 ::aos::time::Time::InMS(5) / 2);
106 while (true) {
107 // Poll the running bit and see if we should cancel.
108 phased_loop.SleepUntilNext();
109 if (!action->Running() || ShouldCancel()) {
110 return;
111 }
112 }
113}
114
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700115bool AutonomousActor::WaitForDriveNear(double distance, double angle) {
116 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
117 ::aos::time::Time::InMS(5) / 2);
118 constexpr double kPositionTolerance = 0.02;
119 constexpr double kProfileTolerance = 0.001;
120
121 while (true) {
122 if (ShouldCancel()) {
123 return false;
124 }
125 phased_loop.SleepUntilNext();
126 drivetrain_queue.status.FetchLatest();
127 if (drivetrain_queue.status.get()) {
128 const double left_profile_error =
129 (initial_drivetrain_.left -
130 drivetrain_queue.status->profiled_left_position_goal);
131 const double right_profile_error =
132 (initial_drivetrain_.right -
133 drivetrain_queue.status->profiled_right_position_goal);
134
135 const double left_error =
136 (initial_drivetrain_.left -
137 drivetrain_queue.status->estimated_left_position);
138 const double right_error =
139 (initial_drivetrain_.right -
140 drivetrain_queue.status->estimated_right_position);
141
142 const double profile_distance_to_go =
143 (left_profile_error + right_profile_error) / 2.0;
144 const double profile_angle_to_go =
145 (right_profile_error - left_profile_error) /
146 (dt_config_.robot_radius * 2.0);
147
148 const double distance_to_go = (left_error + right_error) / 2.0;
149 const double angle_to_go =
150 (right_error - left_error) / (dt_config_.robot_radius * 2.0);
151
152 if (::std::abs(profile_distance_to_go) < distance + kProfileTolerance &&
153 ::std::abs(profile_angle_to_go) < angle + kProfileTolerance &&
154 ::std::abs(distance_to_go) < distance + kPositionTolerance &&
155 ::std::abs(angle_to_go) < angle + kPositionTolerance) {
156 LOG(INFO, "Closer than %f distance, %f angle\n", distance, angle);
157 return true;
158 }
159 }
160 }
161}
162
Austin Schuh23b21802016-04-03 21:18:56 -0700163bool AutonomousActor::WaitForDriveProfileDone() {
164 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
165 ::aos::time::Time::InMS(5) / 2);
166 constexpr double kProfileTolerance = 0.001;
167
168 while (true) {
169 if (ShouldCancel()) {
170 return false;
171 }
172 phased_loop.SleepUntilNext();
173 drivetrain_queue.status.FetchLatest();
174 if (drivetrain_queue.status.get()) {
175 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
176 initial_drivetrain_.left) < kProfileTolerance &&
177 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
178 initial_drivetrain_.right) < kProfileTolerance) {
179 LOG(INFO, "Finished drive\n");
180 return true;
181 }
182 }
183 }
184}
185
Comran Morshed435f1112016-03-12 14:20:45 +0000186bool AutonomousActor::WaitForDriveDone() {
187 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
188 ::aos::time::Time::InMS(5) / 2);
189 constexpr double kPositionTolerance = 0.02;
190 constexpr double kVelocityTolerance = 0.10;
191 constexpr double kProfileTolerance = 0.001;
192
193 while (true) {
194 if (ShouldCancel()) {
195 return false;
196 }
197 phased_loop.SleepUntilNext();
198 drivetrain_queue.status.FetchLatest();
199 if (drivetrain_queue.status.get()) {
200 if (::std::abs(drivetrain_queue.status->profiled_left_position_goal -
Comran Morshedb134e772016-03-16 21:05:05 +0000201 initial_drivetrain_.left) < kProfileTolerance &&
Comran Morshed435f1112016-03-12 14:20:45 +0000202 ::std::abs(drivetrain_queue.status->profiled_right_position_goal -
Comran Morshedb134e772016-03-16 21:05:05 +0000203 initial_drivetrain_.right) < kProfileTolerance &&
Comran Morshed435f1112016-03-12 14:20:45 +0000204 ::std::abs(drivetrain_queue.status->estimated_left_position -
Comran Morshedb134e772016-03-16 21:05:05 +0000205 initial_drivetrain_.left) < kPositionTolerance &&
Comran Morshed435f1112016-03-12 14:20:45 +0000206 ::std::abs(drivetrain_queue.status->estimated_right_position -
Comran Morshedb134e772016-03-16 21:05:05 +0000207 initial_drivetrain_.right) < kPositionTolerance &&
Comran Morshed435f1112016-03-12 14:20:45 +0000208 ::std::abs(drivetrain_queue.status->estimated_left_velocity) <
209 kVelocityTolerance &&
210 ::std::abs(drivetrain_queue.status->estimated_right_velocity) <
211 kVelocityTolerance) {
212 LOG(INFO, "Finished drive\n");
213 return true;
214 }
215 }
216 }
217}
Comran Morshede68e3732016-03-12 14:12:11 +0000218
Comran Morshedb134e772016-03-16 21:05:05 +0000219void AutonomousActor::MoveSuperstructure(
220 double intake, double shoulder, double wrist,
221 const ProfileParameters intake_params,
222 const ProfileParameters shoulder_params,
Austin Schuh23b21802016-04-03 21:18:56 -0700223 const ProfileParameters wrist_params, bool traverse_up,
224 double roller_power) {
Comran Morshedb134e772016-03-16 21:05:05 +0000225 superstructure_goal_ = {intake, shoulder, wrist};
226
227 auto new_superstructure_goal =
228 ::y2016::control_loops::superstructure_queue.goal.MakeMessage();
229
230 new_superstructure_goal->angle_intake = intake;
231 new_superstructure_goal->angle_shoulder = shoulder;
232 new_superstructure_goal->angle_wrist = wrist;
233
234 new_superstructure_goal->max_angular_velocity_intake =
235 intake_params.max_velocity;
236 new_superstructure_goal->max_angular_velocity_shoulder =
237 shoulder_params.max_velocity;
238 new_superstructure_goal->max_angular_velocity_wrist =
239 wrist_params.max_velocity;
240
241 new_superstructure_goal->max_angular_acceleration_intake =
242 intake_params.max_acceleration;
243 new_superstructure_goal->max_angular_acceleration_shoulder =
244 shoulder_params.max_acceleration;
245 new_superstructure_goal->max_angular_acceleration_wrist =
246 wrist_params.max_acceleration;
247
Austin Schuh23b21802016-04-03 21:18:56 -0700248 new_superstructure_goal->voltage_top_rollers = roller_power;
249 new_superstructure_goal->voltage_bottom_rollers = roller_power;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700250
251 new_superstructure_goal->traverse_unlatched = true;
252 new_superstructure_goal->traverse_down = !traverse_up;
Comran Morshedb134e772016-03-16 21:05:05 +0000253
254 if (!new_superstructure_goal.Send()) {
255 LOG(ERROR, "Sending superstructure goal failed.\n");
256 }
257}
258
Austin Schuh23b21802016-04-03 21:18:56 -0700259void AutonomousActor::OpenShooter() {
260 shooter_speed_ = 0.0;
261
262 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
263 .angular_velocity(shooter_speed_)
264 .clamp_open(true)
265 .push_to_shooter(false)
266 .force_lights_on(false)
267 .Send()) {
268 LOG(ERROR, "Sending shooter goal failed.\n");
269 }
270}
271
272void AutonomousActor::CloseShooter() {
273 shooter_speed_ = 0.0;
274
275 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
276 .angular_velocity(shooter_speed_)
277 .clamp_open(false)
278 .push_to_shooter(false)
279 .force_lights_on(false)
280 .Send()) {
281 LOG(ERROR, "Sending shooter goal failed.\n");
282 }
283}
284
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700285void AutonomousActor::SetShooterSpeed(double speed) {
286 shooter_speed_ = speed;
287
288 // In auto, we want to have the lights on whenever possible since we have no
289 // hope of a human aligning the robot.
290 bool force_lights_on = shooter_speed_ > 1.0;
291
292 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
293 .angular_velocity(shooter_speed_)
294 .clamp_open(false)
295 .push_to_shooter(false)
296 .force_lights_on(force_lights_on)
297 .Send()) {
298 LOG(ERROR, "Sending shooter goal failed.\n");
299 }
300}
301
302void AutonomousActor::Shoot() {
303 uint32_t initial_shots = 0;
304
305 control_loops::shooter::shooter_queue.status.FetchLatest();
306 if (control_loops::shooter::shooter_queue.status.get()) {
307 initial_shots = control_loops::shooter::shooter_queue.status->shots;
308 }
309
310 // In auto, we want to have the lights on whenever possible since we have no
311 // hope of a human aligning the robot.
312 bool force_lights_on = shooter_speed_ > 1.0;
313
314 if (!control_loops::shooter::shooter_queue.goal.MakeWithBuilder()
315 .angular_velocity(shooter_speed_)
316 .clamp_open(false)
317 .push_to_shooter(true)
318 .force_lights_on(force_lights_on)
319 .Send()) {
320 LOG(ERROR, "Sending shooter goal failed.\n");
321 }
322
323 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
324 ::aos::time::Time::InMS(5) / 2);
325 while (true) {
326 if (ShouldCancel()) return;
327
328 // Wait for the shot count to change so we know when the shot is complete.
329 control_loops::shooter::shooter_queue.status.FetchLatest();
330 if (control_loops::shooter::shooter_queue.status.get()) {
331 if (initial_shots < control_loops::shooter::shooter_queue.status->shots) {
332 return;
333 }
334 }
335 phased_loop.SleepUntilNext();
336 }
337}
338
339void AutonomousActor::WaitForShooterSpeed() {
340 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
341 ::aos::time::Time::InMS(5) / 2);
342 while (true) {
343 if (ShouldCancel()) return;
344
345 control_loops::shooter::shooter_queue.status.FetchLatest();
346 if (control_loops::shooter::shooter_queue.status.get()) {
347 if (control_loops::shooter::shooter_queue.status->left.ready &&
348 control_loops::shooter::shooter_queue.status->right.ready) {
349 return;
350 }
351 }
352 phased_loop.SleepUntilNext();
353 }
354}
355
356void AutonomousActor::AlignWithVisionGoal() {
357 actors::VisionAlignActionParams params;
358 vision_action_ = ::std::move(actors::MakeVisionAlignAction(params));
359 vision_action_->Start();
360}
361
Austin Schuh23b21802016-04-03 21:18:56 -0700362void AutonomousActor::WaitForAlignedWithVision(
363 ::aos::time::Time align_duration) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700364 bool vision_valid = false;
365 double last_angle = 0.0;
366 int ready_to_fire = 0;
367
368 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
369 ::aos::time::Time::InMS(5) / 2);
370 ::aos::time::Time end_time =
Austin Schuh23b21802016-04-03 21:18:56 -0700371 ::aos::time::Time::Now() + align_duration;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700372 while (end_time > ::aos::time::Time::Now()) {
373 if (ShouldCancel()) break;
374
375 ::y2016::vision::vision_status.FetchLatest();
376 if (::y2016::vision::vision_status.get()) {
377 vision_valid = (::y2016::vision::vision_status->left_image_valid &&
378 ::y2016::vision::vision_status->right_image_valid);
379 last_angle = ::y2016::vision::vision_status->horizontal_angle;
380 }
381
382 drivetrain_queue.status.FetchLatest();
383 drivetrain_queue.goal.FetchLatest();
384
385 if (drivetrain_queue.status.get() && drivetrain_queue.goal.get()) {
386 const double left_goal = drivetrain_queue.goal->left_goal;
387 const double right_goal = drivetrain_queue.goal->right_goal;
388 const double left_current =
389 drivetrain_queue.status->estimated_left_position;
390 const double right_current =
391 drivetrain_queue.status->estimated_right_position;
392 const double left_velocity =
393 drivetrain_queue.status->estimated_left_velocity;
394 const double right_velocity =
395 drivetrain_queue.status->estimated_right_velocity;
396
397 if (vision_valid && ::std::abs(last_angle) < 0.02 &&
398 ::std::abs((left_goal - right_goal) -
399 (left_current - right_current)) /
400 dt_config_.robot_radius / 2.0 <
401 0.02 &&
402 ::std::abs(left_velocity - right_velocity) < 0.01) {
403 ++ready_to_fire;
404 } else {
405 ready_to_fire = 0;
406 }
407 if (ready_to_fire > 9) {
408 break;
Austin Schuh23b21802016-04-03 21:18:56 -0700409 LOG(INFO, "Vision align success!\n");
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700410 }
411 }
412 phased_loop.SleepUntilNext();
413 }
414
415 vision_action_->Cancel();
416 WaitUntilDoneOrCanceled(::std::move(vision_action_));
Austin Schuh23b21802016-04-03 21:18:56 -0700417 LOG(INFO, "Done waiting for vision\n");
418}
419
420bool AutonomousActor::IntakeDone() {
421 control_loops::superstructure_queue.status.FetchAnother();
422
423 constexpr double kProfileError = 1e-5;
424 constexpr double kEpsilon = 0.15;
425
426 if (control_loops::superstructure_queue.status->state < 12 ||
427 control_loops::superstructure_queue.status->state == 16) {
428 LOG(ERROR, "Superstructure no longer running, aborting action\n");
429 return true;
430 }
431
432 if (::std::abs(control_loops::superstructure_queue.status->intake.goal_angle -
433 superstructure_goal_.intake) < kProfileError &&
434 ::std::abs(control_loops::superstructure_queue.status->intake
435 .goal_angular_velocity) < kProfileError) {
436 LOG(DEBUG, "Profile done.\n");
437 if (::std::abs(control_loops::superstructure_queue.status->intake.angle -
438 superstructure_goal_.intake) < kEpsilon &&
439 ::std::abs(control_loops::superstructure_queue.status->intake
440 .angular_velocity) < kEpsilon) {
441 LOG(INFO, "Near goal, done.\n");
442 return true;
443 }
444 }
445 return false;
446}
447
448bool AutonomousActor::SuperstructureProfileDone() {
449 constexpr double kProfileError = 1e-5;
450 return ::std::abs(
451 control_loops::superstructure_queue.status->intake.goal_angle -
452 superstructure_goal_.intake) < kProfileError &&
453 ::std::abs(
454 control_loops::superstructure_queue.status->shoulder.goal_angle -
455 superstructure_goal_.shoulder) < kProfileError &&
456 ::std::abs(
457 control_loops::superstructure_queue.status->wrist.goal_angle -
458 superstructure_goal_.wrist) < kProfileError &&
459 ::std::abs(control_loops::superstructure_queue.status->intake
460 .goal_angular_velocity) < kProfileError &&
461 ::std::abs(control_loops::superstructure_queue.status->shoulder
462 .goal_angular_velocity) < kProfileError &&
463 ::std::abs(control_loops::superstructure_queue.status->wrist
464 .goal_angular_velocity) < kProfileError;
465}
466
467bool AutonomousActor::SuperstructureDone() {
468 control_loops::superstructure_queue.status.FetchAnother();
469
470 constexpr double kEpsilon = 0.03;
471
472 if (control_loops::superstructure_queue.status->state < 12 ||
473 control_loops::superstructure_queue.status->state == 16) {
474 LOG(ERROR, "Superstructure no longer running, aborting action\n");
475 return true;
476 }
477
478 if (SuperstructureProfileDone()) {
479 LOG(DEBUG, "Profile done.\n");
480 if (::std::abs(control_loops::superstructure_queue.status->intake.angle -
481 superstructure_goal_.intake) < (kEpsilon + 0.1) &&
482 ::std::abs(control_loops::superstructure_queue.status->shoulder.angle -
483 superstructure_goal_.shoulder) < (kEpsilon + 0.05) &&
484 ::std::abs(control_loops::superstructure_queue.status->wrist.angle -
485 superstructure_goal_.wrist) < (kEpsilon + 0.01) &&
486 ::std::abs(control_loops::superstructure_queue.status->intake
487 .angular_velocity) < (kEpsilon + 0.1) &&
488 ::std::abs(control_loops::superstructure_queue.status->shoulder
489 .angular_velocity) < (kEpsilon + 0.10) &&
490 ::std::abs(control_loops::superstructure_queue.status->wrist
491 .angular_velocity) < (kEpsilon + 0.05)) {
492 LOG(INFO, "Near goal, done.\n");
493 return true;
494 }
495 }
496 return false;
497}
498
499void AutonomousActor::WaitForIntake() {
500 while (true) {
501 if (ShouldCancel()) return;
502 if (IntakeDone()) return;
503 }
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700504}
505
Comran Morshedb134e772016-03-16 21:05:05 +0000506void AutonomousActor::WaitForSuperstructure() {
507 while (true) {
508 if (ShouldCancel()) return;
Austin Schuh23b21802016-04-03 21:18:56 -0700509 if (SuperstructureDone()) return;
510 }
511}
Comran Morshedb134e772016-03-16 21:05:05 +0000512
Austin Schuh23b21802016-04-03 21:18:56 -0700513void AutonomousActor::WaitForSuperstructureLow() {
514 while (true) {
515 if (ShouldCancel()) return;
516 control_loops::superstructure_queue.status.FetchAnother();
Comran Morshedb134e772016-03-16 21:05:05 +0000517
518 if (control_loops::superstructure_queue.status->state < 12 ||
519 control_loops::superstructure_queue.status->state == 16) {
520 LOG(ERROR, "Superstructure no longer running, aborting action\n");
521 return;
522 }
Austin Schuh23b21802016-04-03 21:18:56 -0700523 if (SuperstructureProfileDone()) return;
524 if (control_loops::superstructure_queue.status->shoulder.angle < 0.1) {
525 return;
Comran Morshedb134e772016-03-16 21:05:05 +0000526 }
527 }
528}
Austin Schuh23b21802016-04-03 21:18:56 -0700529void AutonomousActor::BackLongShotLowBarTwoBall() {
530 LOG(INFO, "Expanding for back long shot\n");
531 MoveSuperstructure(0.00, M_PI / 2.0 - 0.2, -0.625, {7.0, 40.0}, {4.0, 6.0},
532 {10.0, 25.0}, false, 0.0);
533}
534
535void AutonomousActor::BackLongShotTwoBall() {
536 LOG(INFO, "Expanding for back long shot\n");
537 MoveSuperstructure(0.80, M_PI / 2.0 - 0.2, -0.625, {7.0, 40.0}, {4.0, 6.0},
538 {10.0, 25.0}, false, 0.0);
539}
540
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700541void AutonomousActor::BackLongShot() {
542 LOG(INFO, "Expanding for back long shot\n");
Austin Schuh23b21802016-04-03 21:18:56 -0700543 MoveSuperstructure(0.80, M_PI / 2.0 - 0.2, -0.62, {7.0, 40.0}, {4.0, 6.0},
544 {10.0, 25.0}, false, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700545}
546
547void AutonomousActor::BackMiddleShot() {
548 LOG(INFO, "Expanding for back middle shot\n");
549 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 -0700550 {10.0, 25.0}, false, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700551}
552
553void AutonomousActor::TuckArm(bool low_bar, bool traverse_down) {
554 MoveSuperstructure(low_bar ? -0.05 : 2.0, -0.010, 0.0, {7.0, 40.0},
Austin Schuh23b21802016-04-03 21:18:56 -0700555 {4.0, 10.0}, {10.0, 25.0}, !traverse_down, 0.0);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700556}
557
558void AutonomousActor::DoFullShot(bool center) {
559 // Get the superstructure to unfold and get ready for shooting.
560 LOG(INFO, "Unfolding superstructure\n");
561 if (center) {
562 BackMiddleShot();
563 } else {
564 BackLongShot();
565 }
566
567 // Spin up the shooter wheels.
568 LOG(INFO, "Spinning up the shooter wheels\n");
569 SetShooterSpeed(640.0);
570
571 if (ShouldCancel()) return;
572 // Make sure that the base is aligned with the base.
573 LOG(INFO, "Waiting for the superstructure\n");
574 WaitForSuperstructure();
575 if (ShouldCancel()) return;
576 LOG(INFO, "Triggering the vision actor\n");
577 AlignWithVisionGoal();
578
579 // Wait for the drive base to be aligned with the target and make sure that
580 // the shooter is up to speed.
581 LOG(INFO, "Waiting for vision to be aligned\n");
Austin Schuh23b21802016-04-03 21:18:56 -0700582 WaitForAlignedWithVision(aos::time::Time::InSeconds(3));
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700583 if (ShouldCancel()) return;
584 LOG(INFO, "Waiting for shooter to be up to speed\n");
585 WaitForShooterSpeed();
586 if (ShouldCancel()) return;
587
588 LOG(INFO, "Shoot!\n");
589 Shoot();
590
591 // Turn off the shooter and fold up the superstructure.
592 if (ShouldCancel()) return;
593 LOG(INFO, "Stopping shooter\n");
594 SetShooterSpeed(0.0);
595 LOG(INFO, "Folding superstructure back down\n");
596 TuckArm(false, false);
597
598 // Wait for everything to be folded up.
599 LOG(INFO, "Waiting for superstructure to be folded back down\n");
600 WaitForSuperstructure();
601}
602
603void AutonomousActor::LowBarDrive() {
604 TuckArm(false, true);
605 StartDrive(-5.5, 0.0, kLowBarDrive, kSlowTurn);
606
607 if (!WaitForDriveNear(5.3, 0.0)) return;
608 TuckArm(true, true);
609
610 if (!WaitForDriveNear(5.0, 0.0)) return;
611
612 StartDrive(0.0, 0.0, kLowBarDrive, kSlowTurn);
613
614 if (!WaitForDriveNear(3.0, 0.0)) return;
615
616 StartDrive(0.0, 0.0, kLowBarDrive, kSlowTurn);
617
618 if (!WaitForDriveNear(1.0, 0.0)) return;
619
Austin Schuh15b5f6a2016-03-26 19:43:56 -0700620 StartDrive(0, -M_PI / 4.0 - 0.2, kLowBarDrive, kSlowTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700621}
622
623void AutonomousActor::MiddleDrive() {
624 TuckArm(false, false);
Austin Schuh23b21802016-04-03 21:18:56 -0700625 StartDrive(4.05, 0.0, kMoatDrive, kSlowTurn);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700626 if (!WaitForDriveDone()) return;
627 StartDrive(0.0, M_PI, kMoatDrive, kFastTurn);
628}
629
630void AutonomousActor::OneFromMiddleDrive(bool left) {
631 const double kTurnAngle = left ? M_PI / 2.0 - 0.40 : (-M_PI / 2.0 + 0.40);
632 const double kFlipTurnAngle =
633 left ? (M_PI - kTurnAngle) : (-M_PI - kTurnAngle);
634 TuckArm(false, false);
635 StartDrive(5.0 - kDistanceShort, 0.0, kMoatDrive, kFastTurn);
636 if (!WaitForDriveDone()) return;
637 StartDrive(0.0, kTurnAngle, kRealignDrive, kFastTurn);
638 if (!WaitForDriveDone()) return;
639 StartDrive(-1.3, 0.0, kRealignDrive, kFastTurn);
640 if (!WaitForDriveDone()) return;
641 StartDrive(0.0, kFlipTurnAngle, kRealignDrive, kFastTurn);
642
643 if (!WaitForDriveDone()) return;
644 StartDrive(0.3, 0.0, kRealignDrive, kFastTurn);
645}
646
647void AutonomousActor::TwoFromMiddleDrive() {
648 const double kTurnAngle = M_PI / 2.0 - 0.13;
649 TuckArm(false, false);
650 StartDrive(5.0 - kDistanceShort, 0.0, kMoatDrive, kFastTurn);
651 if (!WaitForDriveDone()) return;
652 StartDrive(0.0, kTurnAngle, kMoatDrive, kFastTurn);
653 if (!WaitForDriveDone()) return;
654 StartDrive(-2.6, 0.0, kRealignDrive, kFastTurn);
655 if (!WaitForDriveDone()) return;
656 StartDrive(0.0, M_PI - kTurnAngle, kMoatDrive, kFastTurn);
657
658 if (!WaitForDriveDone()) return;
659 StartDrive(0.3, 0.0, kRealignDrive, kFastTurn);
660}
Comran Morshedb134e772016-03-16 21:05:05 +0000661
Austin Schuh23b21802016-04-03 21:18:56 -0700662void AutonomousActor::CloseIfBall() {
663 ::y2016::sensors::ball_detector.FetchLatest();
664 if (::y2016::sensors::ball_detector.get()) {
665 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
666 if (ball_detected) {
667 CloseShooter();
668 }
669 }
670}
671
672void AutonomousActor::WaitForBall() {
673 while (true) {
674 ::y2016::sensors::ball_detector.FetchAnother();
675 if (::y2016::sensors::ball_detector.get()) {
676 const bool ball_detected = ::y2016::sensors::ball_detector->voltage > 2.5;
677 if (ball_detected) {
678 return;
679 }
680 if (ShouldCancel()) return;
681 }
682 }
683}
684
Comran Morshede68e3732016-03-12 14:12:11 +0000685bool AutonomousActor::RunAction(const actors::AutonomousActionParams &params) {
686 LOG(INFO, "Starting autonomous action with mode %" PRId32 "\n", params.mode);
687
Comran Morshed435f1112016-03-12 14:20:45 +0000688 InitializeEncoders();
689 ResetDrivetrain();
690
Austin Schuh6c9bc622016-03-26 19:44:12 -0700691 switch (params.mode) {
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700692 case 0:
693 LowBarDrive();
694 break;
695 case 1:
696 TwoFromMiddleDrive();
697 break;
698 case 2:
699 OneFromMiddleDrive(true);
700 break;
701 case 3:
702 MiddleDrive();
703 break;
704 case 4:
705 OneFromMiddleDrive(false);
706 break;
Austin Schuh23b21802016-04-03 21:18:56 -0700707 case 5: {
708 aos::time::Time start_time = aos::time::Time::Now();
709 OpenShooter();
710 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 60.0},
711 {4.0, 10.0}, {10.0, 25.0}, false, 12.0);
712 if (ShouldCancel()) return true;
713 LOG(INFO, "Waiting for the intake to come down.\n");
714
715 WaitForIntake();
716 LOG(INFO, "Intake done at %f seconds, starting to drive\n",
717 (aos::time::Time::Now() - start_time).ToSeconds());
718 if (ShouldCancel()) return true;
719 const double kDriveDistance = 5.05;
720 StartDrive(-kDriveDistance, 0.0, kTwoBallLowDrive, kSlowTurn);
721
722 StartDrive(0.0, 0.4, kTwoBallLowDrive, kSwerveTurn);
723 if (!WaitForDriveNear(kDriveDistance - 0.5, 0.0)) return true;
724
725 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 40.0}, {4.0, 10.0},
726 {10.0, 25.0}, false, 0.0);
727 LOG(INFO, "Shutting off rollers at %f seconds, starting to straighten out\n",
728 (aos::time::Time::Now() - start_time).ToSeconds());
729 StartDrive(0.0, -0.4, kTwoBallLowDrive, kSwerveTurn);
730 MoveSuperstructure(-0.05, -0.010, 0.0, {8.0, 40.0}, {4.0, 10.0},
731 {10.0, 25.0}, false, 0.0);
732 CloseShooter();
733 if (!WaitForDriveNear(kDriveDistance - 2.4, 0.0)) return true;
734
735 // We are now under the low bar. Start lifting.
736 BackLongShotLowBarTwoBall();
737 LOG(INFO, "Spinning up the shooter wheels\n");
738 SetShooterSpeed(640.0);
739 StartDrive(0.0, 0.0, kTwoBallFastDrive, kSwerveTurn);
740
741 if (!WaitForDriveNear(1.50, 0.0)) return true;
742 constexpr double kShootTurnAngle = -M_PI / 4.0 - 0.05;
743 StartDrive(0, kShootTurnAngle, kTwoBallFastDrive, kFinishTurn);
744 BackLongShotTwoBall();
745
746 if (!WaitForDriveDone()) return true;
747 LOG(INFO, "First shot done driving at %f seconds\n",
748 (aos::time::Time::Now() - start_time).ToSeconds());
749
750 WaitForSuperstructure();
751
752 if (ShouldCancel()) return true;
753 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.1));
754 AlignWithVisionGoal();
755
756 WaitForShooterSpeed();
757 if (ShouldCancel()) return true;
758
759 WaitForAlignedWithVision(aos::time::Time::InSeconds(0.2));
760 LOG(INFO, "Shoot!\n");
761 Shoot();
762
763 LOG(INFO, "First shot at %f seconds\n",
764 (aos::time::Time::Now() - start_time).ToSeconds());
765 if (ShouldCancel()) return true;
766
767 SetShooterSpeed(0.0);
768 LOG(INFO, "Folding superstructure back down\n");
769 TuckArm(true, true);
770
771 // Undo vision move.
772 StartDrive(0.0, 0.0, kTwoBallFastDrive, kFinishTurn);
773 if (!WaitForDriveDone()) return true;
774
775 constexpr double kBackDrive = 3.09 - 0.4;
776 StartDrive(kBackDrive, 0.0, kTwoBallReturnDrive, kSlowTurn);
777 if (!WaitForDriveNear(kBackDrive - 0.16, 0.0)) return true;
778 StartDrive(0, -kShootTurnAngle, kTwoBallReturnDrive, kSwerveTurn);
779
780 if (!WaitForDriveNear(0.06, 0.0)) return true;
781 LOG(INFO, "At Low Bar %f\n",
782 (aos::time::Time::Now() - start_time).ToSeconds());
783
784 OpenShooter();
785 constexpr double kSecondBallAfterBarDrive = 2.10;
786 StartDrive(kSecondBallAfterBarDrive, 0.0, kTwoBallBallPickup, kSlowTurn);
787 if (!WaitForDriveNear(kSecondBallAfterBarDrive - 0.5, 0.0)) return true;
788 constexpr double kBallSmallWallTurn = -0.11;
789 StartDrive(0, kBallSmallWallTurn, kTwoBallBallPickup, kFinishTurn);
790
791 MoveSuperstructure(0.03, -0.010, 0.0, {8.0, 60.0},
792 {4.0, 10.0}, {10.0, 25.0}, false, 12.0);
793
794 if (!WaitForDriveProfileDone()) return true;
795
796 MoveSuperstructure(0.10, -0.010, 0.0, {8.0, 60.0},
797 {4.0, 10.0}, {10.0, 25.0}, false, 12.0);
798
799 LOG(INFO, "Done backing up %f\n",
800 (aos::time::Time::Now() - start_time).ToSeconds());
801
802 constexpr double kDriveBackDistance = 5.15 - 0.4;
803 StartDrive(-kDriveBackDistance, 0.0, kTwoBallLowDrive, kFinishTurn);
804 CloseIfBall();
805 if (!WaitForDriveNear(kDriveBackDistance - 0.75, 0.0)) return true;
806
807 StartDrive(0.0, -kBallSmallWallTurn, kTwoBallLowDrive, kFinishTurn);
808 LOG(INFO, "Straightening up at %f\n",
809 (aos::time::Time::Now() - start_time).ToSeconds());
810
811 CloseIfBall();
812 if (!WaitForDriveNear(kDriveBackDistance - 2.3, 0.0)) return true;
813
814 ::y2016::sensors::ball_detector.FetchLatest();
815 if (::y2016::sensors::ball_detector.get()) {
816 const bool ball_detected =
817 ::y2016::sensors::ball_detector->voltage > 2.5;
818 if (!ball_detected) {
819 if (!WaitForDriveDone()) return true;
820 LOG(INFO, "Aborting, no ball %f\n",
821 (aos::time::Time::Now() - start_time).ToSeconds());
822 return true;
823 }
824 }
825 CloseShooter();
826
827 BackLongShotLowBarTwoBall();
828 LOG(INFO, "Spinning up the shooter wheels\n");
829 SetShooterSpeed(640.0);
830 StartDrive(0.0, 0.0, kTwoBallFastDrive, kSwerveTurn);
831
832 if (!WaitForDriveNear(1.80, 0.0)) return true;
833 StartDrive(0, kShootTurnAngle, kTwoBallFastDrive, kFinishTurn);
834 BackLongShotTwoBall();
835
836 if (!WaitForDriveDone()) return true;
837 LOG(INFO, "Second shot done driving at %f seconds\n",
838 (aos::time::Time::Now() - start_time).ToSeconds());
839 WaitForSuperstructure();
840 ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.1));
841 AlignWithVisionGoal();
842 if (ShouldCancel()) return true;
843
844 WaitForShooterSpeed();
845 if (ShouldCancel()) return true;
846
847 // 2.2 with 0.4 of vision.
848 // 1.8 without any vision.
849 LOG(INFO, "Going to vision align at %f\n",
850 (aos::time::Time::Now() - start_time).ToSeconds());
851 WaitForAlignedWithVision(start_time + aos::time::Time::InSeconds(12.9) -
852 aos::time::Time::Now());
853 LOG(INFO, "Shoot at %f\n",
854 (aos::time::Time::Now() - start_time).ToSeconds());
855 Shoot();
856
857 LOG(INFO, "Second shot at %f seconds\n",
858 (aos::time::Time::Now() - start_time).ToSeconds());
859 if (ShouldCancel()) return true;
860
861 SetShooterSpeed(0.0);
862 LOG(INFO, "Folding superstructure back down\n");
863 TuckArm(true, false);
864 LOG(INFO, "Shot %f\n",
865 (aos::time::Time::Now() - start_time).ToSeconds());
866
867 WaitForSuperstructureLow();
868
869 LOG(INFO, "Done %f\n",
870 (aos::time::Time::Now() - start_time).ToSeconds());
871
872 return true;
873
874 } break;
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700875 default:
Austin Schuh6c9bc622016-03-26 19:44:12 -0700876 LOG(ERROR, "Invalid auto mode %d\n", params.mode);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700877 return true;
878 }
Comran Morshed435f1112016-03-12 14:20:45 +0000879
880 if (!WaitForDriveDone()) return true;
881
Austin Schuh6c9bc622016-03-26 19:44:12 -0700882 DoFullShot(params.mode != 0);
Comran Morshed435f1112016-03-12 14:20:45 +0000883
884 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
885 ::aos::time::Time::InMS(5) / 2);
Austin Schuhf59b8ee2016-03-19 21:31:36 -0700886
Comran Morshed435f1112016-03-12 14:20:45 +0000887 while (!ShouldCancel()) {
888 phased_loop.SleepUntilNext();
Comran Morshede68e3732016-03-12 14:12:11 +0000889 }
Comran Morshed435f1112016-03-12 14:20:45 +0000890 LOG(DEBUG, "Done running\n");
Comran Morshede68e3732016-03-12 14:12:11 +0000891
892 return true;
893}
894
895::std::unique_ptr<AutonomousAction> MakeAutonomousAction(
896 const ::y2016::actors::AutonomousActionParams &params) {
897 return ::std::unique_ptr<AutonomousAction>(
898 new AutonomousAction(&::y2016::actors::autonomous_action, params));
899}
900
901} // namespace actors
902} // namespace y2016