blob: b6fd150b54faeaf0f7f8a0833ded8630999c617a [file] [log] [blame]
Brian Silverman756f9ff2014-01-17 23:40:23 -08001#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <math.h>
5
6#include "aos/linux_code/init.h"
7#include "aos/prime/input/joystick_input.h"
Austin Schuh06cbbf12014-02-22 02:07:31 -08008#include "aos/common/input/driver_station_data.h"
Brian Silverman756f9ff2014-01-17 23:40:23 -08009#include "aos/common/logging/logging.h"
10
11#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Austin Schuh5d8c5e72014-03-07 20:24:34 -080012#include "frc971/constants.h"
Ben Fredrickson81ba2d52014-03-02 08:21:46 +000013#include "frc971/queues/othersensors.q.h"
Brian Silverman756f9ff2014-01-17 23:40:23 -080014#include "frc971/autonomous/auto.q.h"
Brian Silvermanfac5c292014-02-17 15:26:57 -080015#include "frc971/control_loops/claw/claw.q.h"
16#include "frc971/control_loops/shooter/shooter.q.h"
Ben Fredricksonaa450452014-03-01 09:41:18 +000017#include "frc971/actions/shoot_action.q.h"
Austin Schuh80ff2e12014-03-08 12:06:19 -080018#include "frc971/actions/action_client.h"
19#include "frc971/actions/catch_action.q.h"
20#include "frc971/actions/shoot_action.h"
Brian Silverman756f9ff2014-01-17 23:40:23 -080021
22using ::frc971::control_loops::drivetrain;
Ben Fredrickson81ba2d52014-03-02 08:21:46 +000023using ::frc971::sensors::othersensors;
Brian Silverman756f9ff2014-01-17 23:40:23 -080024
25using ::aos::input::driver_station::ButtonLocation;
26using ::aos::input::driver_station::JoystickAxis;
27using ::aos::input::driver_station::ControlBit;
28
29namespace frc971 {
30namespace input {
31namespace joysticks {
32
33const ButtonLocation kDriveControlLoopEnable1(1, 7),
34 kDriveControlLoopEnable2(1, 11);
35const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
36const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
37const ButtonLocation kQuickTurn(1, 5);
Austin Schuh58d23682014-02-23 01:39:50 -080038
Austin Schuh80ff2e12014-03-08 12:06:19 -080039const ButtonLocation kCatch(3, 10);
40
41const ButtonLocation kFire(3, 9);
Austin Schuh9cb836e2014-02-23 19:25:55 -080042const ButtonLocation kUnload(2, 11);
43const ButtonLocation kReload(2, 6);
Austin Schuh58d23682014-02-23 01:39:50 -080044
Austin Schuh80ff2e12014-03-08 12:06:19 -080045const ButtonLocation kRollersOut(3, 8);
46const ButtonLocation kRollersIn(3, 3);
Austin Schuh58d23682014-02-23 01:39:50 -080047
Austin Schuh80ff2e12014-03-08 12:06:19 -080048const ButtonLocation kTuck(3, 4);
49const ButtonLocation kIntakePosition(3, 5);
50const ButtonLocation kIntakeOpenPosition(3, 11);
51//const ButtonLocation kFlipRobot(3, 7);
52const JoystickAxis kFlipRobot(3, 3);
53// Truss shot. (3, 1)
Austin Schuh58d23682014-02-23 01:39:50 -080054
Austin Schuh80ff2e12014-03-08 12:06:19 -080055const ButtonLocation kLongShot(3, 7);
56const ButtonLocation kMediumShot(3, 6);
57const ButtonLocation kShortShot(3, 2);
Austin Schuh58d23682014-02-23 01:39:50 -080058
59struct ClawGoal {
60 double angle;
61 double separation;
62};
63
Austin Schuh5d8c5e72014-03-07 20:24:34 -080064struct ShotGoal {
65 ClawGoal claw;
66 double shot_power;
67 bool velocity_compensation;
68 double intake_power;
69};
70
Austin Schuh58d23682014-02-23 01:39:50 -080071const ClawGoal kTuckGoal = {-2.273474, -0.749484};
72const ClawGoal kIntakeGoal = {-2.273474, 0.0};
Austin Schuh9cb836e2014-02-23 19:25:55 -080073const ClawGoal kIntakeOpenGoal = {-2.0, 1.2};
Austin Schuh58d23682014-02-23 01:39:50 -080074
Austin Schuh80ff2e12014-03-08 12:06:19 -080075// TODO(austin): Tune these by hand...
76const ClawGoal kFlippedTuckGoal = {2.733474, -0.75};
77const ClawGoal kFlippedIntakeGoal = {2.0, 0.0};
78const ClawGoal kFlippedIntakeOpenGoal = {0.95, 1.0};
79
Austin Schuh5d8c5e72014-03-07 20:24:34 -080080const double kIntakePower = 2.0;
Austin Schuh80ff2e12014-03-08 12:06:19 -080081const double kShootSeparation = 0.08;
Austin Schuh5d8c5e72014-03-07 20:24:34 -080082
83const ShotGoal kLongShotGoal = {
Austin Schuh80ff2e12014-03-08 12:06:19 -080084 {-M_PI / 2.0 + 0.43, kShootSeparation}, 145, false, kIntakePower};
85const ShotGoal kMediumShotGoal = {
86 {-0.9, kShootSeparation}, 100, true, kIntakePower};
87const ShotGoal kShortShotGoal = {
88 {-0.04, kShootSeparation}, 10, false, kIntakePower};
Brian Silverman756f9ff2014-01-17 23:40:23 -080089
Austin Schuh80ff2e12014-03-08 12:06:19 -080090const ShotGoal kFlippedLongShotGoal = {
91 {M_PI / 2.0 - 0.43, kShootSeparation}, 145, false, kIntakePower};
92const ShotGoal kFlippedMediumShotGoal = {
93 {0.9, kShootSeparation}, 100, true, kIntakePower};
94const ShotGoal kFlippedShortShotGoal = {
95 {0.04, kShootSeparation}, 10, false, kIntakePower};
Austin Schuhb7dfabc2014-03-01 18:57:42 -080096
97// Makes a new ShootAction action.
Austin Schuh80ff2e12014-03-08 12:06:19 -080098::std::unique_ptr<TypedAction< ::frc971::actions::CatchActionGroup>>
99MakeCatchAction() {
100 return ::std::unique_ptr<TypedAction< ::frc971::actions::CatchActionGroup>>(
101 new TypedAction< ::frc971::actions::CatchActionGroup>(
102 &::frc971::actions::catch_action));
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800103}
104
105// A queue which queues Actions and cancels them.
106class ActionQueue {
107 public:
108 // Queues up an action for sending.
109 void QueueAction(::std::unique_ptr<Action> action) {
110 if (current_action_) {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800111 LOG(INFO, "Queueing action, canceling prior\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800112 current_action_->Cancel();
113 next_action_ = ::std::move(action);
114 } else {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800115 LOG(INFO, "Queueing action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800116 current_action_ = ::std::move(action);
117 current_action_->Start();
118 }
119 }
120
121 // Cancels the current action, and runs the next one when the current one has
122 // finished.
123 void CancelCurrentAction() {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800124 LOG(INFO, "Canceling current action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800125 if (current_action_) {
126 current_action_->Cancel();
127 }
128 }
129
130 // Cancels all running actions.
131 void CancelAllActions() {
Brian Silverman101b9642014-03-08 12:45:16 -0800132 LOG(DEBUG, "Cancelling all actions\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800133 if (current_action_) {
134 current_action_->Cancel();
135 }
136 next_action_.reset();
137 }
138
139 // Runs the next action when the current one is finished running.
140 void Tick() {
141 if (current_action_) {
142 if (!current_action_->Running()) {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800143 LOG(INFO, "Action is done.\n");
144 current_action_ = ::std::move(next_action_);
145 if (current_action_) {
146 LOG(INFO, "Running next action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800147 current_action_->Start();
148 }
149 }
150 }
151 }
152
153 // Returns true if any action is running or could be running.
154 // For a one cycle faster response, call Tick before running this.
155 bool Running() { return (bool)current_action_; }
156
157 private:
158 ::std::unique_ptr<Action> current_action_;
159 ::std::unique_ptr<Action> next_action_;
160};
161
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800162
Brian Silverman756f9ff2014-01-17 23:40:23 -0800163class Reader : public ::aos::input::JoystickInput {
164 public:
Austin Schuh58d23682014-02-23 01:39:50 -0800165 Reader()
166 : is_high_gear_(false),
Austin Schuh9cb836e2014-02-23 19:25:55 -0800167 shot_power_(80.0),
Austin Schuh58d23682014-02-23 01:39:50 -0800168 goal_angle_(0.0),
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800169 separation_angle_(0.0),
170 velocity_compensation_(false),
171 intake_power_(0.0),
172 was_running_(false) {}
Brian Silverman756f9ff2014-01-17 23:40:23 -0800173
174 virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
Brian Silverman756f9ff2014-01-17 23:40:23 -0800175 if (data.GetControlBit(ControlBit::kAutonomous)) {
176 if (data.PosEdge(ControlBit::kEnabled)){
177 LOG(INFO, "Starting auto mode\n");
178 ::frc971::autonomous::autonomous.MakeWithBuilder()
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800179 .run_auto(true)
180 .Send();
Brian Silverman756f9ff2014-01-17 23:40:23 -0800181 } else if (data.NegEdge(ControlBit::kEnabled)) {
182 LOG(INFO, "Stopping auto mode\n");
183 ::frc971::autonomous::autonomous.MakeWithBuilder()
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800184 .run_auto(false)
185 .Send();
Brian Silverman756f9ff2014-01-17 23:40:23 -0800186 }
Austin Schuh58d23682014-02-23 01:39:50 -0800187 } else {
188 HandleTeleop(data);
Brian Silverman756f9ff2014-01-17 23:40:23 -0800189 }
190 }
Austin Schuh58d23682014-02-23 01:39:50 -0800191
192 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
193 bool is_control_loop_driving = false;
194 double left_goal = 0.0;
195 double right_goal = 0.0;
196 const double wheel = -data.GetAxis(kSteeringWheel);
197 const double throttle = -data.GetAxis(kDriveThrottle);
198 const double kThrottleGain = 1.0 / 2.5;
199 if (false && (data.IsPressed(kDriveControlLoopEnable1) ||
200 data.IsPressed(kDriveControlLoopEnable2))) {
201 // TODO(austin): Static sucks!
202 static double distance = 0.0;
203 static double angle = 0.0;
204 static double filtered_goal_distance = 0.0;
205 if (data.PosEdge(kDriveControlLoopEnable1) ||
206 data.PosEdge(kDriveControlLoopEnable2)) {
Ben Fredrickson81ba2d52014-03-02 08:21:46 +0000207 if (drivetrain.position.FetchLatest() && othersensors.FetchLatest()) {
Austin Schuh58d23682014-02-23 01:39:50 -0800208 distance = (drivetrain.position->left_encoder +
209 drivetrain.position->right_encoder) /
210 2.0 -
211 throttle * kThrottleGain / 2.0;
Ben Fredrickson81ba2d52014-03-02 08:21:46 +0000212 angle = othersensors->gyro_angle;
Austin Schuh58d23682014-02-23 01:39:50 -0800213 filtered_goal_distance = distance;
214 }
215 }
216 is_control_loop_driving = true;
217
218 // const double gyro_angle = Gyro.View().angle;
219 const double goal_theta = angle - wheel * 0.27;
220 const double goal_distance = distance + throttle * kThrottleGain;
221 const double robot_width = 22.0 / 100.0 * 2.54;
222 const double kMaxVelocity = 0.6;
223 if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
224 filtered_goal_distance += kMaxVelocity * 0.02;
225 } else if (goal_distance <
226 -kMaxVelocity * 0.02 + filtered_goal_distance) {
227 filtered_goal_distance -= kMaxVelocity * 0.02;
228 } else {
229 filtered_goal_distance = goal_distance;
230 }
231 left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
232 right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
233 is_high_gear_ = false;
234
235 LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
236 }
237 if (!drivetrain.goal.MakeWithBuilder()
238 .steering(wheel)
239 .throttle(throttle)
240 .highgear(is_high_gear_)
241 .quickturn(data.IsPressed(kQuickTurn))
242 .control_loop_driving(is_control_loop_driving)
243 .left_goal(left_goal)
244 .right_goal(right_goal)
245 .Send()) {
246 LOG(WARNING, "sending stick values failed\n");
247 }
248 if (data.PosEdge(kShiftHigh)) {
249 is_high_gear_ = false;
250 }
251 if (data.PosEdge(kShiftLow)) {
252 is_high_gear_ = true;
253 }
254 }
255
256 void SetGoal(ClawGoal goal) {
257 goal_angle_ = goal.angle;
258 separation_angle_ = goal.separation;
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800259 velocity_compensation_ = false;
260 intake_power_ = 0.0;
261 }
262
263 void SetGoal(ShotGoal goal) {
264 goal_angle_ = goal.claw.angle;
265 separation_angle_ = goal.claw.separation;
266 shot_power_ = goal.shot_power;
267 velocity_compensation_ = goal.velocity_compensation;
268 intake_power_ = goal.intake_power;
Austin Schuh58d23682014-02-23 01:39:50 -0800269 }
270
271 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
272 HandleDrivetrain(data);
Austin Schuhc95c2b72014-03-02 11:56:49 -0800273 if (!data.GetControlBit(ControlBit::kEnabled)) {
274 action_queue_.CancelAllActions();
275 }
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800276 if (data.IsPressed(kRollersIn) || data.IsPressed(kRollersOut)) {
277 intake_power_ = 0.0;
278 }
Austin Schuh58d23682014-02-23 01:39:50 -0800279
Austin Schuh80ff2e12014-03-08 12:06:19 -0800280 if (data.GetAxis(kFlipRobot) < 0.5) {
281 if (data.IsPressed(kIntakeOpenPosition)) {
282 action_queue_.CancelAllActions();
283 SetGoal(kFlippedIntakeOpenGoal);
284 } else if (data.IsPressed(kIntakePosition)) {
285 action_queue_.CancelAllActions();
286 SetGoal(kFlippedIntakeGoal);
287 } else if (data.IsPressed(kTuck)) {
288 action_queue_.CancelAllActions();
289 SetGoal(kFlippedTuckGoal);
290 } else if (data.PosEdge(kLongShot)) {
291 action_queue_.CancelAllActions();
292 SetGoal(kFlippedLongShotGoal);
293 } else if (data.PosEdge(kMediumShot)) {
294 action_queue_.CancelAllActions();
295 SetGoal(kFlippedMediumShotGoal);
296 } else if (data.PosEdge(kShortShot)) {
297 action_queue_.CancelAllActions();
298 SetGoal(kFlippedShortShotGoal);
299 }
300 } else {
301 if (data.IsPressed(kIntakeOpenPosition)) {
302 action_queue_.CancelAllActions();
303 SetGoal(kIntakeOpenGoal);
304 } else if (data.IsPressed(kIntakePosition)) {
305 action_queue_.CancelAllActions();
306 SetGoal(kIntakeGoal);
307 } else if (data.IsPressed(kTuck)) {
308 action_queue_.CancelAllActions();
309 SetGoal(kTuckGoal);
310 } else if (data.PosEdge(kLongShot)) {
311 action_queue_.CancelAllActions();
312 SetGoal(kLongShotGoal);
313 } else if (data.PosEdge(kMediumShot)) {
314 action_queue_.CancelAllActions();
315 SetGoal(kMediumShotGoal);
316 } else if (data.PosEdge(kShortShot)) {
317 action_queue_.CancelAllActions();
318 SetGoal(kShortShotGoal);
319 }
Austin Schuh58d23682014-02-23 01:39:50 -0800320 }
321
Austin Schuh80ff2e12014-03-08 12:06:19 -0800322 if (data.PosEdge(kCatch)) {
323 auto catch_action = MakeCatchAction();
324 catch_action->GetGoal()->catch_angle = goal_angle_;
325 action_queue_.QueueAction(::std::move(catch_action));
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800326 }
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800327
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800328 if (data.PosEdge(kFire)) {
Austin Schuh80ff2e12014-03-08 12:06:19 -0800329 action_queue_.QueueAction(actions::MakeShootAction());
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800330 }
331
332 action_queue_.Tick();
Austin Schuhc95c2b72014-03-02 11:56:49 -0800333 if (data.IsPressed(kUnload) || data.IsPressed(kReload)) {
334 action_queue_.CancelAllActions();
Austin Schuh80ff2e12014-03-08 12:06:19 -0800335 intake_power_ = 0.0;
336 velocity_compensation_ = false;
Austin Schuhc95c2b72014-03-02 11:56:49 -0800337 }
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800338
339 // Send out the claw and shooter goals if no actions are running.
340 if (!action_queue_.Running()) {
Austin Schuh80ff2e12014-03-08 12:06:19 -0800341 // If the action just ended, turn the intake off and stop velocity
342 // compensating.
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800343 if (was_running_) {
344 intake_power_ = 0.0;
345 velocity_compensation_ = false;
346 }
347
348 control_loops::drivetrain.status.FetchLatest();
349 const double goal_angle =
350 goal_angle_ +
351 (velocity_compensation_
352 ? SpeedToAngleOffset(
353 control_loops::drivetrain.status->robot_speed)
354 : 0.0);
355
Austin Schuh80ff2e12014-03-08 12:06:19 -0800356 bool intaking = data.IsPressed(kRollersIn) ||
357 data.IsPressed(kIntakePosition) ||
358 data.IsPressed(kIntakeOpenPosition);
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800359 if (!control_loops::claw_queue_group.goal.MakeWithBuilder()
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800360 .bottom_angle(goal_angle)
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800361 .separation_angle(separation_angle_)
Austin Schuh80ff2e12014-03-08 12:06:19 -0800362 .intake(intaking ? 12.0
363 : (data.IsPressed(kRollersOut) ? -12.0
364 : intake_power_))
365 .centering(intaking ? 12.0 : 0.0)
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800366 .Send()) {
367 LOG(WARNING, "sending claw goal failed\n");
368 }
369
370 if (!control_loops::shooter_queue_group.goal.MakeWithBuilder()
371 .shot_power(shot_power_)
372 .shot_requested(data.IsPressed(kFire))
373 .unload_requested(data.IsPressed(kUnload))
374 .load_requested(data.IsPressed(kReload))
375 .Send()) {
376 LOG(WARNING, "sending shooter goal failed\n");
377 }
Austin Schuh58d23682014-02-23 01:39:50 -0800378 }
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800379 was_running_ = action_queue_.Running();
380 }
381
382 double SpeedToAngleOffset(double speed) {
383 const frc971::constants::Values &values = frc971::constants::GetValues();
384 // scale speed to a [0.0-1.0] on something close to the max
385 // TODO(austin): Change the scale factor for different shots.
386 return (speed / values.drivetrain_max_speed) * 0.3;
Austin Schuh58d23682014-02-23 01:39:50 -0800387 }
388
Austin Schuh01c652b2014-02-21 23:13:42 -0800389 private:
Austin Schuh58d23682014-02-23 01:39:50 -0800390 bool is_high_gear_;
391 double shot_power_;
392 double goal_angle_;
393 double separation_angle_;
Austin Schuh5d8c5e72014-03-07 20:24:34 -0800394 bool velocity_compensation_;
395 double intake_power_;
396 bool was_running_;
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800397
398 ActionQueue action_queue_;
Brian Silverman756f9ff2014-01-17 23:40:23 -0800399};
400
401} // namespace joysticks
402} // namespace input
403} // namespace frc971
404
405int main() {
406 ::aos::Init();
407 ::frc971::input::joysticks::Reader reader;
408 reader.Run();
409 ::aos::Cleanup();
410}