blob: 0f781a9536e8a704d92debab75d0905c5d465a5b [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) {
Austin Schuh6182f8d2015-02-14 22:15:04 -0800101 bool last_auto_running = auto_running_;
102 auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
103 data.IsPressed(ControlBit::kEnabled);
104 if (auto_running_ != last_auto_running) {
105 if (auto_running_) {
106 StartAuto();
107 } else {
108 StopAuto();
Brian Silverman20141f92015-01-05 17:39:01 -0800109 }
Austin Schuh6182f8d2015-02-14 22:15:04 -0800110 }
111
112 if (!data.GetControlBit(ControlBit::kAutonomous)) {
Brian Silverman20141f92015-01-05 17:39:01 -0800113 HandleTeleop(data);
114 }
115 }
116
117 void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
118 bool is_control_loop_driving = false;
119 double left_goal = 0.0;
120 double right_goal = 0.0;
121 const double wheel = -data.GetAxis(kSteeringWheel);
122 const double throttle = -data.GetAxis(kDriveThrottle);
123 const double kThrottleGain = 1.0 / 2.5;
124 if (false && (data.IsPressed(kDriveControlLoopEnable1) ||
125 data.IsPressed(kDriveControlLoopEnable2))) {
126 // TODO(austin): Static sucks!
127 static double distance = 0.0;
128 static double angle = 0.0;
129 static double filtered_goal_distance = 0.0;
130 if (data.PosEdge(kDriveControlLoopEnable1) ||
131 data.PosEdge(kDriveControlLoopEnable2)) {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500132 if (drivetrain_queue.position.FetchLatest() &&
133 gyro_reading.FetchLatest()) {
134 distance = (drivetrain_queue.position->left_encoder +
135 drivetrain_queue.position->right_encoder) /
Brian Silverman20141f92015-01-05 17:39:01 -0800136 2.0 -
137 throttle * kThrottleGain / 2.0;
138 angle = gyro_reading->angle;
139 filtered_goal_distance = distance;
140 }
141 }
142 is_control_loop_driving = true;
143
144 // const double gyro_angle = Gyro.View().angle;
145 const double goal_theta = angle - wheel * 0.27;
146 const double goal_distance = distance + throttle * kThrottleGain;
147 const double robot_width = 22.0 / 100.0 * 2.54;
148 const double kMaxVelocity = 0.6;
149 if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
150 filtered_goal_distance += kMaxVelocity * 0.02;
151 } else if (goal_distance <
152 -kMaxVelocity * 0.02 + filtered_goal_distance) {
153 filtered_goal_distance -= kMaxVelocity * 0.02;
154 } else {
155 filtered_goal_distance = goal_distance;
156 }
157 left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
158 right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
159 is_high_gear_ = false;
160
161 LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
162 }
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500163 if (!drivetrain_queue.goal.MakeWithBuilder()
Brian Silverman20141f92015-01-05 17:39:01 -0800164 .steering(wheel)
165 .throttle(throttle)
Brian Silverman93335ae2015-01-26 20:43:39 -0500166 //.highgear(is_high_gear_)
Brian Silverman20141f92015-01-05 17:39:01 -0800167 .quickturn(data.IsPressed(kQuickTurn))
168 .control_loop_driving(is_control_loop_driving)
169 .left_goal(left_goal)
170 .right_goal(right_goal)
171 .left_velocity_goal(0)
172 .right_velocity_goal(0)
173 .Send()) {
174 LOG(WARNING, "sending stick values failed\n");
175 }
176 if (data.PosEdge(kShiftHigh)) {
177 is_high_gear_ = false;
178 }
179 if (data.PosEdge(kShiftLow)) {
180 is_high_gear_ = true;
181 }
182 }
183
184 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
185 HandleDrivetrain(data);
186 if (!data.GetControlBit(ControlBit::kEnabled)) {
187 action_queue_.CancelAllActions();
Austin Schuh6182f8d2015-02-14 22:15:04 -0800188 LOG(DEBUG, "Canceling\n");
Brian Silverman20141f92015-01-05 17:39:01 -0800189 }
190
191 action_queue_.Tick();
192 was_running_ = action_queue_.Running();
193 }
194
195 private:
Austin Schuh6182f8d2015-02-14 22:15:04 -0800196 void StartAuto() {
197 LOG(INFO, "Starting auto mode\n");
198 ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
199 }
200
201 void StopAuto() {
202 LOG(INFO, "Stopping auto mode\n");
203 ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
204 }
205
Brian Silverman20141f92015-01-05 17:39:01 -0800206 bool is_high_gear_;
207 bool was_running_;
208
Austin Schuh6182f8d2015-02-14 22:15:04 -0800209 bool auto_running_ = false;
210
Brian Silverman20141f92015-01-05 17:39:01 -0800211 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}