blob: 156f90adf3ac90a0adbc68d88f3148104d295e22 [file] [log] [blame]
Comran Morshed9a9948c2016-01-16 15:58:04 +00001#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"
16#include "frc971/wpilib/wpilib_robot_base.h"
17#include "dma.h"
18#ifndef WPILIB2015
19#include "DigitalGlitchFilter.h"
20#endif
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
Comran Morshed225f0b92016-02-10 20:34:27 +000033#include "frc971/control_loops/control_loops.q.h"
Comran Morshed9a9948c2016-01-16 15:58:04 +000034#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Comran Morshed6c6a0a92016-01-17 12:45:16 +000035#include "y2016/constants.h"
Comran Morshed225f0b92016-02-10 20:34:27 +000036#include "y2016/control_loops/shooter/shooter.q.h"
37#include "y2016/control_loops/superstructure/superstructure.q.h"
Comran Morshed9a9948c2016-01-16 15:58:04 +000038
39#include "frc971/wpilib/joystick_sender.h"
40#include "frc971/wpilib/loop_output_handler.h"
41#include "frc971/wpilib/buffered_solenoid.h"
42#include "frc971/wpilib/buffered_pcm.h"
43#include "frc971/wpilib/gyro_sender.h"
44#include "frc971/wpilib/dma_edge_counting.h"
45#include "frc971/wpilib/interrupt_edge_counting.h"
46#include "frc971/wpilib/encoder_and_potentiometer.h"
47#include "frc971/wpilib/logging.q.h"
48#include "frc971/wpilib/wpilib_interface.h"
49#include "frc971/wpilib/pdp_fetcher.h"
50
51#ifndef M_PI
52#define M_PI 3.14159265358979323846
53#endif
54
55using ::frc971::control_loops::drivetrain_queue;
Comran Morshed225f0b92016-02-10 20:34:27 +000056using ::y2016::control_loops::shooter::shooter_queue;
57using ::y2016::control_loops::superstructure_queue;
Comran Morshed9a9948c2016-01-16 15:58:04 +000058
Comran Morshed6c6a0a92016-01-17 12:45:16 +000059namespace y2016 {
Comran Morshed9a9948c2016-01-16 15:58:04 +000060namespace wpilib {
61
62// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
63// DMA stuff and then removing the * 2.0 in *_translate.
64// The low bit is direction.
65
66// TODO(brian): Replace this with ::std::make_unique once all our toolchains
67// have support.
68template <class T, class... U>
69std::unique_ptr<T> make_unique(U &&... u) {
70 return std::unique_ptr<T>(new T(std::forward<U>(u)...));
71}
72
Comran Morshed225f0b92016-02-10 20:34:27 +000073// Translates for the sensor values to convert raw index pulses into something
74// with proper units.
75
76// TODO(comran): Template these methods since there is a lot of repetition here.
77double hall_translate(double in) {
78 // Turn voltage from our 3-state halls into a ratio that the loop can use.
79 return in / 5.0;
80}
81
Comran Morshed9a9948c2016-01-16 15:58:04 +000082double drivetrain_translate(int32_t in) {
Comran Morshed6c6a0a92016-01-17 12:45:16 +000083 return -static_cast<double>(in) / (256.0 /*cpr*/ * 4.0 /*4x*/) *
Comran Morshed225f0b92016-02-10 20:34:27 +000084 constants::Values::kDrivetrainEncoderRatio *
Comran Morshed9a9948c2016-01-16 15:58:04 +000085 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
86}
87
88double drivetrain_velocity_translate(double in) {
89 return (1.0 / in) / 256.0 /*cpr*/ *
Comran Morshed225f0b92016-02-10 20:34:27 +000090 constants::Values::kDrivetrainEncoderRatio *
Comran Morshed9a9948c2016-01-16 15:58:04 +000091 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
92}
93
Comran Morshed225f0b92016-02-10 20:34:27 +000094double shooter_translate(int32_t in) {
95 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
96 constants::Values::kShooterEncoderRatio * (2 * M_PI /*radians*/);
97}
Comran Morshed9a9948c2016-01-16 15:58:04 +000098
Comran Morshed225f0b92016-02-10 20:34:27 +000099double intake_translate(int32_t in) {
100 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
101 constants::Values::kIntakeEncoderRatio * (2 * M_PI /*radians*/);
102}
103
104double shoulder_translate(int32_t in) {
105 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
106 constants::Values::kShoulderEncoderRatio * (2 * M_PI /*radians*/);
107}
108
109double wrist_translate(int32_t in) {
110 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
111 constants::Values::kWristEncoderRatio * (2 * M_PI /*radians*/);
112}
113
114double intake_pot_translate(double voltage) {
115 return voltage * constants::Values::kIntakePotRatio *
116 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
117}
118
119double shoulder_pot_translate(double voltage) {
120 return voltage * constants::Values::kShoulderPotRatio *
121 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
122}
123
124double wrist_pot_translate(double voltage) {
125 return voltage * constants::Values::kWristPotRatio *
126 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000127}
128
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000129// TODO(constants): Update.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000130static const double kMaximumEncoderPulsesPerSecond =
131 5600.0 /* free speed RPM */ * 14.0 / 48.0 /* bottom gear reduction */ *
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000132 18.0 / 32.0 /* big belt reduction */ * 18.0 /
133 66.0 /* top gear reduction */ * 48.0 / 18.0 /* encoder gears */ /
Comran Morshed9a9948c2016-01-16 15:58:04 +0000134 60.0 /* seconds / minute */ * 256.0 /* CPR */;
135
Comran Morshed225f0b92016-02-10 20:34:27 +0000136// Class to send position messages with sensor readings to our loops.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000137class SensorReader {
138 public:
139 SensorReader() {
140 // Set it to filter out anything shorter than 1/4 of the minimum pulse width
141 // we should ever see.
142 encoder_filter_.SetPeriodNanoSeconds(
143 static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
144 hall_filter_.SetPeriodNanoSeconds(100000);
145 }
146
Comran Morshed225f0b92016-02-10 20:34:27 +0000147 // Drivetrain setters.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000148 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
149 drivetrain_left_encoder_ = ::std::move(encoder);
150 drivetrain_left_encoder_->SetMaxPeriod(0.005);
151 }
152
153 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
154 drivetrain_right_encoder_ = ::std::move(encoder);
155 drivetrain_right_encoder_->SetMaxPeriod(0.005);
156 }
157
Comran Morshed225f0b92016-02-10 20:34:27 +0000158 void set_drivetrain_left_hall(::std::unique_ptr<AnalogInput> analog) {
159 drivetrain_left_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000160 }
161
Comran Morshed225f0b92016-02-10 20:34:27 +0000162 void set_drivetrain_right_hall(::std::unique_ptr<AnalogInput> analog) {
163 drivetrain_right_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000164 }
165
Comran Morshed225f0b92016-02-10 20:34:27 +0000166 // Shooter setters.
167 void set_shooter_left_encoder(::std::unique_ptr<Encoder> encoder) {
168 encoder_filter_.Add(encoder.get());
169 shooter_left_encoder_ = ::std::move(encoder);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000170 }
171
Comran Morshed225f0b92016-02-10 20:34:27 +0000172 void set_shooter_right_encoder(::std::unique_ptr<Encoder> encoder) {
173 encoder_filter_.Add(encoder.get());
174 shooter_right_encoder_ = ::std::move(encoder);
175 }
176
177 // Intake setters.
178 void set_intake_encoder(::std::unique_ptr<Encoder> encoder) {
179 encoder_filter_.Add(encoder.get());
180 intake_encoder_.set_encoder(::std::move(encoder));
181 }
182
183 void set_intake_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
184 intake_encoder_.set_potentiometer(::std::move(potentiometer));
185 }
186
187 void set_intake_index(::std::unique_ptr<DigitalInput> index) {
188 encoder_filter_.Add(index.get());
189 intake_encoder_.set_index(::std::move(index));
190 }
191
192 // Shoulder setters.
193 void set_shoulder_encoder(::std::unique_ptr<Encoder> encoder) {
194 encoder_filter_.Add(encoder.get());
195 shoulder_encoder_.set_encoder(::std::move(encoder));
196 }
197
198 void set_shoulder_potentiometer(
199 ::std::unique_ptr<AnalogInput> potentiometer) {
200 shoulder_encoder_.set_potentiometer(::std::move(potentiometer));
201 }
202
203 void set_shoulder_index(::std::unique_ptr<DigitalInput> index) {
204 encoder_filter_.Add(index.get());
205 shoulder_encoder_.set_index(::std::move(index));
206 }
207
208 // Wrist setters.
209 void set_wrist_encoder(::std::unique_ptr<Encoder> encoder) {
210 encoder_filter_.Add(encoder.get());
211 wrist_encoder_.set_encoder(::std::move(encoder));
212 }
213
214 void set_wrist_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
215 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
216 }
217
218 void set_wrist_index(::std::unique_ptr<DigitalInput> index) {
219 encoder_filter_.Add(index.get());
220 wrist_encoder_.set_index(::std::move(index));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000221 }
222
Comran Morshed9a9948c2016-01-16 15:58:04 +0000223 // All of the DMA-related set_* calls must be made before this, and it doesn't
224 // hurt to do all of them.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000225
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000226 // TODO(comran): Add 2016 things down below for dma synchronization.
227 void set_dma(::std::unique_ptr<DMA> dma) {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000228 dma_synchronizer_.reset(
229 new ::frc971::wpilib::DMASynchronizer(::std::move(dma)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000230 dma_synchronizer_->Add(&intake_encoder_);
231 dma_synchronizer_->Add(&shoulder_encoder_);
232 dma_synchronizer_->Add(&wrist_encoder_);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000233 }
234
235 void operator()() {
236 ::aos::SetCurrentThreadName("SensorReader");
237
238 my_pid_ = getpid();
239 ds_ =
240#ifdef WPILIB2015
241 DriverStation::GetInstance();
242#else
243 &DriverStation::GetInstance();
244#endif
245
Comran Morshed9a9948c2016-01-16 15:58:04 +0000246 dma_synchronizer_->Start();
247
248 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
249 ::aos::time::Time::InMS(4));
250
251 ::aos::SetCurrentThreadRealtimePriority(40);
252 while (run_) {
253 {
254 const int iterations = phased_loop.SleepUntilNext();
255 if (iterations != 1) {
256 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
257 }
258 }
259 RunIteration();
260 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000261 }
262
263 void RunIteration() {
264 ::frc971::wpilib::SendRobotState(my_pid_, ds_);
265
266 const auto &values = constants::GetValues();
267
268 {
269 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
270 drivetrain_message->right_encoder =
271 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
272 drivetrain_message->left_encoder =
273 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
274 drivetrain_message->left_speed =
275 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
276 drivetrain_message->right_speed =
277 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
278
Comran Morshed9a9948c2016-01-16 15:58:04 +0000279 drivetrain_message->left_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000280 hall_translate(drivetrain_left_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000281 drivetrain_message->right_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000282 hall_translate(drivetrain_right_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000283
284 drivetrain_message.Send();
285 }
286
Comran Morshed9a9948c2016-01-16 15:58:04 +0000287 dma_synchronizer_->RunIteration();
Comran Morshed225f0b92016-02-10 20:34:27 +0000288
289 {
290 auto shooter_message = shooter_queue.position.MakeMessage();
291 shooter_message->theta_left =
292 shooter_translate(shooter_left_encoder_->GetRaw());
293 shooter_message->theta_right =
294 shooter_translate(shooter_right_encoder_->GetRaw());
295 shooter_message.Send();
296 }
297
298 {
299 auto superstructure_message = superstructure_queue.position.MakeMessage();
300 CopyPotAndIndexPosition(intake_encoder_, &superstructure_message->intake,
301 intake_translate, intake_pot_translate, false,
302 values.intake.pot_offset);
303 CopyPotAndIndexPosition(shoulder_encoder_,
304 &superstructure_message->shoulder,
305 shoulder_translate, shoulder_pot_translate, false,
306 values.shoulder.pot_offset);
307 CopyPotAndIndexPosition(wrist_encoder_, &superstructure_message->wrist,
308 wrist_translate, wrist_pot_translate, false,
309 values.wrist.pot_offset);
310
311 superstructure_message.Send();
312 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000313 }
314
315 void Quit() { run_ = false; }
316
317 private:
Comran Morshed225f0b92016-02-10 20:34:27 +0000318 void CopyPotAndIndexPosition(
319 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
320 ::frc971::PotAndIndexPosition *position,
321 ::std::function<double(int32_t)> encoder_translate,
322 ::std::function<double(double)> potentiometer_translate, bool reverse,
323 double pot_offset) {
324 const double multiplier = reverse ? -1.0 : 1.0;
325 position->encoder =
326 multiplier * encoder_translate(encoder.polled_encoder_value());
327 position->pot = multiplier * potentiometer_translate(
328 encoder.polled_potentiometer_voltage()) +
329 pot_offset;
330 position->latched_encoder =
331 multiplier * encoder_translate(encoder.last_encoder_value());
332 position->latched_pot =
333 multiplier *
334 potentiometer_translate(encoder.last_potentiometer_voltage()) +
335 pot_offset;
336 position->index_pulses = encoder.index_posedge_count();
337 }
338
Comran Morshed9a9948c2016-01-16 15:58:04 +0000339 int32_t my_pid_;
340 DriverStation *ds_;
341
342 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
343
Comran Morshed225f0b92016-02-10 20:34:27 +0000344 ::std::unique_ptr<Encoder> drivetrain_left_encoder_,
345 drivetrain_right_encoder_;
346 ::std::unique_ptr<AnalogInput> drivetrain_left_hall_, drivetrain_right_hall_;
347
348 ::std::unique_ptr<Encoder> shooter_left_encoder_, shooter_right_encoder_;
349 ::frc971::wpilib::DMAEncoderAndPotentiometer intake_encoder_, shoulder_encoder_, wrist_encoder_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000350
Comran Morshed9a9948c2016-01-16 15:58:04 +0000351 ::std::atomic<bool> run_{true};
352 DigitalGlitchFilter encoder_filter_, hall_filter_;
353};
354
355class SolenoidWriter {
356 public:
357 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
358 : pcm_(pcm),
Comran Morshed9a9948c2016-01-16 15:58:04 +0000359 drivetrain_(".frc971.control_loops.drivetrain_queue.output") {}
360
361 void set_pressure_switch(::std::unique_ptr<DigitalInput> pressure_switch) {
362 pressure_switch_ = ::std::move(pressure_switch);
363 }
364
365 void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
366 compressor_relay_ = ::std::move(compressor_relay);
367 }
368
369 void set_drivetrain_left(
370 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
371 drivetrain_left_ = ::std::move(s);
372 }
373
374 void set_drivetrain_right(
375 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
376 drivetrain_right_ = ::std::move(s);
377 }
378
Comran Morshed9a9948c2016-01-16 15:58:04 +0000379 void operator()() {
380 ::aos::SetCurrentThreadName("Solenoids");
381 ::aos::SetCurrentThreadRealtimePriority(27);
382
383 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(20),
384 ::aos::time::Time::InMS(1));
385
386 while (run_) {
387 {
388 const int iterations = phased_loop.SleepUntilNext();
389 if (iterations != 1) {
390 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
391 }
392 }
393
394 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000395 drivetrain_.FetchLatest();
396 if (drivetrain_.get()) {
397 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
398 drivetrain_left_->Set(!drivetrain_->left_high);
399 drivetrain_right_->Set(!drivetrain_->right_high);
400 }
401 }
402
403 {
404 ::frc971::wpilib::PneumaticsToLog to_log;
405 {
406 const bool compressor_on = !pressure_switch_->Get();
407 to_log.compressor_on = compressor_on;
408 if (compressor_on) {
409 compressor_relay_->Set(Relay::kForward);
410 } else {
411 compressor_relay_->Set(Relay::kOff);
412 }
413 }
414
415 pcm_->Flush();
416 to_log.read_solenoids = pcm_->GetAll();
417 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
418 }
419 }
420 }
421
422 void Quit() { run_ = false; }
423
424 private:
425 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
426
Comran Morshed225f0b92016-02-10 20:34:27 +0000427 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_left_,
428 drivetrain_right_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000429
430 ::std::unique_ptr<DigitalInput> pressure_switch_;
431 ::std::unique_ptr<Relay> compressor_relay_;
432
Comran Morshed9a9948c2016-01-16 15:58:04 +0000433 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
434
435 ::std::atomic<bool> run_{true};
436};
437
438class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
439 public:
Comran Morshed225f0b92016-02-10 20:34:27 +0000440 void set_drivetrain_left_talon(::std::unique_ptr<Talon> t) {
441 drivetrain_left_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000442 }
443
Comran Morshed225f0b92016-02-10 20:34:27 +0000444 void set_drivetrain_right_talon(::std::unique_ptr<Talon> t) {
445 drivetrain_right_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000446 }
447
448 private:
449 virtual void Read() override {
450 ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
451 }
452
453 virtual void Write() override {
454 auto &queue = ::frc971::control_loops::drivetrain_queue.output;
455 LOG_STRUCT(DEBUG, "will output", *queue);
Comran Morshed225f0b92016-02-10 20:34:27 +0000456 drivetrain_left_talon_->Set(-queue->left_voltage / 12.0);
457 drivetrain_right_talon_->Set(queue->right_voltage / 12.0);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000458 }
459
460 virtual void Stop() override {
461 LOG(WARNING, "drivetrain output too old\n");
Comran Morshed225f0b92016-02-10 20:34:27 +0000462 drivetrain_left_talon_->Disable();
463 drivetrain_right_talon_->Disable();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000464 }
465
Comran Morshed225f0b92016-02-10 20:34:27 +0000466 ::std::unique_ptr<Talon> drivetrain_left_talon_, drivetrain_right_talon_;
467};
468
469class ShooterWriter : public ::frc971::wpilib::LoopOutputHandler {
470 public:
471 void set_shooter_left_talon(::std::unique_ptr<Talon> t) {
472 shooter_left_talon_ = ::std::move(t);
473 }
474
475 void set_shooter_right_talon(::std::unique_ptr<Talon> t) {
476 shooter_right_talon_ = ::std::move(t);
477 }
478
479 private:
480 virtual void Read() override {
481 ::y2016::control_loops::shooter::shooter_queue.output.FetchAnother();
482 }
483
484 virtual void Write() override {
485 auto &queue = ::y2016::control_loops::shooter::shooter_queue.output;
486 LOG_STRUCT(DEBUG, "will output", *queue);
487 shooter_left_talon_->Set(queue->voltage_left / 12.0);
488 shooter_right_talon_->Set(queue->voltage_right / 12.0);
489 }
490
491 virtual void Stop() override {
492 LOG(WARNING, "Shooter output too old.\n");
493 shooter_left_talon_->Disable();
494 shooter_right_talon_->Disable();
495 }
496
497 ::std::unique_ptr<Talon> shooter_left_talon_, shooter_right_talon_;
498};
499
500class SuperstructureWriter : public ::frc971::wpilib::LoopOutputHandler {
501 public:
502 void set_intake_talon(::std::unique_ptr<Talon> t) {
503 intake_talon_ = ::std::move(t);
504 }
505
506 void set_shoulder_talon(::std::unique_ptr<Talon> t) {
507 shoulder_talon_ = ::std::move(t);
508 }
509
510 void set_wrist_talon(::std::unique_ptr<Talon> t) {
511 wrist_talon_ = ::std::move(t);
512 }
513
514 private:
515 virtual void Read() override {
516 ::y2016::control_loops::superstructure_queue.output.FetchAnother();
517 }
518
519 virtual void Write() override {
520 auto &queue = ::y2016::control_loops::superstructure_queue.output;
521 LOG_STRUCT(DEBUG, "will output", *queue);
522 intake_talon_->Set(queue->voltage_intake / 12.0);
523 shoulder_talon_->Set(-queue->voltage_shoulder / 12.0);
524 wrist_talon_->Set(queue->voltage_wrist / 12.0);
525 }
526
527 virtual void Stop() override {
528 LOG(WARNING, "Superstructure output too old.\n");
529 intake_talon_->Disable();
530 shoulder_talon_->Disable();
531 wrist_talon_->Disable();
532 }
533
534 ::std::unique_ptr<Talon> intake_talon_, shoulder_talon_, wrist_talon_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000535};
536
Comran Morshed9a9948c2016-01-16 15:58:04 +0000537class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
538 public:
539 ::std::unique_ptr<Encoder> make_encoder(int index) {
540 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
541 Encoder::k4X);
542 }
543
544 void Run() override {
545 ::aos::InitNRT();
546 ::aos::SetCurrentThreadName("StartCompetition");
547
548 ::frc971::wpilib::JoystickSender joystick_sender;
549 ::std::thread joystick_thread(::std::ref(joystick_sender));
550
551 ::frc971::wpilib::PDPFetcher pdp_fetcher;
552 ::std::thread pdp_fetcher_thread(::std::ref(pdp_fetcher));
553 SensorReader reader;
554
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000555 // TODO(constants): Update these input numbers.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000556 reader.set_drivetrain_left_encoder(make_encoder(0));
557 reader.set_drivetrain_right_encoder(make_encoder(1));
Comran Morshed225f0b92016-02-10 20:34:27 +0000558 reader.set_drivetrain_left_hall(make_unique<AnalogInput>(1));
559 reader.set_drivetrain_right_hall(make_unique<AnalogInput>(2));
560
561 reader.set_shooter_left_encoder(make_encoder(0));
562 reader.set_shooter_right_encoder(make_encoder(0));
563
564 reader.set_intake_encoder(make_encoder(0));
565 reader.set_intake_index(make_unique<DigitalInput>(0));
566 reader.set_intake_potentiometer(make_unique<AnalogInput>(0));
567
568 reader.set_shoulder_encoder(make_encoder(0));
569 reader.set_shoulder_index(make_unique<DigitalInput>(0));
570 reader.set_shoulder_potentiometer(make_unique<AnalogInput>(0));
571
572 reader.set_wrist_encoder(make_encoder(0));
573 reader.set_wrist_index(make_unique<DigitalInput>(0));
574 reader.set_wrist_potentiometer(make_unique<AnalogInput>(0));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000575
Comran Morshed9a9948c2016-01-16 15:58:04 +0000576 reader.set_dma(make_unique<DMA>());
577 ::std::thread reader_thread(::std::ref(reader));
578
579 ::frc971::wpilib::GyroSender gyro_sender;
580 ::std::thread gyro_thread(::std::ref(gyro_sender));
581
582 DrivetrainWriter drivetrain_writer;
Comran Morshed225f0b92016-02-10 20:34:27 +0000583 drivetrain_writer.set_drivetrain_left_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000584 ::std::unique_ptr<Talon>(new Talon(5)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000585 drivetrain_writer.set_drivetrain_right_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000586 ::std::unique_ptr<Talon>(new Talon(2)));
587 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
588
Comran Morshed225f0b92016-02-10 20:34:27 +0000589 ShooterWriter shooter_writer;
590 shooter_writer.set_shooter_left_talon(
591 ::std::unique_ptr<Talon>(new Talon(0)));
592 shooter_writer.set_shooter_right_talon(
593 ::std::unique_ptr<Talon>(new Talon(0)));
594 ::std::thread shooter_writer_thread(::std::ref(shooter_writer));
595
596 SuperstructureWriter superstructure_writer;
597 superstructure_writer.set_intake_talon(
598 ::std::unique_ptr<Talon>(new Talon(0)));
599 superstructure_writer.set_shoulder_talon(
600 ::std::unique_ptr<Talon>(new Talon(0)));
601 superstructure_writer.set_wrist_talon(
602 ::std::unique_ptr<Talon>(new Talon(0)));
603 ::std::thread superstructure_writer_thread(
604 ::std::ref(superstructure_writer));
605
Comran Morshed9a9948c2016-01-16 15:58:04 +0000606 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
607 new ::frc971::wpilib::BufferedPcm());
608 SolenoidWriter solenoid_writer(pcm);
609 solenoid_writer.set_drivetrain_left(pcm->MakeSolenoid(6));
610 solenoid_writer.set_drivetrain_right(pcm->MakeSolenoid(7));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000611
612 solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(25));
613 solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
614 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
615
616 // Wait forever. Not much else to do...
617 while (true) {
618 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
619 if (r != 0) {
620 PLOG(WARNING, "infinite select failed");
621 } else {
622 PLOG(WARNING, "infinite select succeeded??\n");
623 }
624 }
625
626 LOG(ERROR, "Exiting WPILibRobot\n");
627
628 joystick_sender.Quit();
629 joystick_thread.join();
630 pdp_fetcher.Quit();
631 pdp_fetcher_thread.join();
632 reader.Quit();
633 reader_thread.join();
634 gyro_sender.Quit();
635 gyro_thread.join();
636
637 drivetrain_writer.Quit();
638 drivetrain_writer_thread.join();
Comran Morshed225f0b92016-02-10 20:34:27 +0000639 shooter_writer.Quit();
640 shooter_writer_thread.join();
641 superstructure_writer.Quit();
642 superstructure_writer_thread.join();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000643 solenoid_writer.Quit();
644 solenoid_thread.join();
645
646 ::aos::Cleanup();
647 }
648};
649
650} // namespace wpilib
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000651} // namespace y2016
Comran Morshed9a9948c2016-01-16 15:58:04 +0000652
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000653AOS_ROBOT_CLASS(::y2016::wpilib::WPILibRobot);