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