blob: 198b00215589eb21a552963a09cc72de6d47a402 [file] [log] [blame]
Adam Snaider18f44172016-10-22 15:30:21 -07001#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/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
14#include "frc971/control_loops/drivetrain/drivetrain.q.h"
15#include "y2016_bot3/control_loops/intake/intake.q.h"
16#include "y2016_bot3/control_loops/intake/intake.h"
17#include "y2016_bot3/queues/ball_detector.q.h"
18
19#include "frc971/queues/gyro.q.h"
20#include "frc971/autonomous/auto.q.h"
21#include "y2016_bot3/actors/autonomous_actor.h"
22#include "y2016_bot3/control_loops/drivetrain/drivetrain_base.h"
23
24using ::frc971::control_loops::drivetrain_queue;
25using ::y2016_bot3::control_loops::intake_queue;
26
27using ::aos::input::driver_station::ButtonLocation;
28using ::aos::input::driver_station::ControlBit;
29using ::aos::input::driver_station::JoystickAxis;
30using ::aos::input::driver_station::POVLocation;
31
32namespace y2016_bot3 {
33namespace input {
34namespace joysticks {
35
36const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
37const ButtonLocation kQuickTurn(1, 5);
38
39const ButtonLocation kTurn1(1, 7);
40const ButtonLocation kTurn2(1, 11);
41
42// Buttons on the lexan driver station to get things running on bring-up day.
Campbell Crowley483d6272016-11-05 14:11:34 -070043const ButtonLocation kIntakeDown(3, 5);
44const ButtonLocation kIntakeIn(3, 4);
Adam Snaider18f44172016-10-22 15:30:21 -070045const ButtonLocation kFire(3, 3);
Campbell Crowley483d6272016-11-05 14:11:34 -070046const ButtonLocation kIntakeOut(3, 3);
47const ButtonLocation kChevalDeFrise(3, 11);
Adam Snaider18f44172016-10-22 15:30:21 -070048
49class Reader : public ::aos::input::JoystickInput {
50 public:
51 Reader()
52 : intake_goal_(0.0),
53 dt_config_(control_loops::drivetrain::GetDrivetrainConfig()) {}
54
55 void RunIteration(const ::aos::input::driver_station::Data &data) override {
56 bool last_auto_running = auto_running_;
57 auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
58 data.GetControlBit(ControlBit::kEnabled);
59 if (auto_running_ != last_auto_running) {
60 if (auto_running_) {
61 StartAuto();
62 } else {
63 StopAuto();
64 }
65 }
66
67 if (!data.GetControlBit(ControlBit::kEnabled)) {
68 // If we are not enabled, reset the waiting for zero bit.
69 LOG(DEBUG, "Waiting for zero.\n");
70 waiting_for_zero_ = true;
71 }
72
73 if (!auto_running_) {
74 HandleDrivetrain(data);
75 HandleTeleop(data);
76 }
77
78 // Process any pending actions.
79 action_queue_.Tick();
80 was_running_ = action_queue_.Running();
81 }
82
83 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
84 bool is_control_loop_driving = false;
85 static double left_goal = 0.0;
86 static double right_goal = 0.0;
87
88 const double wheel = -data.GetAxis(kSteeringWheel);
89 const double throttle = -data.GetAxis(kDriveThrottle);
90 drivetrain_queue.status.FetchLatest();
91
92 if (data.PosEdge(kTurn1) || data.PosEdge(kTurn2)) {
93 if (drivetrain_queue.status.get()) {
94 left_goal = drivetrain_queue.status->estimated_left_position;
95 right_goal = drivetrain_queue.status->estimated_right_position;
96 }
97 }
98 if (data.IsPressed(kTurn1) || data.IsPressed(kTurn2)) {
99 is_control_loop_driving = true;
100 }
101 if (!drivetrain_queue.goal.MakeWithBuilder()
102 .steering(wheel)
103 .throttle(throttle)
104 .quickturn(data.IsPressed(kQuickTurn))
105 .control_loop_driving(is_control_loop_driving)
106 .left_goal(left_goal - wheel * 0.5 + throttle * 0.3)
107 .right_goal(right_goal + wheel * 0.5 + throttle * 0.3)
108 .left_velocity_goal(0)
109 .right_velocity_goal(0)
110 .Send()) {
111 LOG(WARNING, "sending stick values failed\n");
112 }
113 }
114
115 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
116 intake_goal_ = y2016_bot3::constants::kIntakeRange.upper - 0.04;
117
118 if (!data.GetControlBit(ControlBit::kEnabled)) {
119 action_queue_.CancelAllActions();
120 LOG(DEBUG, "Canceling\n");
121 }
122
123 intake_queue.status.FetchLatest();
124 if (!intake_queue.status.get()) {
125 LOG(ERROR, "Got no intake status packet.\n");
126 }
127
128 if (intake_queue.status.get() && intake_queue.status->zeroed) {
129 if (waiting_for_zero_) {
130 LOG(DEBUG, "Zeroed! Starting teleop mode.\n");
131 waiting_for_zero_ = false;
132 }
133 } else {
134 waiting_for_zero_ = true;
135 }
136
137 bool ball_detected = false;
138 ::y2016_bot3::sensors::ball_detector.FetchLatest();
139 if (::y2016_bot3::sensors::ball_detector.get()) {
140 ball_detected = ::y2016_bot3::sensors::ball_detector->voltage > 2.5;
141 }
142 if (data.PosEdge(kIntakeIn)) {
143 saw_ball_when_started_intaking_ = ball_detected;
144 }
145
Adam Snaidera3271fe2016-10-26 21:03:38 -0700146 is_intaking_ = data.IsPressed(kIntakeIn) &&
147 (!ball_detected || saw_ball_when_started_intaking_);
Adam Snaider18f44172016-10-22 15:30:21 -0700148
149 is_outtaking_ = data.IsPressed(kIntakeOut);
150
151 if (is_intaking_ || is_outtaking_) {
152 recently_intaking_accumulator_ = 20;
153 }
154
155 if (data.IsPressed(kIntakeDown)) {
156 if (recently_intaking_accumulator_) {
157 intake_goal_ = 0.1;
158 } else {
159 intake_goal_ = -0.05;
160 }
161 }
162
163 if (recently_intaking_accumulator_ > 0) {
164 --recently_intaking_accumulator_;
165 }
166
167 if (data.IsPressed(kChevalDeFrise)) {
Adam Snaider18f44172016-10-22 15:30:21 -0700168 traverse_down_ = true;
169 } else {
Adam Snaider18f44172016-10-22 15:30:21 -0700170 traverse_down_ = false;
171 }
172
173 if (!waiting_for_zero_) {
174 auto new_intake_goal = intake_queue.goal.MakeMessage();
175 new_intake_goal->angle_intake = intake_goal_;
176
177 new_intake_goal->max_angular_velocity_intake = 7.0;
178 new_intake_goal->max_angular_acceleration_intake = 40.0;
179
Adam Snaider10a8e312016-11-26 15:02:35 -0800180 static constexpr bool kGrannyMode = false;
181 if (kGrannyMode) {
182 new_intake_goal->max_angular_velocity_intake = 0.2;
183 new_intake_goal->max_angular_acceleration_intake = 1.0;
184 }
Campbell Crowley483d6272016-11-05 14:11:34 -0700185
Adam Snaider18f44172016-10-22 15:30:21 -0700186 if (is_intaking_) {
Campbell Crowley483d6272016-11-05 14:11:34 -0700187 new_intake_goal->voltage_intake_rollers = -12.0;
188 new_intake_goal->voltage_top_rollers = -12.0;
Adam Snaider18f44172016-10-22 15:30:21 -0700189 new_intake_goal->voltage_bottom_rollers = 12.0;
190 } else if (is_outtaking_) {
Campbell Crowley483d6272016-11-05 14:11:34 -0700191 new_intake_goal->voltage_intake_rollers = 12.0;
192 new_intake_goal->voltage_top_rollers = 12.0;
Adam Snaider18f44172016-10-22 15:30:21 -0700193 new_intake_goal->voltage_bottom_rollers = -7.0;
194 } else {
Campbell Crowley483d6272016-11-05 14:11:34 -0700195 new_intake_goal->voltage_intake_rollers = 0.0;
Adam Snaider18f44172016-10-22 15:30:21 -0700196 new_intake_goal->voltage_top_rollers = 0.0;
197 new_intake_goal->voltage_bottom_rollers = 0.0;
198 }
199
Adam Snaider18f44172016-10-22 15:30:21 -0700200 new_intake_goal->traverse_down = traverse_down_;
201 new_intake_goal->force_intake = true;
202
203 if (!new_intake_goal.Send()) {
204 LOG(ERROR, "Sending intake goal failed.\n");
205 } else {
206 LOG(DEBUG, "sending goal: intake: %f\n", intake_goal_);
207 }
208 }
209 }
210
211 private:
212 void StartAuto() {
213 LOG(INFO, "Starting auto mode\n");
214
215 actors::AutonomousActionParams params;
216 actors::auto_mode.FetchLatest();
217 if (actors::auto_mode.get() != nullptr) {
218 params.mode = actors::auto_mode->mode;
219 } else {
220 LOG(WARNING, "no auto mode values\n");
221 params.mode = 0;
222 }
223 action_queue_.EnqueueAction(actors::MakeAutonomousAction(params));
224 }
225
226 void StopAuto() {
227 LOG(INFO, "Stopping auto mode\n");
228 action_queue_.CancelAllActions();
229 }
230
231 // Whatever these are set to are our default goals to send out after zeroing.
232 double intake_goal_;
233
234 bool was_running_ = false;
235 bool auto_running_ = false;
236
Adam Snaider18f44172016-10-22 15:30:21 -0700237 bool traverse_down_ = false;
238
239 // If we're waiting for the subsystems to zero.
240 bool waiting_for_zero_ = true;
241
242 // If true, the ball was present when the intaking button was pressed.
243 bool saw_ball_when_started_intaking_ = false;
244
245 bool is_intaking_ = false;
246 bool is_outtaking_ = false;
247
248 int recently_intaking_accumulator_ = 0;
249
250 ::aos::common::actions::ActionQueue action_queue_;
251
252 const ::frc971::control_loops::drivetrain::DrivetrainConfig dt_config_;
253
254 ::aos::util::SimpleLogInterval no_drivetrain_status_ =
Austin Schuh61bdc602016-12-04 19:10:10 -0800255 ::aos::util::SimpleLogInterval(::std::chrono::milliseconds(200), WARNING,
Adam Snaider18f44172016-10-22 15:30:21 -0700256 "no drivetrain status");
257};
258
259} // namespace joysticks
260} // namespace input
261} // namespace y2016_bot3
262
263int main() {
264 ::aos::Init(-1);
265 ::y2016_bot3::input::joysticks::Reader reader;
266 reader.Run();
267 ::aos::Cleanup();
268}