blob: c96734cdb62b43d3b8ae833bce701f69c2624094 [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
19using ::frc971::control_loops::drivetrain;
20using ::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 {
114 auto goal = drivetrain.goal.MakeMessage();
115 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)) {
144 if (drivetrain.position.FetchLatest() && gyro_reading.FetchLatest()) {
145 distance = (drivetrain.position->left_encoder +
146 drivetrain.position->right_encoder) /
147 2.0 -
148 throttle * kThrottleGain / 2.0;
149 angle = gyro_reading->angle;
150 filtered_goal_distance = distance;
151 }
152 }
153 is_control_loop_driving = true;
154
155 // const double gyro_angle = Gyro.View().angle;
156 const double goal_theta = angle - wheel * 0.27;
157 const double goal_distance = distance + throttle * kThrottleGain;
158 const double robot_width = 22.0 / 100.0 * 2.54;
159 const double kMaxVelocity = 0.6;
160 if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
161 filtered_goal_distance += kMaxVelocity * 0.02;
162 } else if (goal_distance <
163 -kMaxVelocity * 0.02 + filtered_goal_distance) {
164 filtered_goal_distance -= kMaxVelocity * 0.02;
165 } else {
166 filtered_goal_distance = goal_distance;
167 }
168 left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
169 right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
170 is_high_gear_ = false;
171
172 LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
173 }
174 if (!drivetrain.goal.MakeWithBuilder()
175 .steering(wheel)
176 .throttle(throttle)
177 .highgear(is_high_gear_)
178 .quickturn(data.IsPressed(kQuickTurn))
179 .control_loop_driving(is_control_loop_driving)
180 .left_goal(left_goal)
181 .right_goal(right_goal)
182 .left_velocity_goal(0)
183 .right_velocity_goal(0)
184 .Send()) {
185 LOG(WARNING, "sending stick values failed\n");
186 }
187 if (data.PosEdge(kShiftHigh)) {
188 is_high_gear_ = false;
189 }
190 if (data.PosEdge(kShiftLow)) {
191 is_high_gear_ = true;
192 }
193 }
194
195 void HandleTeleop(const ::aos::input::driver_station::Data &data) {
196 HandleDrivetrain(data);
197 if (!data.GetControlBit(ControlBit::kEnabled)) {
198 action_queue_.CancelAllActions();
199 LOG(DEBUG, "Canceling\n");
200 }
201
202 action_queue_.Tick();
203 was_running_ = action_queue_.Running();
204 }
205
206 private:
207 bool is_high_gear_;
208 bool was_running_;
209
210 ActionQueue action_queue_;
211
212 ::aos::util::SimpleLogInterval no_drivetrain_status_ =
213 ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
214 "no drivetrain status");
215};
216
217} // namespace joysticks
218} // namespace input
219} // namespace frc971
220
221int main() {
222 ::aos::Init();
223 ::frc971::input::joysticks::Reader reader;
224 reader.Run();
225 ::aos::Cleanup();
226}