blob: dfe125920ce7e1cecddac28dd6b3d0c89b349169 [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 Morshedb79c4242016-02-06 18:27:26 +000035#include "y2016/control_loops/shooter/shooter.q.h"
Comran Morshed6c6a0a92016-01-17 12:45:16 +000036#include "y2016/constants.h"
Comran Morshed225f0b92016-02-10 20:34:27 +000037#include "y2016/control_loops/shooter/shooter.q.h"
38#include "y2016/control_loops/superstructure/superstructure.q.h"
Comran Morshed9a9948c2016-01-16 15:58:04 +000039
40#include "frc971/wpilib/joystick_sender.h"
41#include "frc971/wpilib/loop_output_handler.h"
42#include "frc971/wpilib/buffered_solenoid.h"
43#include "frc971/wpilib/buffered_pcm.h"
44#include "frc971/wpilib/gyro_sender.h"
45#include "frc971/wpilib/dma_edge_counting.h"
46#include "frc971/wpilib/interrupt_edge_counting.h"
47#include "frc971/wpilib/encoder_and_potentiometer.h"
48#include "frc971/wpilib/logging.q.h"
49#include "frc971/wpilib/wpilib_interface.h"
50#include "frc971/wpilib/pdp_fetcher.h"
51
52#ifndef M_PI
53#define M_PI 3.14159265358979323846
54#endif
55
56using ::frc971::control_loops::drivetrain_queue;
Comran Morshed225f0b92016-02-10 20:34:27 +000057using ::y2016::control_loops::shooter::shooter_queue;
58using ::y2016::control_loops::superstructure_queue;
Comran Morshed9a9948c2016-01-16 15:58:04 +000059
Comran Morshed6c6a0a92016-01-17 12:45:16 +000060namespace y2016 {
Comran Morshed9a9948c2016-01-16 15:58:04 +000061namespace wpilib {
62
63// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
64// DMA stuff and then removing the * 2.0 in *_translate.
65// The low bit is direction.
66
67// TODO(brian): Replace this with ::std::make_unique once all our toolchains
68// have support.
69template <class T, class... U>
70std::unique_ptr<T> make_unique(U &&... u) {
71 return std::unique_ptr<T>(new T(std::forward<U>(u)...));
72}
73
Comran Morshed225f0b92016-02-10 20:34:27 +000074// Translates for the sensor values to convert raw index pulses into something
75// with proper units.
76
77// TODO(comran): Template these methods since there is a lot of repetition here.
78double hall_translate(double in) {
79 // Turn voltage from our 3-state halls into a ratio that the loop can use.
80 return in / 5.0;
81}
82
Comran Morshed9a9948c2016-01-16 15:58:04 +000083double drivetrain_translate(int32_t in) {
Comran Morshed6c6a0a92016-01-17 12:45:16 +000084 return -static_cast<double>(in) / (256.0 /*cpr*/ * 4.0 /*4x*/) *
Comran Morshed225f0b92016-02-10 20:34:27 +000085 constants::Values::kDrivetrainEncoderRatio *
Comran Morshed9a9948c2016-01-16 15:58:04 +000086 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
87}
88
89double drivetrain_velocity_translate(double in) {
90 return (1.0 / in) / 256.0 /*cpr*/ *
Comran Morshed225f0b92016-02-10 20:34:27 +000091 constants::Values::kDrivetrainEncoderRatio *
Comran Morshed9a9948c2016-01-16 15:58:04 +000092 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
93}
94
Comran Morshed225f0b92016-02-10 20:34:27 +000095double shooter_translate(int32_t in) {
96 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
97 constants::Values::kShooterEncoderRatio * (2 * M_PI /*radians*/);
98}
Comran Morshed9a9948c2016-01-16 15:58:04 +000099
Comran Morshed225f0b92016-02-10 20:34:27 +0000100double intake_translate(int32_t in) {
101 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
102 constants::Values::kIntakeEncoderRatio * (2 * M_PI /*radians*/);
103}
104
105double shoulder_translate(int32_t in) {
106 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
107 constants::Values::kShoulderEncoderRatio * (2 * M_PI /*radians*/);
108}
109
110double wrist_translate(int32_t in) {
111 return -static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
112 constants::Values::kWristEncoderRatio * (2 * M_PI /*radians*/);
113}
114
115double intake_pot_translate(double voltage) {
116 return voltage * constants::Values::kIntakePotRatio *
117 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
118}
119
120double shoulder_pot_translate(double voltage) {
121 return voltage * constants::Values::kShoulderPotRatio *
122 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
123}
124
125double wrist_pot_translate(double voltage) {
126 return voltage * constants::Values::kWristPotRatio *
127 (5.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000128}
129
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000130// TODO(constants): Update.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000131static const double kMaximumEncoderPulsesPerSecond =
132 5600.0 /* free speed RPM */ * 14.0 / 48.0 /* bottom gear reduction */ *
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000133 18.0 / 32.0 /* big belt reduction */ * 18.0 /
134 66.0 /* top gear reduction */ * 48.0 / 18.0 /* encoder gears */ /
Comran Morshed9a9948c2016-01-16 15:58:04 +0000135 60.0 /* seconds / minute */ * 256.0 /* CPR */;
136
Comran Morshed225f0b92016-02-10 20:34:27 +0000137// Class to send position messages with sensor readings to our loops.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000138class SensorReader {
139 public:
140 SensorReader() {
141 // Set it to filter out anything shorter than 1/4 of the minimum pulse width
142 // we should ever see.
143 encoder_filter_.SetPeriodNanoSeconds(
144 static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
145 hall_filter_.SetPeriodNanoSeconds(100000);
146 }
147
Comran Morshed225f0b92016-02-10 20:34:27 +0000148 // Drivetrain setters.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000149 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
150 drivetrain_left_encoder_ = ::std::move(encoder);
151 drivetrain_left_encoder_->SetMaxPeriod(0.005);
152 }
153
154 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
155 drivetrain_right_encoder_ = ::std::move(encoder);
156 drivetrain_right_encoder_->SetMaxPeriod(0.005);
157 }
158
Comran Morshed225f0b92016-02-10 20:34:27 +0000159 void set_drivetrain_left_hall(::std::unique_ptr<AnalogInput> analog) {
160 drivetrain_left_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000161 }
162
Comran Morshed225f0b92016-02-10 20:34:27 +0000163 void set_drivetrain_right_hall(::std::unique_ptr<AnalogInput> analog) {
164 drivetrain_right_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000165 }
166
Comran Morshed225f0b92016-02-10 20:34:27 +0000167 // Shooter setters.
168 void set_shooter_left_encoder(::std::unique_ptr<Encoder> encoder) {
169 encoder_filter_.Add(encoder.get());
170 shooter_left_encoder_ = ::std::move(encoder);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000171 }
172
Comran Morshed225f0b92016-02-10 20:34:27 +0000173 void set_shooter_right_encoder(::std::unique_ptr<Encoder> encoder) {
174 encoder_filter_.Add(encoder.get());
175 shooter_right_encoder_ = ::std::move(encoder);
176 }
177
178 // Intake setters.
179 void set_intake_encoder(::std::unique_ptr<Encoder> encoder) {
180 encoder_filter_.Add(encoder.get());
181 intake_encoder_.set_encoder(::std::move(encoder));
182 }
183
184 void set_intake_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
185 intake_encoder_.set_potentiometer(::std::move(potentiometer));
186 }
187
188 void set_intake_index(::std::unique_ptr<DigitalInput> index) {
189 encoder_filter_.Add(index.get());
190 intake_encoder_.set_index(::std::move(index));
191 }
192
193 // Shoulder setters.
194 void set_shoulder_encoder(::std::unique_ptr<Encoder> encoder) {
195 encoder_filter_.Add(encoder.get());
196 shoulder_encoder_.set_encoder(::std::move(encoder));
197 }
198
199 void set_shoulder_potentiometer(
200 ::std::unique_ptr<AnalogInput> potentiometer) {
201 shoulder_encoder_.set_potentiometer(::std::move(potentiometer));
202 }
203
204 void set_shoulder_index(::std::unique_ptr<DigitalInput> index) {
205 encoder_filter_.Add(index.get());
206 shoulder_encoder_.set_index(::std::move(index));
207 }
208
209 // Wrist setters.
210 void set_wrist_encoder(::std::unique_ptr<Encoder> encoder) {
211 encoder_filter_.Add(encoder.get());
212 wrist_encoder_.set_encoder(::std::move(encoder));
213 }
214
215 void set_wrist_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
216 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
217 }
218
219 void set_wrist_index(::std::unique_ptr<DigitalInput> index) {
220 encoder_filter_.Add(index.get());
221 wrist_encoder_.set_index(::std::move(index));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000222 }
223
Comran Morshed9a9948c2016-01-16 15:58:04 +0000224 // All of the DMA-related set_* calls must be made before this, and it doesn't
225 // hurt to do all of them.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000226
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000227 // TODO(comran): Add 2016 things down below for dma synchronization.
228 void set_dma(::std::unique_ptr<DMA> dma) {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000229 dma_synchronizer_.reset(
230 new ::frc971::wpilib::DMASynchronizer(::std::move(dma)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000231 dma_synchronizer_->Add(&intake_encoder_);
232 dma_synchronizer_->Add(&shoulder_encoder_);
233 dma_synchronizer_->Add(&wrist_encoder_);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000234 }
235
236 void operator()() {
237 ::aos::SetCurrentThreadName("SensorReader");
238
239 my_pid_ = getpid();
240 ds_ =
241#ifdef WPILIB2015
242 DriverStation::GetInstance();
243#else
244 &DriverStation::GetInstance();
245#endif
246
Comran Morshed9a9948c2016-01-16 15:58:04 +0000247 dma_synchronizer_->Start();
248
249 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
250 ::aos::time::Time::InMS(4));
251
252 ::aos::SetCurrentThreadRealtimePriority(40);
253 while (run_) {
254 {
255 const int iterations = phased_loop.SleepUntilNext();
256 if (iterations != 1) {
257 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
258 }
259 }
260 RunIteration();
261 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000262 }
263
264 void RunIteration() {
265 ::frc971::wpilib::SendRobotState(my_pid_, ds_);
266
267 const auto &values = constants::GetValues();
268
269 {
270 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
271 drivetrain_message->right_encoder =
272 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
273 drivetrain_message->left_encoder =
274 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
275 drivetrain_message->left_speed =
276 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
277 drivetrain_message->right_speed =
278 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
279
Comran Morshed9a9948c2016-01-16 15:58:04 +0000280 drivetrain_message->left_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000281 hall_translate(drivetrain_left_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000282 drivetrain_message->right_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000283 hall_translate(drivetrain_right_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000284
285 drivetrain_message.Send();
286 }
287
Comran Morshed9a9948c2016-01-16 15:58:04 +0000288 dma_synchronizer_->RunIteration();
Comran Morshed225f0b92016-02-10 20:34:27 +0000289
290 {
291 auto shooter_message = shooter_queue.position.MakeMessage();
292 shooter_message->theta_left =
293 shooter_translate(shooter_left_encoder_->GetRaw());
294 shooter_message->theta_right =
295 shooter_translate(shooter_right_encoder_->GetRaw());
296 shooter_message.Send();
297 }
298
299 {
300 auto superstructure_message = superstructure_queue.position.MakeMessage();
301 CopyPotAndIndexPosition(intake_encoder_, &superstructure_message->intake,
302 intake_translate, intake_pot_translate, false,
303 values.intake.pot_offset);
304 CopyPotAndIndexPosition(shoulder_encoder_,
305 &superstructure_message->shoulder,
306 shoulder_translate, shoulder_pot_translate, false,
307 values.shoulder.pot_offset);
308 CopyPotAndIndexPosition(wrist_encoder_, &superstructure_message->wrist,
309 wrist_translate, wrist_pot_translate, false,
310 values.wrist.pot_offset);
311
312 superstructure_message.Send();
313 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000314 }
315
316 void Quit() { run_ = false; }
317
318 private:
Comran Morshed225f0b92016-02-10 20:34:27 +0000319 void CopyPotAndIndexPosition(
320 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
321 ::frc971::PotAndIndexPosition *position,
322 ::std::function<double(int32_t)> encoder_translate,
323 ::std::function<double(double)> potentiometer_translate, bool reverse,
324 double pot_offset) {
325 const double multiplier = reverse ? -1.0 : 1.0;
326 position->encoder =
327 multiplier * encoder_translate(encoder.polled_encoder_value());
328 position->pot = multiplier * potentiometer_translate(
329 encoder.polled_potentiometer_voltage()) +
330 pot_offset;
331 position->latched_encoder =
332 multiplier * encoder_translate(encoder.last_encoder_value());
333 position->latched_pot =
334 multiplier *
335 potentiometer_translate(encoder.last_potentiometer_voltage()) +
336 pot_offset;
337 position->index_pulses = encoder.index_posedge_count();
338 }
339
Comran Morshed9a9948c2016-01-16 15:58:04 +0000340 int32_t my_pid_;
341 DriverStation *ds_;
342
343 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
344
Comran Morshed225f0b92016-02-10 20:34:27 +0000345 ::std::unique_ptr<Encoder> drivetrain_left_encoder_,
346 drivetrain_right_encoder_;
347 ::std::unique_ptr<AnalogInput> drivetrain_left_hall_, drivetrain_right_hall_;
348
349 ::std::unique_ptr<Encoder> shooter_left_encoder_, shooter_right_encoder_;
Comran Morshedb79c4242016-02-06 18:27:26 +0000350 ::frc971::wpilib::DMAEncoderAndPotentiometer intake_encoder_,
351 shoulder_encoder_, wrist_encoder_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000352
Comran Morshed9a9948c2016-01-16 15:58:04 +0000353 ::std::atomic<bool> run_{true};
354 DigitalGlitchFilter encoder_filter_, hall_filter_;
355};
356
357class SolenoidWriter {
358 public:
359 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
360 : pcm_(pcm),
Comran Morshedb79c4242016-02-06 18:27:26 +0000361 drivetrain_(".frc971.control_loops.drivetrain_queue.output"),
362 shooter_(".y2016.control_loops.shooter_queue.output") {}
Comran Morshed9a9948c2016-01-16 15:58:04 +0000363
364 void set_pressure_switch(::std::unique_ptr<DigitalInput> pressure_switch) {
365 pressure_switch_ = ::std::move(pressure_switch);
366 }
367
368 void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
369 compressor_relay_ = ::std::move(compressor_relay);
370 }
371
372 void set_drivetrain_left(
373 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
374 drivetrain_left_ = ::std::move(s);
375 }
376
377 void set_drivetrain_right(
378 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
379 drivetrain_right_ = ::std::move(s);
380 }
381
Comran Morshedb79c4242016-02-06 18:27:26 +0000382 void set_shooter_clamp(
383 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
384 shooter_clamp_ = ::std::move(s);
385 }
386
387 void set_shooter_pusher(
388 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
389 shooter_pusher_ = ::std::move(s);
390 }
391
Comran Morshed9a9948c2016-01-16 15:58:04 +0000392 void operator()() {
393 ::aos::SetCurrentThreadName("Solenoids");
394 ::aos::SetCurrentThreadRealtimePriority(27);
395
396 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(20),
397 ::aos::time::Time::InMS(1));
398
399 while (run_) {
400 {
401 const int iterations = phased_loop.SleepUntilNext();
402 if (iterations != 1) {
403 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
404 }
405 }
406
407 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000408 drivetrain_.FetchLatest();
409 if (drivetrain_.get()) {
410 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
411 drivetrain_left_->Set(!drivetrain_->left_high);
412 drivetrain_right_->Set(!drivetrain_->right_high);
413 }
414 }
415
416 {
Comran Morshedb79c4242016-02-06 18:27:26 +0000417 shooter_.FetchLatest();
418 if (shooter_.get()) {
419 LOG_STRUCT(DEBUG, "solenoids", *shooter_);
420 shooter_clamp_->Set(shooter_->clamp_open);
421 shooter_pusher_->Set(shooter_->push_to_shooter);
422 }
423 }
424
425 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000426 ::frc971::wpilib::PneumaticsToLog to_log;
427 {
428 const bool compressor_on = !pressure_switch_->Get();
429 to_log.compressor_on = compressor_on;
430 if (compressor_on) {
431 compressor_relay_->Set(Relay::kForward);
432 } else {
433 compressor_relay_->Set(Relay::kOff);
434 }
435 }
436
437 pcm_->Flush();
438 to_log.read_solenoids = pcm_->GetAll();
439 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
440 }
441 }
442 }
443
444 void Quit() { run_ = false; }
445
446 private:
447 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
448
Comran Morshed225f0b92016-02-10 20:34:27 +0000449 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_left_,
Comran Morshedb79c4242016-02-06 18:27:26 +0000450 drivetrain_right_, shooter_clamp_, shooter_pusher_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000451 ::std::unique_ptr<DigitalInput> pressure_switch_;
452 ::std::unique_ptr<Relay> compressor_relay_;
453
Comran Morshed9a9948c2016-01-16 15:58:04 +0000454 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
Comran Morshed3263e8f2016-02-14 17:55:45 +0000455 ::aos::Queue<::y2016::control_loops::shooter::ShooterQueue::Output> shooter_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000456
457 ::std::atomic<bool> run_{true};
458};
459
460class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
461 public:
Comran Morshed225f0b92016-02-10 20:34:27 +0000462 void set_drivetrain_left_talon(::std::unique_ptr<Talon> t) {
463 drivetrain_left_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000464 }
465
Comran Morshed225f0b92016-02-10 20:34:27 +0000466 void set_drivetrain_right_talon(::std::unique_ptr<Talon> t) {
467 drivetrain_right_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000468 }
469
470 private:
471 virtual void Read() override {
472 ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
473 }
474
475 virtual void Write() override {
476 auto &queue = ::frc971::control_loops::drivetrain_queue.output;
477 LOG_STRUCT(DEBUG, "will output", *queue);
Comran Morshed225f0b92016-02-10 20:34:27 +0000478 drivetrain_left_talon_->Set(-queue->left_voltage / 12.0);
479 drivetrain_right_talon_->Set(queue->right_voltage / 12.0);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000480 }
481
482 virtual void Stop() override {
483 LOG(WARNING, "drivetrain output too old\n");
Comran Morshed225f0b92016-02-10 20:34:27 +0000484 drivetrain_left_talon_->Disable();
485 drivetrain_right_talon_->Disable();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000486 }
487
Comran Morshed225f0b92016-02-10 20:34:27 +0000488 ::std::unique_ptr<Talon> drivetrain_left_talon_, drivetrain_right_talon_;
489};
490
491class ShooterWriter : public ::frc971::wpilib::LoopOutputHandler {
492 public:
493 void set_shooter_left_talon(::std::unique_ptr<Talon> t) {
494 shooter_left_talon_ = ::std::move(t);
495 }
496
497 void set_shooter_right_talon(::std::unique_ptr<Talon> t) {
498 shooter_right_talon_ = ::std::move(t);
499 }
500
501 private:
502 virtual void Read() override {
503 ::y2016::control_loops::shooter::shooter_queue.output.FetchAnother();
504 }
505
506 virtual void Write() override {
507 auto &queue = ::y2016::control_loops::shooter::shooter_queue.output;
508 LOG_STRUCT(DEBUG, "will output", *queue);
509 shooter_left_talon_->Set(queue->voltage_left / 12.0);
510 shooter_right_talon_->Set(queue->voltage_right / 12.0);
511 }
512
513 virtual void Stop() override {
514 LOG(WARNING, "Shooter output too old.\n");
515 shooter_left_talon_->Disable();
516 shooter_right_talon_->Disable();
517 }
518
519 ::std::unique_ptr<Talon> shooter_left_talon_, shooter_right_talon_;
520};
521
522class SuperstructureWriter : public ::frc971::wpilib::LoopOutputHandler {
523 public:
524 void set_intake_talon(::std::unique_ptr<Talon> t) {
525 intake_talon_ = ::std::move(t);
526 }
527
528 void set_shoulder_talon(::std::unique_ptr<Talon> t) {
529 shoulder_talon_ = ::std::move(t);
530 }
531
532 void set_wrist_talon(::std::unique_ptr<Talon> t) {
533 wrist_talon_ = ::std::move(t);
534 }
535
536 private:
537 virtual void Read() override {
538 ::y2016::control_loops::superstructure_queue.output.FetchAnother();
539 }
540
541 virtual void Write() override {
542 auto &queue = ::y2016::control_loops::superstructure_queue.output;
543 LOG_STRUCT(DEBUG, "will output", *queue);
544 intake_talon_->Set(queue->voltage_intake / 12.0);
545 shoulder_talon_->Set(-queue->voltage_shoulder / 12.0);
546 wrist_talon_->Set(queue->voltage_wrist / 12.0);
547 }
548
549 virtual void Stop() override {
550 LOG(WARNING, "Superstructure output too old.\n");
551 intake_talon_->Disable();
552 shoulder_talon_->Disable();
553 wrist_talon_->Disable();
554 }
555
556 ::std::unique_ptr<Talon> intake_talon_, shoulder_talon_, wrist_talon_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000557};
558
Comran Morshed9a9948c2016-01-16 15:58:04 +0000559class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
560 public:
561 ::std::unique_ptr<Encoder> make_encoder(int index) {
562 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
563 Encoder::k4X);
564 }
565
566 void Run() override {
567 ::aos::InitNRT();
568 ::aos::SetCurrentThreadName("StartCompetition");
569
570 ::frc971::wpilib::JoystickSender joystick_sender;
571 ::std::thread joystick_thread(::std::ref(joystick_sender));
572
573 ::frc971::wpilib::PDPFetcher pdp_fetcher;
574 ::std::thread pdp_fetcher_thread(::std::ref(pdp_fetcher));
575 SensorReader reader;
576
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000577 // TODO(constants): Update these input numbers.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000578 reader.set_drivetrain_left_encoder(make_encoder(0));
579 reader.set_drivetrain_right_encoder(make_encoder(1));
Comran Morshed225f0b92016-02-10 20:34:27 +0000580 reader.set_drivetrain_left_hall(make_unique<AnalogInput>(1));
581 reader.set_drivetrain_right_hall(make_unique<AnalogInput>(2));
582
583 reader.set_shooter_left_encoder(make_encoder(0));
584 reader.set_shooter_right_encoder(make_encoder(0));
585
586 reader.set_intake_encoder(make_encoder(0));
587 reader.set_intake_index(make_unique<DigitalInput>(0));
588 reader.set_intake_potentiometer(make_unique<AnalogInput>(0));
589
590 reader.set_shoulder_encoder(make_encoder(0));
591 reader.set_shoulder_index(make_unique<DigitalInput>(0));
592 reader.set_shoulder_potentiometer(make_unique<AnalogInput>(0));
593
594 reader.set_wrist_encoder(make_encoder(0));
595 reader.set_wrist_index(make_unique<DigitalInput>(0));
596 reader.set_wrist_potentiometer(make_unique<AnalogInput>(0));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000597
Comran Morshed9a9948c2016-01-16 15:58:04 +0000598 reader.set_dma(make_unique<DMA>());
599 ::std::thread reader_thread(::std::ref(reader));
600
601 ::frc971::wpilib::GyroSender gyro_sender;
602 ::std::thread gyro_thread(::std::ref(gyro_sender));
603
604 DrivetrainWriter drivetrain_writer;
Comran Morshed225f0b92016-02-10 20:34:27 +0000605 drivetrain_writer.set_drivetrain_left_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000606 ::std::unique_ptr<Talon>(new Talon(5)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000607 drivetrain_writer.set_drivetrain_right_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000608 ::std::unique_ptr<Talon>(new Talon(2)));
609 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
610
Comran Morshed225f0b92016-02-10 20:34:27 +0000611 ShooterWriter shooter_writer;
612 shooter_writer.set_shooter_left_talon(
613 ::std::unique_ptr<Talon>(new Talon(0)));
614 shooter_writer.set_shooter_right_talon(
615 ::std::unique_ptr<Talon>(new Talon(0)));
616 ::std::thread shooter_writer_thread(::std::ref(shooter_writer));
617
618 SuperstructureWriter superstructure_writer;
619 superstructure_writer.set_intake_talon(
620 ::std::unique_ptr<Talon>(new Talon(0)));
621 superstructure_writer.set_shoulder_talon(
622 ::std::unique_ptr<Talon>(new Talon(0)));
623 superstructure_writer.set_wrist_talon(
624 ::std::unique_ptr<Talon>(new Talon(0)));
625 ::std::thread superstructure_writer_thread(
626 ::std::ref(superstructure_writer));
627
Comran Morshed9a9948c2016-01-16 15:58:04 +0000628 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
629 new ::frc971::wpilib::BufferedPcm());
630 SolenoidWriter solenoid_writer(pcm);
631 solenoid_writer.set_drivetrain_left(pcm->MakeSolenoid(6));
632 solenoid_writer.set_drivetrain_right(pcm->MakeSolenoid(7));
Comran Morshedb79c4242016-02-06 18:27:26 +0000633 solenoid_writer.set_shooter_clamp(pcm->MakeSolenoid(6));
634 solenoid_writer.set_shooter_pusher(pcm->MakeSolenoid(7));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000635
636 solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(25));
637 solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
638 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
639
640 // Wait forever. Not much else to do...
641 while (true) {
642 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
643 if (r != 0) {
644 PLOG(WARNING, "infinite select failed");
645 } else {
646 PLOG(WARNING, "infinite select succeeded??\n");
647 }
648 }
649
650 LOG(ERROR, "Exiting WPILibRobot\n");
651
652 joystick_sender.Quit();
653 joystick_thread.join();
654 pdp_fetcher.Quit();
655 pdp_fetcher_thread.join();
656 reader.Quit();
657 reader_thread.join();
658 gyro_sender.Quit();
659 gyro_thread.join();
660
661 drivetrain_writer.Quit();
662 drivetrain_writer_thread.join();
Comran Morshed225f0b92016-02-10 20:34:27 +0000663 shooter_writer.Quit();
664 shooter_writer_thread.join();
665 superstructure_writer.Quit();
666 superstructure_writer_thread.join();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000667 solenoid_writer.Quit();
668 solenoid_thread.join();
669
670 ::aos::Cleanup();
671 }
672};
673
674} // namespace wpilib
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000675} // namespace y2016
Comran Morshed9a9948c2016-01-16 15:58:04 +0000676
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000677AOS_ROBOT_CLASS(::y2016::wpilib::WPILibRobot);