blob: 29d0f759af9ba66ed527842822dc7c469c809bb7 [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
45constexpr double kOneToteHeight{0.45};
46constexpr 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
75class Reader : public ::aos::input::JoystickInput {
76 public:
77 Reader() : was_running_(false) {}
78
79 virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
80 bool last_auto_running = auto_running_;
81 auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
82 data.GetControlBit(ControlBit::kEnabled);
83 if (auto_running_ != last_auto_running) {
84 if (auto_running_) {
85 StartAuto();
86 } else {
87 StopAuto();
88 }
89 }
90
91 if (!data.GetControlBit(ControlBit::kAutonomous)) {
92 HandleDrivetrain(data);
93 HandleTeleop(data);
94 }
95 }
96
97 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
98 const double wheel = -data.GetAxis(kSteeringWheel);
99 const double throttle = -data.GetAxis(kDriveThrottle);
100
101 if (!drivetrain_queue.goal.MakeWithBuilder()
102 .steering(wheel)
103 .throttle(throttle)
104 .quickturn(data.IsPressed(kQuickTurn))
105 .control_loop_driving(false)
106 .Send()) {
107 LOG(WARNING, "sending stick values failed\n");
108 }
109 }
110
111 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
Austin Schuhedd63012015-09-13 05:09:03 +0000112 double intake_goal = 0;
113
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000114 if (!data.GetControlBit(ControlBit::kEnabled)) {
115 action_queue_.CancelAllActions();
Austin Schuhedd63012015-09-13 05:09:03 +0000116 intake_closed_ = false;
117 can_restraint_open_ = true;
118 passive_support_open_ = true;
Austin Schuh8fc29c52015-09-13 20:19:05 +0000119 LOG(DEBUG, "Canceling\n");
120 }
121
122 elevator_queue.status.FetchLatest();
123 if (!elevator_queue.status.get()) {
124 LOG(ERROR, "Got no elevator status packet.\n");
125 }
126
127 if (elevator_queue.status.get() && elevator_queue.status->zeroed) {
128 if (waiting_for_zero_) {
129 LOG(INFO, "Zeroed! Starting teleop mode.\n");
130 waiting_for_zero_ = false;
131
132 // Set the initial goals to the bottom, since otherwise the driver seems
133 // to get confused and think that the end of the zeroing sequence is the
134 // same location and then wonders why it doesn't work...
135 elevator_goal_ = kGroundHeight;
136 }
137 } else {
138 waiting_for_zero_ = true;
139 }
140
141 if (data.PosEdge(kAutoStack)) {
142 action_queue_.CancelAllActions();
143 if (tote_count_ == 6) {
144 stacking_state_machine_ = FULL;
145 } else {
146 stacking_state_machine_ = WAITING;
147 }
148 }
149 if (data.IsPressed(kAutoStack)) {
150 switch (stacking_state_machine_) {
151 case WAITING:
152 elevator_params_ = kFastElevatorMove;
153 elevator_goal_ = kOneToteHeight;
154 if (elevator_queue.status->has_tote) {
155 stacking_state_machine_ = GOING_DOWN;
156 }
157 break;
158 case GOING_DOWN:
159 elevator_params_ = kFastElevatorMove;
160 elevator_goal_ = kGroundHeight;
161 if (elevator_queue.status->height < 0.05) {
162 ++tote_count_;
163 if (tote_count_ == 6) {
164 stacking_state_machine_ = FULL;
165 } else {
166 stacking_state_machine_ = GOING_UP;
167 }
168 }
169 break;
170 case GOING_UP:
171 elevator_params_ = kFastElevatorMove;
172 elevator_goal_ = kOneToteHeight;
173 if (elevator_queue.status->height > kOneToteHeight - 0.05) {
174 stacking_state_machine_ = WAITING;
175 }
176 break;
177 case FULL:
178 elevator_goal_ = kCarryHeight;
179 elevator_params_ = kFastElevatorMove;
180 break;
181 case OFF:
182 stacking_state_machine_ = WAITING;
183 break;
184 }
185 } else {
186 stacking_state_machine_ = OFF;
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000187 }
188
Austin Schuhedd63012015-09-13 05:09:03 +0000189 // Buttons for intaking.
190 if (data.IsPressed(kIntakeIn)) {
191 intake_goal = 10.0;
Austin Schuh8fc29c52015-09-13 20:19:05 +0000192 if (stacking_state_machine_ != OFF &&
193 elevator_queue.status->height < 0.43) {
194 intake_goal = 0.0;
195 }
Austin Schuhedd63012015-09-13 05:09:03 +0000196 } else if (data.IsPressed(kIntakeOut)) {
197 intake_goal = -10.0;
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000198
Austin Schuhedd63012015-09-13 05:09:03 +0000199 action_queue_.CancelAllActions();
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000200 }
Austin Schuhedd63012015-09-13 05:09:03 +0000201 // TODO(Adam): Implement essential actors/goals.
202 if (data.PosEdge(kMoveToteHeight)) {
Austin Schuhedd63012015-09-13 05:09:03 +0000203 elevator_goal_ = 0.45;
204 elevator_params_ = {1.0, 5.0};
205 action_queue_.CancelAllActions();
206 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000207
Austin Schuhedd63012015-09-13 05:09:03 +0000208 if (data.PosEdge(kOpenIntake)) {
209 intake_closed_ = false;
210 }
211
212 if (data.PosEdge(kCloseIntake)) {
213 intake_closed_ = true;
214 }
215
216 if (data.PosEdge(kOpenCanRestraint)) {
217 can_restraint_open_ = true;
218 }
219
220 if (data.PosEdge(kCloseCanRestraint)) {
221 can_restraint_open_ = false;
222 }
223
224 if (data.PosEdge(kOpenPassiveSupport)) {
225 passive_support_open_ = true;
226 }
227
228 if (data.PosEdge(kClosePassiveSupport)) {
229 passive_support_open_ = false;
230 }
231
Austin Schuhedd63012015-09-13 05:09:03 +0000232 // Buttons for elevator.
233
234 if (data.PosEdge(kCarry)) {
235 // TODO(comran): Get actual height/velocity/acceleration values.
236 elevator_goal_ = 0.180;
237 elevator_params_ = {1.0, 2.0};
238 action_queue_.CancelAllActions();
239 }
240
241 if (data.PosEdge(kSetDown)) {
242 // TODO(comran): Get actual height/velocity/acceleration values.
Austin Schuh8fc29c52015-09-13 20:19:05 +0000243 elevator_goal_ = 0.005;
Austin Schuhedd63012015-09-13 05:09:03 +0000244 elevator_params_ = {1.0, 5.0};
245 action_queue_.CancelAllActions();
246 }
247
248 if (data.PosEdge(kSkyscraper)) {
249 // TODO(comran): Get actual height/velocity/acceleration values.
250 elevator_goal_ = 1.0;
Austin Schuhd54e0c42015-09-13 08:15:55 +0000251 elevator_params_ = {1.0, 5.0};
Austin Schuhedd63012015-09-13 05:09:03 +0000252 }
253
254 if (data.PosEdge(kScoreBegin)) {
255 // TODO(comran): Get actual height/velocity/acceleration values.
Austin Schuh8fc29c52015-09-13 20:19:05 +0000256 elevator_goal_ = 0.030;
257 elevator_params_ = {1.0, 5.0};
258 intake_closed_ = false;
259 can_restraint_open_ = true;
260 passive_support_open_ = true;
261 tote_count_ = 0;
Austin Schuhedd63012015-09-13 05:09:03 +0000262 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000263
Austin Schuhedd63012015-09-13 05:09:03 +0000264 // Send our goals if everything looks OK.
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000265 if (!waiting_for_zero_) {
266 if (!action_queue_.Running()) {
Austin Schuhedd63012015-09-13 05:09:03 +0000267 // Send our elevator goals, with limits set in the profile params.
268 auto new_elevator_goal = elevator_queue.goal.MakeMessage();
269 new_elevator_goal->max_velocity = elevator_params_.velocity;
270 new_elevator_goal->max_acceleration = elevator_params_.acceleration;
271 new_elevator_goal->height = elevator_goal_;
272 new_elevator_goal->velocity = 0.0;
273 new_elevator_goal->passive_support = passive_support_open_;
274 new_elevator_goal->can_support = can_restraint_open_;
275
276 if (new_elevator_goal.Send()) {
277 LOG(DEBUG, "sending goals: elevator: %f\n", elevator_goal_);
278 } else {
279 LOG(ERROR, "Sending elevator goal failed.\n");
280 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000281 }
282 }
283
Austin Schuhedd63012015-09-13 05:09:03 +0000284 // Send our intake goals.
285 if (!intake_queue.goal.MakeWithBuilder().movement(intake_goal)
286 .claw_closed(intake_closed_).Send()) {
287 LOG(ERROR, "Sending intake goal failed.\n");
288 }
289
290 // If an action is running, use the action's goals for the profiled
291 // superstructure subsystems & bypass others.
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000292 if (action_queue_.Running()) {
Austin Schuhedd63012015-09-13 05:09:03 +0000293 control_loops::elevator_queue.status.FetchLatest();
294 if (control_loops::elevator_queue.status.get()) {
295 elevator_goal_ = control_loops::elevator_queue.status->goal_height;
296 } else {
297 LOG(ERROR, "No elevator status!\n");
298 }
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000299 }
300 action_queue_.Tick();
301 was_running_ = action_queue_.Running();
302 }
303
304 private:
305 void StartAuto() {
306 LOG(INFO, "Starting auto mode\n");
307 ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
308 }
309
310 void StopAuto() {
311 LOG(INFO, "Stopping auto mode\n");
312 ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
313 }
314
315 bool was_running_;
316
Austin Schuhedd63012015-09-13 05:09:03 +0000317 double elevator_goal_ = 0.2;
318
319 ProfileParams elevator_params_ = kElevatorMove;
320
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000321 // If we're waiting for the subsystems to zero.
322 bool waiting_for_zero_ = true;
323
324 bool auto_running_ = false;
325
Austin Schuhedd63012015-09-13 05:09:03 +0000326 bool intake_closed_ = false;
327
Austin Schuh8fc29c52015-09-13 20:19:05 +0000328 bool can_restraint_open_ = true;
Austin Schuhedd63012015-09-13 05:09:03 +0000329
Austin Schuh8fc29c52015-09-13 20:19:05 +0000330 bool passive_support_open_ = true;
331
332 int tote_count_ = 0;
Austin Schuhedd63012015-09-13 05:09:03 +0000333
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000334 ::aos::common::actions::ActionQueue action_queue_;
335
Austin Schuh8fc29c52015-09-13 20:19:05 +0000336 enum StackingStateMachine {
337 WAITING,
338 GOING_DOWN,
339 GOING_UP,
340 FULL,
341 OFF
342 };
343
344 StackingStateMachine stacking_state_machine_;
345
Comran Morshed0d6cf9b2015-06-17 19:29:57 +0000346 ::aos::util::SimpleLogInterval no_drivetrain_status_ =
347 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
348 "no drivetrain status");
349};
350
351} // namespace joysticks
352} // namespace input
353} // namespace bot3
354
355int main() {
356 ::aos::Init();
357 ::bot3::input::joysticks::Reader reader;
358 reader.Run();
359 ::aos::Cleanup();
360}