blob: 5ca4fa1fa7c80e4dacc3033fd7b138a08b6436a1 [file] [log] [blame]
Brian Silverman20141f92015-01-05 17:39:01 -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"
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
13#include "frc971/control_loops/drivetrain/drivetrain.q.h"
14#include "frc971/constants.h"
15#include "frc971/queues/gyro.q.h"
16#include "frc971/autonomous/auto.q.h"
17#include "frc971/actions/action_client.h"
18
Brian Silvermanada5f2c2015-02-01 02:41:14 -050019using ::frc971::control_loops::drivetrain_queue;
Brian Silverman20141f92015-01-05 17:39:01 -080020using ::frc971::sensors::gyro_reading;
21
22using ::aos::input::driver_station::ButtonLocation;
23using ::aos::input::driver_station::JoystickAxis;
24using ::aos::input::driver_station::ControlBit;
25
26namespace frc971 {
27namespace input {
28namespace joysticks {
29
30const ButtonLocation kDriveControlLoopEnable1(1, 7),
31 kDriveControlLoopEnable2(1, 11);
32const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
33const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
34const ButtonLocation kQuickTurn(1, 5);
35
36// A queue which queues Actions and cancels them.
37class ActionQueue {
38 public:
39 // Queues up an action for sending.
40 void QueueAction(::std::unique_ptr<Action> action) {
41 if (current_action_) {
42 LOG(INFO, "Queueing action, canceling prior\n");
43 current_action_->Cancel();
44 next_action_ = ::std::move(action);
45 } else {
46 LOG(INFO, "Queueing action\n");
47 current_action_ = ::std::move(action);
48 current_action_->Start();
49 }
50 }
51
52 // Cancels the current action, and runs the next one when the current one has
53 // finished.
54 void CancelCurrentAction() {
55 LOG(INFO, "Canceling current action\n");
56 if (current_action_) {
57 current_action_->Cancel();
58 }
59 }
60
61 // Cancels all running actions.
62 void CancelAllActions() {
63 LOG(DEBUG, "Cancelling all actions\n");
64 if (current_action_) {
65 current_action_->Cancel();
66 }
67 next_action_.reset();
68 }
69
70 // Runs the next action when the current one is finished running.
71 void Tick() {
72 if (current_action_) {
73 if (!current_action_->Running()) {
74 LOG(INFO, "Action is done.\n");
75 current_action_ = ::std::move(next_action_);
76 if (current_action_) {
77 LOG(INFO, "Running next action\n");
78 current_action_->Start();
79 }
80 }
81 }
82 }
83
84 // Returns true if any action is running or could be running.
85 // For a one cycle faster response, call Tick before running this.
86 bool Running() { return static_cast<bool>(current_action_); }
87
88 private:
89 ::std::unique_ptr<Action> current_action_;
90 ::std::unique_ptr<Action> next_action_;
91};
92
93
94class Reader : public ::aos::input::JoystickInput {
95 public:
96 Reader()
97 : is_high_gear_(false),
98 was_running_(false) {}
99
100 virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
101 if (data.GetControlBit(ControlBit::kAutonomous)) {
102 if (data.PosEdge(ControlBit::kEnabled)){
103 LOG(INFO, "Starting auto mode\n");
104 ::frc971::autonomous::autonomous.MakeWithBuilder()
105 .run_auto(true)
106 .Send();
107 } else if (data.NegEdge(ControlBit::kEnabled)) {
108 LOG(INFO, "Stopping auto mode\n");
109 ::frc971::autonomous::autonomous.MakeWithBuilder()
110 .run_auto(false)
111 .Send();
112 } else if (!data.GetControlBit(ControlBit::kEnabled)) {
113 {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500114 auto goal = drivetrain_queue.goal.MakeMessage();
Brian Silverman20141f92015-01-05 17:39:01 -0800115 goal->Zero();
116 goal->control_loop_driving = false;
117 goal->left_goal = goal->right_goal = 0;
118 goal->left_velocity_goal = goal->right_velocity_goal = 0;
119 if (!goal.Send()) {
120 LOG(WARNING, "sending 0 drivetrain goal failed\n");
121 }
122 }
123 }
124 } else {
125 HandleTeleop(data);
126 }
127 }
128
129 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
130 bool is_control_loop_driving = false;
131 double left_goal = 0.0;
132 double right_goal = 0.0;
133 const double wheel = -data.GetAxis(kSteeringWheel);
134 const double throttle = -data.GetAxis(kDriveThrottle);
135 const double kThrottleGain = 1.0 / 2.5;
136 if (false && (data.IsPressed(kDriveControlLoopEnable1) ||
137 data.IsPressed(kDriveControlLoopEnable2))) {
138 // TODO(austin): Static sucks!
139 static double distance = 0.0;
140 static double angle = 0.0;
141 static double filtered_goal_distance = 0.0;
142 if (data.PosEdge(kDriveControlLoopEnable1) ||
143 data.PosEdge(kDriveControlLoopEnable2)) {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500144 if (drivetrain_queue.position.FetchLatest() &&
145 gyro_reading.FetchLatest()) {
146 distance = (drivetrain_queue.position->left_encoder +
147 drivetrain_queue.position->right_encoder) /
Brian Silverman20141f92015-01-05 17:39:01 -0800148 2.0 -
149 throttle * kThrottleGain / 2.0;
150 angle = gyro_reading->angle;
151 filtered_goal_distance = distance;
152 }
153 }
154 is_control_loop_driving = true;
155
156 // const double gyro_angle = Gyro.View().angle;
157 const double goal_theta = angle - wheel * 0.27;
158 const double goal_distance = distance + throttle * kThrottleGain;
159 const double robot_width = 22.0 / 100.0 * 2.54;
160 const double kMaxVelocity = 0.6;
161 if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
162 filtered_goal_distance += kMaxVelocity * 0.02;
163 } else if (goal_distance <
164 -kMaxVelocity * 0.02 + filtered_goal_distance) {
165 filtered_goal_distance -= kMaxVelocity * 0.02;
166 } else {
167 filtered_goal_distance = goal_distance;
168 }
169 left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
170 right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
171 is_high_gear_ = false;
172
173 LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
174 }
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500175 if (!drivetrain_queue.goal.MakeWithBuilder()
Brian Silverman20141f92015-01-05 17:39:01 -0800176 .steering(wheel)
177 .throttle(throttle)
Brian Silverman93335ae2015-01-26 20:43:39 -0500178 //.highgear(is_high_gear_)
Brian Silverman20141f92015-01-05 17:39:01 -0800179 .quickturn(data.IsPressed(kQuickTurn))
180 .control_loop_driving(is_control_loop_driving)
181 .left_goal(left_goal)
182 .right_goal(right_goal)
183 .left_velocity_goal(0)
184 .right_velocity_goal(0)
185 .Send()) {
186 LOG(WARNING, "sending stick values failed\n");
187 }
188 if (data.PosEdge(kShiftHigh)) {
189 is_high_gear_ = false;
190 }
191 if (data.PosEdge(kShiftLow)) {
192 is_high_gear_ = true;
193 }
194 }
195
196 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
197 HandleDrivetrain(data);
198 if (!data.GetControlBit(ControlBit::kEnabled)) {
199 action_queue_.CancelAllActions();
200 LOG(DEBUG, "Canceling\n");
201 }
202
203 action_queue_.Tick();
204 was_running_ = action_queue_.Running();
205 }
206
207 private:
208 bool is_high_gear_;
209 bool was_running_;
210
211 ActionQueue action_queue_;
212
213 ::aos::util::SimpleLogInterval no_drivetrain_status_ =
214 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
215 "no drivetrain status");
216};
217
218} // namespace joysticks
219} // namespace input
220} // namespace frc971
221
222int main() {
223 ::aos::Init();
224 ::frc971::input::joysticks::Reader reader;
225 reader.Run();
226 ::aos::Cleanup();
227}