blob: e55a82764c16f63554dca46a1af56b7cca0921d2 [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"
Ben Fredrickson81ba2d52014-03-02 08:21:46 +000012#include "frc971/queues/othersensors.q.h"
Brian Silverman756f9ff2014-01-17 23:40:23 -080013#include "frc971/autonomous/auto.q.h"
Brian Silvermanfac5c292014-02-17 15:26:57 -080014#include "frc971/control_loops/claw/claw.q.h"
15#include "frc971/control_loops/shooter/shooter.q.h"
Ben Fredricksonaa450452014-03-01 09:41:18 +000016#include "frc971/actions/shoot_action.q.h"
Brian Silverman756f9ff2014-01-17 23:40:23 -080017
18using ::frc971::control_loops::drivetrain;
Ben Fredrickson81ba2d52014-03-02 08:21:46 +000019using ::frc971::sensors::othersensors;
Brian Silverman756f9ff2014-01-17 23:40:23 -080020
21using ::aos::input::driver_station::ButtonLocation;
22using ::aos::input::driver_station::JoystickAxis;
23using ::aos::input::driver_station::ControlBit;
24
25namespace frc971 {
26namespace input {
27namespace joysticks {
28
29const ButtonLocation kDriveControlLoopEnable1(1, 7),
30 kDriveControlLoopEnable2(1, 11);
31const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
32const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
33const ButtonLocation kQuickTurn(1, 5);
Austin Schuh58d23682014-02-23 01:39:50 -080034
Austin Schuh06cbbf12014-02-22 02:07:31 -080035const ButtonLocation kFire(3, 11);
Austin Schuh9cb836e2014-02-23 19:25:55 -080036const ButtonLocation kUnload(2, 11);
37const ButtonLocation kReload(2, 6);
Austin Schuh58d23682014-02-23 01:39:50 -080038
39const ButtonLocation kRollersOut(3, 12);
40const ButtonLocation kRollersIn(3, 10);
41
42const ButtonLocation kTuck(3, 8);
Austin Schuh9cb836e2014-02-23 19:25:55 -080043const ButtonLocation kIntakeOpenPosition(3, 9);
Austin Schuh58d23682014-02-23 01:39:50 -080044const ButtonLocation kIntakePosition(3, 7);
45
46const ButtonLocation kLongShot(3, 5);
47const ButtonLocation kMediumShot(3, 3);
48const ButtonLocation kShortShot(3, 6);
49
50struct ClawGoal {
51 double angle;
52 double separation;
53};
54
55const ClawGoal kTuckGoal = {-2.273474, -0.749484};
56const ClawGoal kIntakeGoal = {-2.273474, 0.0};
Austin Schuh9cb836e2014-02-23 19:25:55 -080057const ClawGoal kIntakeOpenGoal = {-2.0, 1.2};
Austin Schuh58d23682014-02-23 01:39:50 -080058
Austin Schuh9cb836e2014-02-23 19:25:55 -080059const ClawGoal kLongShotGoal = {-M_PI / 2.0 + 0.43, 0.10};
60const ClawGoal kMediumShotGoal = {-0.9, 0.10};
61const ClawGoal kShortShotGoal = {-0.04, 0.11};
Brian Silverman756f9ff2014-01-17 23:40:23 -080062
Austin Schuhb7dfabc2014-03-01 18:57:42 -080063class Action {
64 public:
65 // Cancels the action.
66 void Cancel() { DoCancel(); }
67 // Returns true if the action is currently running.
68 bool Running() { return DoRunning(); }
69 // Starts the action.
70 void Start() { DoStart(); }
71
72 private:
73 virtual void DoCancel() = 0;
74 virtual bool DoRunning() = 0;
75 virtual void DoStart() = 0;
76};
77
78// Templated subclass to hold the type information.
79template <typename T>
80class TypedAction : public Action {
81 public:
82 typedef typename std::remove_reference<
83 decltype(*(static_cast<T *>(NULL)->goal.MakeMessage().get()))>::type
84 GoalType;
85
86 TypedAction(T *queue_group)
87 : queue_group_(queue_group),
88 goal_(queue_group_->goal.MakeMessage()),
Austin Schuhc95c2b72014-03-02 11:56:49 -080089 has_started_(false) {}
Austin Schuhb7dfabc2014-03-01 18:57:42 -080090
91 // Returns the current goal that will be sent when the action is sent.
92 GoalType *GetGoal() { return goal_.get(); }
93
Austin Schuhc95c2b72014-03-02 11:56:49 -080094 ~TypedAction() {
95 LOG(INFO, "Calling destructor\n");
96 DoCancel();
97 }
98
Austin Schuhb7dfabc2014-03-01 18:57:42 -080099 private:
100 // Cancels the action.
Austin Schuhc95c2b72014-03-02 11:56:49 -0800101 virtual void DoCancel() {
102 LOG(INFO, "Canceling action\n");
103 queue_group_->goal.MakeWithBuilder().run(false).Send();
104 }
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800105
106 // Returns true if the action is running or we don't have an initial response
107 // back from it to signal whether or not it is running.
108 virtual bool DoRunning() {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800109 if (has_started_) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800110 queue_group_->status.FetchLatest();
111 } else if (queue_group_->status.FetchLatest()) {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800112 if (queue_group_->status->running) {
113 // Wait until it reports that it is running to start.
114 has_started_ = true;
115 }
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800116 }
Austin Schuhc95c2b72014-03-02 11:56:49 -0800117 return !has_started_ ||
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800118 (queue_group_->status.get() && queue_group_->status->running);
119 }
120
121 // Starts the action if a goal has been created.
122 virtual void DoStart() {
123 if (goal_) {
124 goal_->run = true;
125 goal_.Send();
Austin Schuhc95c2b72014-03-02 11:56:49 -0800126 has_started_ = false;
127 LOG(INFO, "Starting action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800128 } else {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800129 has_started_ = true;
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800130 }
131 }
132
133 T *queue_group_;
134 ::aos::ScopedMessagePtr<GoalType> goal_;
135 // Track if we have seen a response to the start message.
136 // If we haven't, we are considered running regardless.
Austin Schuhc95c2b72014-03-02 11:56:49 -0800137 bool has_started_;
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800138};
139
140// Makes a new ShootAction action.
141::std::unique_ptr<TypedAction< ::frc971::actions::ShootActionQueueGroup>>
142MakeShootAction() {
143 return ::std::unique_ptr<
144 TypedAction< ::frc971::actions::ShootActionQueueGroup>>(
145 new TypedAction< ::frc971::actions::ShootActionQueueGroup>(
146 &::frc971::actions::shoot_action));
147}
148
149// A queue which queues Actions and cancels them.
150class ActionQueue {
151 public:
152 // Queues up an action for sending.
153 void QueueAction(::std::unique_ptr<Action> action) {
154 if (current_action_) {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800155 LOG(INFO, "Queueing action, canceling prior\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800156 current_action_->Cancel();
157 next_action_ = ::std::move(action);
158 } else {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800159 LOG(INFO, "Queueing action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800160 current_action_ = ::std::move(action);
161 current_action_->Start();
162 }
163 }
164
165 // Cancels the current action, and runs the next one when the current one has
166 // finished.
167 void CancelCurrentAction() {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800168 LOG(INFO, "Canceling current action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800169 if (current_action_) {
170 current_action_->Cancel();
171 }
172 }
173
174 // Cancels all running actions.
175 void CancelAllActions() {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800176 LOG(INFO, "Canceling all actions\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800177 if (current_action_) {
178 current_action_->Cancel();
179 }
180 next_action_.reset();
181 }
182
183 // Runs the next action when the current one is finished running.
184 void Tick() {
185 if (current_action_) {
186 if (!current_action_->Running()) {
Austin Schuhc95c2b72014-03-02 11:56:49 -0800187 LOG(INFO, "Action is done.\n");
188 current_action_ = ::std::move(next_action_);
189 if (current_action_) {
190 LOG(INFO, "Running next action\n");
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800191 current_action_->Start();
192 }
193 }
194 }
195 }
196
197 // Returns true if any action is running or could be running.
198 // For a one cycle faster response, call Tick before running this.
199 bool Running() { return (bool)current_action_; }
200
201 private:
202 ::std::unique_ptr<Action> current_action_;
203 ::std::unique_ptr<Action> next_action_;
204};
205
Brian Silverman756f9ff2014-01-17 23:40:23 -0800206class Reader : public ::aos::input::JoystickInput {
207 public:
Austin Schuh58d23682014-02-23 01:39:50 -0800208 Reader()
209 : is_high_gear_(false),
Austin Schuh9cb836e2014-02-23 19:25:55 -0800210 shot_power_(80.0),
Austin Schuh58d23682014-02-23 01:39:50 -0800211 goal_angle_(0.0),
212 separation_angle_(0.0) {}
Brian Silverman756f9ff2014-01-17 23:40:23 -0800213
214 virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
Brian Silverman756f9ff2014-01-17 23:40:23 -0800215 if (data.GetControlBit(ControlBit::kAutonomous)) {
216 if (data.PosEdge(ControlBit::kEnabled)){
217 LOG(INFO, "Starting auto mode\n");
218 ::frc971::autonomous::autonomous.MakeWithBuilder()
219 .run_auto(true).Send();
220 } else if (data.NegEdge(ControlBit::kEnabled)) {
221 LOG(INFO, "Stopping auto mode\n");
222 ::frc971::autonomous::autonomous.MakeWithBuilder()
223 .run_auto(false).Send();
224 }
Austin Schuh58d23682014-02-23 01:39:50 -0800225 } else {
226 HandleTeleop(data);
Brian Silverman756f9ff2014-01-17 23:40:23 -0800227 }
228 }
Austin Schuh58d23682014-02-23 01:39:50 -0800229
230 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
231 bool is_control_loop_driving = false;
232 double left_goal = 0.0;
233 double right_goal = 0.0;
234 const double wheel = -data.GetAxis(kSteeringWheel);
235 const double throttle = -data.GetAxis(kDriveThrottle);
236 const double kThrottleGain = 1.0 / 2.5;
237 if (false && (data.IsPressed(kDriveControlLoopEnable1) ||
238 data.IsPressed(kDriveControlLoopEnable2))) {
239 // TODO(austin): Static sucks!
240 static double distance = 0.0;
241 static double angle = 0.0;
242 static double filtered_goal_distance = 0.0;
243 if (data.PosEdge(kDriveControlLoopEnable1) ||
244 data.PosEdge(kDriveControlLoopEnable2)) {
Ben Fredrickson81ba2d52014-03-02 08:21:46 +0000245 if (drivetrain.position.FetchLatest() && othersensors.FetchLatest()) {
Austin Schuh58d23682014-02-23 01:39:50 -0800246 distance = (drivetrain.position->left_encoder +
247 drivetrain.position->right_encoder) /
248 2.0 -
249 throttle * kThrottleGain / 2.0;
Ben Fredrickson81ba2d52014-03-02 08:21:46 +0000250 angle = othersensors->gyro_angle;
Austin Schuh58d23682014-02-23 01:39:50 -0800251 filtered_goal_distance = distance;
252 }
253 }
254 is_control_loop_driving = true;
255
256 // const double gyro_angle = Gyro.View().angle;
257 const double goal_theta = angle - wheel * 0.27;
258 const double goal_distance = distance + throttle * kThrottleGain;
259 const double robot_width = 22.0 / 100.0 * 2.54;
260 const double kMaxVelocity = 0.6;
261 if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
262 filtered_goal_distance += kMaxVelocity * 0.02;
263 } else if (goal_distance <
264 -kMaxVelocity * 0.02 + filtered_goal_distance) {
265 filtered_goal_distance -= kMaxVelocity * 0.02;
266 } else {
267 filtered_goal_distance = goal_distance;
268 }
269 left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
270 right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
271 is_high_gear_ = false;
272
273 LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
274 }
275 if (!drivetrain.goal.MakeWithBuilder()
276 .steering(wheel)
277 .throttle(throttle)
278 .highgear(is_high_gear_)
279 .quickturn(data.IsPressed(kQuickTurn))
280 .control_loop_driving(is_control_loop_driving)
281 .left_goal(left_goal)
282 .right_goal(right_goal)
283 .Send()) {
284 LOG(WARNING, "sending stick values failed\n");
285 }
286 if (data.PosEdge(kShiftHigh)) {
287 is_high_gear_ = false;
288 }
289 if (data.PosEdge(kShiftLow)) {
290 is_high_gear_ = true;
291 }
292 }
293
294 void SetGoal(ClawGoal goal) {
295 goal_angle_ = goal.angle;
296 separation_angle_ = goal.separation;
297 }
298
299 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
300 HandleDrivetrain(data);
Austin Schuhc95c2b72014-03-02 11:56:49 -0800301 if (!data.GetControlBit(ControlBit::kEnabled)) {
302 action_queue_.CancelAllActions();
303 }
Austin Schuh58d23682014-02-23 01:39:50 -0800304
Austin Schuh9cb836e2014-02-23 19:25:55 -0800305 if (data.IsPressed(kIntakeOpenPosition)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800306 action_queue_.CancelAllActions();
Austin Schuh9cb836e2014-02-23 19:25:55 -0800307 SetGoal(kIntakeOpenGoal);
308 } else if (data.IsPressed(kIntakePosition)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800309 action_queue_.CancelAllActions();
Austin Schuh58d23682014-02-23 01:39:50 -0800310 SetGoal(kIntakeGoal);
311 } else if (data.IsPressed(kTuck)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800312 action_queue_.CancelAllActions();
Austin Schuh58d23682014-02-23 01:39:50 -0800313 SetGoal(kTuckGoal);
314 }
315
Ben Fredricksonaa450452014-03-01 09:41:18 +0000316 if (data.PosEdge(kLongShot)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800317 auto shoot_action = MakeShootAction();
318
319 shot_power_ = 160.0;
320 shoot_action->GetGoal()->shot_power = shot_power_;
321 shoot_action->GetGoal()->shot_angle = kLongShotGoal.angle;
322 SetGoal(kLongShotGoal);
323
324 action_queue_.QueueAction(::std::move(shoot_action));
Ben Fredricksonf465a062014-03-02 00:18:59 +0000325 } else if (data.PosEdge(kMediumShot)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800326 auto shoot_action = MakeShootAction();
327
328 shot_power_ = 100.0;
329 shoot_action->GetGoal()->shot_power = shot_power_;
330 shoot_action->GetGoal()->shot_angle = kMediumShotGoal.angle;
331 SetGoal(kMediumShotGoal);
332
333 action_queue_.QueueAction(::std::move(shoot_action));
Ben Fredricksonf465a062014-03-02 00:18:59 +0000334 } else if (data.PosEdge(kShortShot)) {
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800335 auto shoot_action = MakeShootAction();
336
Austin Schuhc95c2b72014-03-02 11:56:49 -0800337 shot_power_ = 20.0;
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800338 shoot_action->GetGoal()->shot_power = shot_power_;
339 shoot_action->GetGoal()->shot_angle = kShortShotGoal.angle;
340 SetGoal(kShortShotGoal);
341
342 action_queue_.QueueAction(::std::move(shoot_action));
343 }
344
345 action_queue_.Tick();
Austin Schuhc95c2b72014-03-02 11:56:49 -0800346 if (data.IsPressed(kUnload) || data.IsPressed(kReload)) {
347 action_queue_.CancelAllActions();
348 }
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800349
350 // Send out the claw and shooter goals if no actions are running.
351 if (!action_queue_.Running()) {
352 if (!control_loops::claw_queue_group.goal.MakeWithBuilder()
353 .bottom_angle(goal_angle_)
354 .separation_angle(separation_angle_)
355 .intake(data.IsPressed(kRollersIn)
356 ? 12.0
357 : (data.IsPressed(kRollersOut) ? -12.0 : 0.0))
358 .centering(data.IsPressed(kRollersIn) ? 12.0 : 0.0)
359 .Send()) {
360 LOG(WARNING, "sending claw goal failed\n");
361 }
362
363 if (!control_loops::shooter_queue_group.goal.MakeWithBuilder()
364 .shot_power(shot_power_)
365 .shot_requested(data.IsPressed(kFire))
366 .unload_requested(data.IsPressed(kUnload))
367 .load_requested(data.IsPressed(kReload))
368 .Send()) {
369 LOG(WARNING, "sending shooter goal failed\n");
370 }
Austin Schuh58d23682014-02-23 01:39:50 -0800371 }
372 }
373
Austin Schuh01c652b2014-02-21 23:13:42 -0800374 private:
Austin Schuh58d23682014-02-23 01:39:50 -0800375 bool is_high_gear_;
376 double shot_power_;
377 double goal_angle_;
378 double separation_angle_;
Austin Schuhb7dfabc2014-03-01 18:57:42 -0800379
380 ActionQueue action_queue_;
Brian Silverman756f9ff2014-01-17 23:40:23 -0800381};
382
383} // namespace joysticks
384} // namespace input
385} // namespace frc971
386
387int main() {
388 ::aos::Init();
389 ::frc971::input::joysticks::Reader reader;
390 reader.Run();
391 ::aos::Cleanup();
392}