blob: 6702dc4b17869be8da832ee02f0efecba00de8e1 [file] [log] [blame]
Brian Silvermanc71537c2016-01-01 13:43:14 -08001#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <inttypes.h>
5
6#include <thread>
7#include <mutex>
8#include <functional>
9
10#include "Encoder.h"
11#include "Talon.h"
12#include "DriverStation.h"
13#include "AnalogInput.h"
14#include "Compressor.h"
15#include "Relay.h"
Brian Silverman5090c432016-01-02 14:44:26 -080016#include "frc971/wpilib/wpilib_robot_base.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080017#ifndef WPILIB2015
18#include "DigitalGlitchFilter.h"
19#endif
20#include "PowerDistributionPanel.h"
21#undef ERROR
22
23#include "aos/common/logging/logging.h"
24#include "aos/common/logging/queue_logging.h"
25#include "aos/common/time.h"
26#include "aos/common/util/log_interval.h"
27#include "aos/common/util/phased_loop.h"
28#include "aos/common/util/wrapping_counter.h"
29#include "aos/common/stl_mutex.h"
30#include "aos/linux_code/init.h"
31#include "aos/common/messages/robot_state.q.h"
32
33#include "y2012/control_loops/drivetrain/drivetrain.q.h"
34#include "y2012/control_loops/accessories/accessories.q.h"
35
36#include "frc971/wpilib/joystick_sender.h"
37#include "frc971/wpilib/loop_output_handler.h"
38#include "frc971/wpilib/buffered_solenoid.h"
39#include "frc971/wpilib/buffered_pcm.h"
40#include "frc971/wpilib/gyro_sender.h"
41#include "frc971/wpilib/dma_edge_counting.h"
42#include "frc971/wpilib/interrupt_edge_counting.h"
43#include "frc971/wpilib/encoder_and_potentiometer.h"
44#include "frc971/wpilib/logging.q.h"
45#include "frc971/wpilib/wpilib_interface.h"
Brian Silvermanb5b46ca2016-03-13 01:14:17 -050046#include "frc971/wpilib/dma.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080047
48#ifndef M_PI
49#define M_PI 3.14159265358979323846
50#endif
51
52using ::y2012::control_loops::drivetrain_queue;
53using ::y2012::control_loops::accessories_queue;
54
55namespace y2012 {
56namespace wpilib {
57
58template <class T, class... U>
59std::unique_ptr<T> make_unique(U &&... u) {
60 return std::unique_ptr<T>(new T(std::forward<U>(u)...));
61}
62
63double drivetrain_translate(int32_t in) {
64 return -static_cast<double>(in) /
65 (256.0 /*cpr*/ * 4.0 /*4x*/) *
66 1 *
67 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
68}
69
70double drivetrain_velocity_translate(double in) {
71 return (1.0 / in) / 256.0 /*cpr*/ *
72 1 *
73 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
74}
75
76static const double kMaximumEncoderPulsesPerSecond =
77 5600.0 /* free speed RPM */ * 14.0 / 48.0 /* bottom gear reduction */ *
78 18.0 / 32.0 /* big belt reduction */ *
79 18.0 / 66.0 /* top gear reduction */ * 48.0 / 18.0 /* encoder gears */ /
80 60.0 /* seconds / minute */ * 256.0 /* CPR */;
81
82class SensorReader {
83 public:
84 SensorReader() {}
85
86 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
87 drivetrain_left_encoder_ = ::std::move(encoder);
88 drivetrain_left_encoder_->SetMaxPeriod(0.005);
89 }
90
91 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
92 drivetrain_right_encoder_ = ::std::move(encoder);
93 drivetrain_right_encoder_->SetMaxPeriod(0.005);
94 }
95
96 void operator()() {
97 ::aos::SetCurrentThreadName("SensorReader");
98
99 my_pid_ = getpid();
100 ds_ =
101#ifdef WPILIB2015
102 DriverStation::GetInstance();
103#else
104 &DriverStation::GetInstance();
105#endif
Brian Silverman5090c432016-01-02 14:44:26 -0800106
Brian Silvermanc71537c2016-01-01 13:43:14 -0800107 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
108 ::aos::time::Time::InMS(4));
109
Brian Silverman5090c432016-01-02 14:44:26 -0800110 ::aos::SetCurrentThreadRealtimePriority(40);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800111 while (run_) {
112 {
113 const int iterations = phased_loop.SleepUntilNext();
114 if (iterations != 1) {
115 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
116 }
117 }
118 RunIteration();
119 }
120 }
121
122 void RunIteration() {
Brian Silverman39b339e2016-01-03 13:24:22 -0800123 ::frc971::wpilib::SendRobotState(my_pid_, ds_);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800124
125 {
126 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
127 drivetrain_message->right_encoder =
128 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
129 drivetrain_message->left_encoder =
130 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
131 drivetrain_message->left_speed =
132 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
133 drivetrain_message->right_speed =
134 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
135
136 drivetrain_message.Send();
137 }
138
139 accessories_queue.position.MakeMessage().Send();
140 }
141
142 void Quit() { run_ = false; }
143
144 private:
Brian Silvermanc71537c2016-01-01 13:43:14 -0800145 int32_t my_pid_;
146 DriverStation *ds_;
147
148 ::std::unique_ptr<Encoder> drivetrain_left_encoder_;
149 ::std::unique_ptr<Encoder> drivetrain_right_encoder_;
150 ::std::atomic<bool> run_{true};
151};
152
153class SolenoidWriter {
154 public:
155 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
156 : pcm_(pcm),
157 drivetrain_(".y2012.control_loops.drivetrain_queue.output"),
158 accessories_(".y2012.control_loops.accessories_queue.output") {}
159
160 void set_drivetrain_high(
161 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
162 drivetrain_high_ = ::std::move(s);
163 }
164
165 void set_drivetrain_low(
166 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
167 drivetrain_low_ = ::std::move(s);
168 }
169
170 void set_s1(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
171 s1_ = ::std::move(s);
172 }
173
174 void set_s2(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
175 s2_ = ::std::move(s);
176 }
177
178 void set_s3(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
179 s3_ = ::std::move(s);
180 }
181
182 void operator()() {
183 ::aos::SetCurrentThreadName("Solenoids");
Brian Silverman5090c432016-01-02 14:44:26 -0800184 ::aos::SetCurrentThreadRealtimePriority(27);
185
186 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(20),
187 ::aos::time::Time::InMS(1));
Brian Silvermanc71537c2016-01-01 13:43:14 -0800188
189 while (run_) {
Brian Silverman5090c432016-01-02 14:44:26 -0800190 {
191 const int iterations = phased_loop.SleepUntilNext();
192 if (iterations != 1) {
193 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
194 }
195 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800196
197 {
198 accessories_.FetchLatest();
199 if (accessories_.get()) {
200 LOG_STRUCT(DEBUG, "solenoids", *accessories_);
201 s1_->Set(accessories_->solenoids[0]);
202 s2_->Set(accessories_->solenoids[1]);
203 s3_->Set(accessories_->solenoids[2]);
204 }
205 }
206
207 {
208 drivetrain_.FetchLatest();
209 if (drivetrain_.get()) {
210 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
211 const bool high = drivetrain_->left_high || drivetrain_->right_high;
212 drivetrain_high_->Set(high);
213 drivetrain_low_->Set(!high);
214 }
215 }
216
217 {
218 ::frc971::wpilib::PneumaticsToLog to_log;
219 pcm_->Flush();
220 to_log.read_solenoids = pcm_->GetAll();
221 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
222 }
223 }
224 }
225
226 void Quit() { run_ = false; }
227
228 private:
229 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
230
231 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_high_;
232 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_low_;
233 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s1_, s2_, s3_;
234
235 ::std::unique_ptr<Compressor> compressor_;
236
237 ::aos::Queue<::y2012::control_loops::DrivetrainQueue::Output> drivetrain_;
238 ::aos::Queue<::y2012::control_loops::AccessoriesQueue::Message> accessories_;
239
240 ::std::atomic<bool> run_{true};
241};
242
243class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
244 public:
245 void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
246 left_drivetrain_talon_ = ::std::move(t);
247 }
248
249 void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
250 right_drivetrain_talon_ = ::std::move(t);
251 }
252
253 private:
254 virtual void Read() override {
255 ::y2012::control_loops::drivetrain_queue.output.FetchAnother();
256 }
257
258 virtual void Write() override {
259 auto &queue = ::y2012::control_loops::drivetrain_queue.output;
260 LOG_STRUCT(DEBUG, "will output", *queue);
261 left_drivetrain_talon_->Set(-queue->left_voltage / 12.0);
262 right_drivetrain_talon_->Set(queue->right_voltage / 12.0);
263 }
264
265 virtual void Stop() override {
266 LOG(WARNING, "drivetrain output too old\n");
267 left_drivetrain_talon_->Disable();
268 right_drivetrain_talon_->Disable();
269 }
270
271 ::std::unique_ptr<Talon> left_drivetrain_talon_;
272 ::std::unique_ptr<Talon> right_drivetrain_talon_;
273};
274
275class AccessoriesWriter : public ::frc971::wpilib::LoopOutputHandler {
276 public:
277 void set_talon1(::std::unique_ptr<Talon> t) {
278 talon1_ = ::std::move(t);
279 }
280
281 void set_talon2(::std::unique_ptr<Talon> t) {
282 talon2_ = ::std::move(t);
283 }
284
285 private:
286 virtual void Read() override {
287 ::y2012::control_loops::accessories_queue.output.FetchAnother();
288 }
289
290 virtual void Write() override {
291 auto &queue = ::y2012::control_loops::accessories_queue.output;
292 talon1_->Set(queue->sticks[0]);
293 talon2_->Set(queue->sticks[1]);
294 LOG_STRUCT(DEBUG, "will output", *queue);
295 }
296
297 virtual void Stop() override {
298 LOG(WARNING, "shooter output too old\n");
299 talon1_->Disable();
300 talon2_->Disable();
301 }
302
303 ::std::unique_ptr<Talon> talon1_, talon2_;
304};
305
Brian Silverman5090c432016-01-02 14:44:26 -0800306class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800307 public:
308 ::std::unique_ptr<Encoder> make_encoder(int index) {
309 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
310 Encoder::k4X);
311 }
312
Brian Silverman5090c432016-01-02 14:44:26 -0800313 void Run() override {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800314 ::aos::InitNRT();
315 ::aos::SetCurrentThreadName("StartCompetition");
316
317 ::frc971::wpilib::JoystickSender joystick_sender;
318 ::std::thread joystick_thread(::std::ref(joystick_sender));
319
320 SensorReader reader;
321
322 reader.set_drivetrain_left_encoder(make_encoder(0));
323 reader.set_drivetrain_right_encoder(make_encoder(1));
324
325 ::std::thread reader_thread(::std::ref(reader));
326
327 DrivetrainWriter drivetrain_writer;
328 drivetrain_writer.set_left_drivetrain_talon(
329 ::std::unique_ptr<Talon>(new Talon(3)));
330 drivetrain_writer.set_right_drivetrain_talon(
331 ::std::unique_ptr<Talon>(new Talon(4)));
332 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
333
334 ::y2012::wpilib::AccessoriesWriter accessories_writer;
335 accessories_writer.set_talon1(::std::unique_ptr<Talon>(new Talon(5)));
336 accessories_writer.set_talon2(::std::unique_ptr<Talon>(new Talon(6)));
337 ::std::thread accessories_writer_thread(::std::ref(accessories_writer));
338
339 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
340 new ::frc971::wpilib::BufferedPcm());
341 SolenoidWriter solenoid_writer(pcm);
342 solenoid_writer.set_drivetrain_high(pcm->MakeSolenoid(0));
343 solenoid_writer.set_drivetrain_low(pcm->MakeSolenoid(2));
344 solenoid_writer.set_s1(pcm->MakeSolenoid(1));
345 solenoid_writer.set_s2(pcm->MakeSolenoid(3));
346 solenoid_writer.set_s3(pcm->MakeSolenoid(4));
347
348 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
349
350 // Wait forever. Not much else to do...
Brian Silverman5090c432016-01-02 14:44:26 -0800351 while (true) {
352 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
353 if (r != 0) {
354 PLOG(WARNING, "infinite select failed");
355 } else {
356 PLOG(WARNING, "infinite select succeeded??\n");
357 }
358 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800359
360 LOG(ERROR, "Exiting WPILibRobot\n");
361
362 joystick_sender.Quit();
363 joystick_thread.join();
364 reader.Quit();
365 reader_thread.join();
366
367 drivetrain_writer.Quit();
368 drivetrain_writer_thread.join();
369 accessories_writer.Quit();
370 accessories_writer_thread.join();
371
372 ::aos::Cleanup();
373 }
374};
375
376} // namespace wpilib
377} // namespace y2012
378
379
Brian Silverman5090c432016-01-02 14:44:26 -0800380AOS_ROBOT_CLASS(::y2012::wpilib::WPILibRobot);