blob: a819757593cef656c32540bddb3887e61fb70570 [file] [log] [blame]
Comran Morshed0d6cf9b2015-06-17 19:29:57 +00001#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"
8#include "aos/common/input/driver_station_data.h"
9#include "aos/common/logging/logging.h"
10#include "aos/common/util/log_interval.h"
11#include "aos/common/time.h"
12#include "aos/common/actions/actions.h"
13
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000014#include "frc971/queues/gyro.q.h"
15#include "bot3/autonomous/auto.q.h"
Austin Schuhedd63012015-09-13 05:09:03 +000016#include "bot3/control_loops/elevator/elevator.h"
17#include "bot3/control_loops/drivetrain/drivetrain.q.h"
18#include "bot3/control_loops/elevator/elevator.q.h"
19#include "bot3/control_loops/intake/intake.q.h"
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000020
21using ::bot3::control_loops::drivetrain_queue;
Austin Schuhedd63012015-09-13 05:09:03 +000022using ::bot3::control_loops::elevator_queue;
23using ::bot3::control_loops::intake_queue;
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000024using ::frc971::sensors::gyro_reading;
25
26using ::aos::input::driver_station::ButtonLocation;
27using ::aos::input::driver_station::POVLocation;
28using ::aos::input::driver_station::JoystickAxis;
29using ::aos::input::driver_station::ControlBit;
30
31namespace bot3 {
32namespace input {
33namespace joysticks {
34
Austin Schuhedd63012015-09-13 05:09:03 +000035struct ProfileParams {
36 double velocity;
37 double acceleration;
38};
39
40// Preset motion limits.
41constexpr ProfileParams kElevatorMove{0.3, 1.0};
Austin Schuh8fc29c52015-09-13 20:19:05 +000042constexpr ProfileParams kFastElevatorMove{1.0, 5.0};
43
44// Preset goals for autostacking
Austin Schuh1ed71ad2015-09-14 21:24:03 +000045constexpr double kOneToteHeight{0.46};
Austin Schuh8fc29c52015-09-13 20:19:05 +000046constexpr double kCarryHeight{0.180};
47constexpr double kGroundHeight{0.030};
Austin Schuhedd63012015-09-13 05:09:03 +000048
49// Joystick & button addresses.
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000050const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
51const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
52const ButtonLocation kQuickTurn(1, 5);
53
Austin Schuhedd63012015-09-13 05:09:03 +000054// essential
55const ButtonLocation kMoveToteHeight(4, 9);
56const ButtonLocation kOpenIntake(3, 8);
57const ButtonLocation kCloseIntake(3, 6);
58const ButtonLocation kOpenCanRestraint(4, 5);
59const ButtonLocation kCloseCanRestraint(4, 1);
60const POVLocation kOpenPassiveSupport(4, 0);
61const POVLocation kClosePassiveSupport(4, 180);
62
Austin Schuh8fc29c52015-09-13 20:19:05 +000063const ButtonLocation kIntakeOut(3, 7);
64const ButtonLocation kIntakeIn(4, 12);
Austin Schuhedd63012015-09-13 05:09:03 +000065
66const ButtonLocation kAutoStack(4, 7);
67const ButtonLocation kManualStack(4, 6);
68
69const ButtonLocation kCarry(4, 10);
70const ButtonLocation kSetDown(3, 9);
71const ButtonLocation kSkyscraper(4, 11);
72
73const ButtonLocation kScoreBegin(4, 8);
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000074
Comran Morshed34f891d2015-09-15 22:04:43 +000075const ButtonLocation kCanGrabberLift(2, 1);
76const ButtonLocation kFastCanGrabberLift(2, 3);
77
Comran Morshed0d6cf9b2015-06-17 19:29:57 +000078class Reader : public ::aos::input::JoystickInput {
79 public:
80 Reader() : was_running_(false) {}
81
82 virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
83 bool last_auto_running = auto_running_;
84 auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
85 data.GetControlBit(ControlBit::kEnabled);
86 if (auto_running_ != last_auto_running) {
87 if (auto_running_) {
88 StartAuto();
89 } else {
90 StopAuto();
91 }
92 }
93
94 if (!data.GetControlBit(ControlBit::kAutonomous)) {
95 HandleDrivetrain(data);
96 HandleTeleop(data);
97 }
98 }
99
100 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
101 const double wheel = -data.GetAxis(kSteeringWheel);
102 const double throttle = -data.GetAxis(kDriveThrottle);
103
104 if (!drivetrain_queue.goal.MakeWithBuilder()
105 .steering(wheel)
106 .throttle(throttle)
107 .quickturn(data.IsPressed(kQuickTurn))
108 .control_loop_driving(false)
109 .Send()) {
110 LOG(WARNING, "sending stick values failed\n");
111 }
112 }
113
114 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
Austin Schuhedd63012015-09-13 05:09:03 +0000115 double intake_goal = 0;
116
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000117 if (!data.GetControlBit(ControlBit::kEnabled)) {
118 action_queue_.CancelAllActions();
Austin Schuhedd63012015-09-13 05:09:03 +0000119 intake_closed_ = false;
120 can_restraint_open_ = true;
121 passive_support_open_ = true;
Austin Schuh8fc29c52015-09-13 20:19:05 +0000122 LOG(DEBUG, "Canceling\n");
123 }
124
125 elevator_queue.status.FetchLatest();
126 if (!elevator_queue.status.get()) {
127 LOG(ERROR, "Got no elevator status packet.\n");
128 }
129
130 if (elevator_queue.status.get() && elevator_queue.status->zeroed) {
131 if (waiting_for_zero_) {
132 LOG(INFO, "Zeroed! Starting teleop mode.\n");
133 waiting_for_zero_ = false;
134
135 // Set the initial goals to the bottom, since otherwise the driver seems
136 // to get confused and think that the end of the zeroing sequence is the
137 // same location and then wonders why it doesn't work...
138 elevator_goal_ = kGroundHeight;
139 }
140 } else {
141 waiting_for_zero_ = true;
142 }
143
144 if (data.PosEdge(kAutoStack)) {
145 action_queue_.CancelAllActions();
146 if (tote_count_ == 6) {
147 stacking_state_machine_ = FULL;
148 } else {
149 stacking_state_machine_ = WAITING;
150 }
151 }
152 if (data.IsPressed(kAutoStack)) {
153 switch (stacking_state_machine_) {
154 case WAITING:
155 elevator_params_ = kFastElevatorMove;
156 elevator_goal_ = kOneToteHeight;
157 if (elevator_queue.status->has_tote) {
158 stacking_state_machine_ = GOING_DOWN;
159 }
160 break;
161 case GOING_DOWN:
162 elevator_params_ = kFastElevatorMove;
163 elevator_goal_ = kGroundHeight;
164 if (elevator_queue.status->height < 0.05) {
165 ++tote_count_;
166 if (tote_count_ == 6) {
167 stacking_state_machine_ = FULL;
168 } else {
169 stacking_state_machine_ = GOING_UP;
170 }
171 }
172 break;
173 case GOING_UP:
174 elevator_params_ = kFastElevatorMove;
175 elevator_goal_ = kOneToteHeight;
176 if (elevator_queue.status->height > kOneToteHeight - 0.05) {
177 stacking_state_machine_ = WAITING;
178 }
179 break;
180 case FULL:
181 elevator_goal_ = kCarryHeight;
182 elevator_params_ = kFastElevatorMove;
183 break;
184 case OFF:
185 stacking_state_machine_ = WAITING;
186 break;
187 }
188 } else {
189 stacking_state_machine_ = OFF;
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000190 }
191
Austin Schuhedd63012015-09-13 05:09:03 +0000192 // Buttons for intaking.
193 if (data.IsPressed(kIntakeIn)) {
194 intake_goal = 10.0;
Austin Schuh8fc29c52015-09-13 20:19:05 +0000195 if (stacking_state_machine_ != OFF &&
196 elevator_queue.status->height < 0.43) {
197 intake_goal = 0.0;
198 }
Austin Schuhedd63012015-09-13 05:09:03 +0000199 } else if (data.IsPressed(kIntakeOut)) {
200 intake_goal = -10.0;
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000201
Austin Schuhedd63012015-09-13 05:09:03 +0000202 action_queue_.CancelAllActions();
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000203 }
Austin Schuhedd63012015-09-13 05:09:03 +0000204 // TODO(Adam): Implement essential actors/goals.
205 if (data.PosEdge(kMoveToteHeight)) {
Austin Schuhedd63012015-09-13 05:09:03 +0000206 elevator_goal_ = 0.45;
207 elevator_params_ = {1.0, 5.0};
208 action_queue_.CancelAllActions();
209 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000210
Austin Schuhedd63012015-09-13 05:09:03 +0000211 if (data.PosEdge(kOpenIntake)) {
212 intake_closed_ = false;
213 }
214
215 if (data.PosEdge(kCloseIntake)) {
216 intake_closed_ = true;
217 }
218
219 if (data.PosEdge(kOpenCanRestraint)) {
220 can_restraint_open_ = true;
221 }
222
223 if (data.PosEdge(kCloseCanRestraint)) {
224 can_restraint_open_ = false;
225 }
226
227 if (data.PosEdge(kOpenPassiveSupport)) {
228 passive_support_open_ = true;
229 }
230
231 if (data.PosEdge(kClosePassiveSupport)) {
232 passive_support_open_ = false;
233 }
234
Austin Schuhedd63012015-09-13 05:09:03 +0000235 // Buttons for elevator.
Austin Schuhedd63012015-09-13 05:09:03 +0000236 if (data.PosEdge(kCarry)) {
237 // TODO(comran): Get actual height/velocity/acceleration values.
238 elevator_goal_ = 0.180;
239 elevator_params_ = {1.0, 2.0};
240 action_queue_.CancelAllActions();
241 }
242
243 if (data.PosEdge(kSetDown)) {
244 // TODO(comran): Get actual height/velocity/acceleration values.
Austin Schuh8fc29c52015-09-13 20:19:05 +0000245 elevator_goal_ = 0.005;
Austin Schuhedd63012015-09-13 05:09:03 +0000246 elevator_params_ = {1.0, 5.0};
247 action_queue_.CancelAllActions();
248 }
249
250 if (data.PosEdge(kSkyscraper)) {
251 // TODO(comran): Get actual height/velocity/acceleration values.
252 elevator_goal_ = 1.0;
Austin Schuhd54e0c42015-09-13 08:15:55 +0000253 elevator_params_ = {1.0, 5.0};
Austin Schuhedd63012015-09-13 05:09:03 +0000254 }
255
256 if (data.PosEdge(kScoreBegin)) {
257 // TODO(comran): Get actual height/velocity/acceleration values.
Austin Schuh8fc29c52015-09-13 20:19:05 +0000258 elevator_goal_ = 0.030;
259 elevator_params_ = {1.0, 5.0};
260 intake_closed_ = false;
261 can_restraint_open_ = true;
262 passive_support_open_ = true;
263 tote_count_ = 0;
Austin Schuhedd63012015-09-13 05:09:03 +0000264 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000265
Comran Morshed34f891d2015-09-15 22:04:43 +0000266 // Buttons for can grabber.
267 if (data.IsPressed(kCanGrabberLift)) {
268 ::bot3::autonomous::can_grabber_control.MakeWithBuilder()
269 .can_grabber_voltage(-4).Send();
270 } else if (data.IsPressed(kFastCanGrabberLift)) {
271 ::bot3::autonomous::can_grabber_control.MakeWithBuilder()
272 .can_grabber_voltage(-12).Send();
273 }
274
Austin Schuhedd63012015-09-13 05:09:03 +0000275 // Send our goals if everything looks OK.
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000276 if (!waiting_for_zero_) {
277 if (!action_queue_.Running()) {
Austin Schuhedd63012015-09-13 05:09:03 +0000278 // Send our elevator goals, with limits set in the profile params.
279 auto new_elevator_goal = elevator_queue.goal.MakeMessage();
280 new_elevator_goal->max_velocity = elevator_params_.velocity;
281 new_elevator_goal->max_acceleration = elevator_params_.acceleration;
282 new_elevator_goal->height = elevator_goal_;
283 new_elevator_goal->velocity = 0.0;
284 new_elevator_goal->passive_support = passive_support_open_;
285 new_elevator_goal->can_support = can_restraint_open_;
286
287 if (new_elevator_goal.Send()) {
288 LOG(DEBUG, "sending goals: elevator: %f\n", elevator_goal_);
289 } else {
290 LOG(ERROR, "Sending elevator goal failed.\n");
291 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000292 }
293 }
294
Austin Schuhedd63012015-09-13 05:09:03 +0000295 // Send our intake goals.
296 if (!intake_queue.goal.MakeWithBuilder().movement(intake_goal)
297 .claw_closed(intake_closed_).Send()) {
298 LOG(ERROR, "Sending intake goal failed.\n");
299 }
300
301 // If an action is running, use the action's goals for the profiled
302 // superstructure subsystems & bypass others.
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000303 if (action_queue_.Running()) {
Austin Schuhedd63012015-09-13 05:09:03 +0000304 control_loops::elevator_queue.status.FetchLatest();
305 if (control_loops::elevator_queue.status.get()) {
306 elevator_goal_ = control_loops::elevator_queue.status->goal_height;
307 } else {
308 LOG(ERROR, "No elevator status!\n");
309 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000310 }
311 action_queue_.Tick();
312 was_running_ = action_queue_.Running();
313 }
314
315 private:
316 void StartAuto() {
317 LOG(INFO, "Starting auto mode\n");
318 ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
319 }
320
321 void StopAuto() {
322 LOG(INFO, "Stopping auto mode\n");
323 ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
324 }
325
326 bool was_running_;
327
Austin Schuhedd63012015-09-13 05:09:03 +0000328 double elevator_goal_ = 0.2;
329
330 ProfileParams elevator_params_ = kElevatorMove;
331
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000332 // If we're waiting for the subsystems to zero.
333 bool waiting_for_zero_ = true;
334
335 bool auto_running_ = false;
336
Austin Schuhedd63012015-09-13 05:09:03 +0000337 bool intake_closed_ = false;
338
Austin Schuh8fc29c52015-09-13 20:19:05 +0000339 bool can_restraint_open_ = true;
Austin Schuhedd63012015-09-13 05:09:03 +0000340
Austin Schuh8fc29c52015-09-13 20:19:05 +0000341 bool passive_support_open_ = true;
342
343 int tote_count_ = 0;
Austin Schuhedd63012015-09-13 05:09:03 +0000344
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000345 ::aos::common::actions::ActionQueue action_queue_;
346
Austin Schuh8fc29c52015-09-13 20:19:05 +0000347 enum StackingStateMachine {
348 WAITING,
349 GOING_DOWN,
350 GOING_UP,
351 FULL,
352 OFF
353 };
354
355 StackingStateMachine stacking_state_machine_;
356
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000357 ::aos::util::SimpleLogInterval no_drivetrain_status_ =
358 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
359 "no drivetrain status");
360};
361
362} // namespace joysticks
363} // namespace input
364} // namespace bot3
365
366int main() {
367 ::aos::Init();
368 ::bot3::input::joysticks::Reader reader;
369 reader.Run();
370 ::aos::Cleanup();
371}