blob: d43af3131ed620565b5439f68eed670ad06a7ae1 [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 Morshed1b764322016-02-14 20:18:12 +0000130constexpr double kMaxDrivetrainEncoderPulsesPerSecond =
131 5600.0 /* CIM free speed RPM */ * 14.0 / 48.0 /* 1st reduction */ * 28.0 /
132 50.0 /* 2nd reduction (high gear) */ * 30.0 / 44.0 /* encoder gears */ /
133 60.0 /* seconds per minute */ * 256.0 /* CPR */ * 4 /* edges per cycle */;
134
135constexpr double kMaxShooterEncoderPulsesPerSecond =
136 18700.0 /* 775pro free speed RPM */ * 12.0 /
137 18.0 /* motor to encoder reduction */ / 60.0 /* seconds per minute */ *
138 128.0 /* CPR */ * 4 /* edges per cycle */;
139
140double kMaxDrivetrainShooterEncoderPulsesPerSecond = ::std::max(
141 kMaxDrivetrainEncoderPulsesPerSecond, kMaxShooterEncoderPulsesPerSecond);
142
143constexpr double kMaxSuperstructureEncoderPulsesPerSecond =
144 18700.0 /* 775pro free speed RPM */ * 12.0 /
145 56.0 /* motor to encoder reduction */ / 60.0 /* seconds per minute */ *
146 512.0 /* CPR */ * 4 /* index pulse every quarter cycle */;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000147
Comran Morshed225f0b92016-02-10 20:34:27 +0000148// Class to send position messages with sensor readings to our loops.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000149class SensorReader {
150 public:
151 SensorReader() {
152 // Set it to filter out anything shorter than 1/4 of the minimum pulse width
153 // we should ever see.
Comran Morshed1b764322016-02-14 20:18:12 +0000154 drivetrain_shooter_encoder_filter_.SetPeriodNanoSeconds(
155 static_cast<int>(1 / 4.0 /* built-in tolerance */ /
156 kMaxDrivetrainShooterEncoderPulsesPerSecond * 1e9 +
157 0.5));
158 superstructure_encoder_filter_.SetPeriodNanoSeconds(
159 static_cast<int>(1 / 4.0 /* built-in tolerance */ /
160 kMaxSuperstructureEncoderPulsesPerSecond * 1e9 +
161 0.5));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000162 hall_filter_.SetPeriodNanoSeconds(100000);
163 }
164
Comran Morshed225f0b92016-02-10 20:34:27 +0000165 // Drivetrain setters.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000166 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000167 drivetrain_shooter_encoder_filter_.Add(encoder.get());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000168 drivetrain_left_encoder_ = ::std::move(encoder);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000169 }
170
171 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000172 drivetrain_shooter_encoder_filter_.Add(encoder.get());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000173 drivetrain_right_encoder_ = ::std::move(encoder);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000174 }
175
Comran Morshed225f0b92016-02-10 20:34:27 +0000176 void set_drivetrain_left_hall(::std::unique_ptr<AnalogInput> analog) {
177 drivetrain_left_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000178 }
179
Comran Morshed225f0b92016-02-10 20:34:27 +0000180 void set_drivetrain_right_hall(::std::unique_ptr<AnalogInput> analog) {
181 drivetrain_right_hall_ = ::std::move(analog);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000182 }
183
Comran Morshed225f0b92016-02-10 20:34:27 +0000184 // Shooter setters.
185 void set_shooter_left_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000186 drivetrain_shooter_encoder_filter_.Add(encoder.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000187 shooter_left_encoder_ = ::std::move(encoder);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000188 }
189
Comran Morshed225f0b92016-02-10 20:34:27 +0000190 void set_shooter_right_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000191 drivetrain_shooter_encoder_filter_.Add(encoder.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000192 shooter_right_encoder_ = ::std::move(encoder);
193 }
194
195 // Intake setters.
196 void set_intake_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000197 superstructure_encoder_filter_.Add(encoder.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000198 intake_encoder_.set_encoder(::std::move(encoder));
199 }
200
201 void set_intake_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
202 intake_encoder_.set_potentiometer(::std::move(potentiometer));
203 }
204
205 void set_intake_index(::std::unique_ptr<DigitalInput> index) {
Comran Morshed1b764322016-02-14 20:18:12 +0000206 superstructure_encoder_filter_.Add(index.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000207 intake_encoder_.set_index(::std::move(index));
208 }
209
210 // Shoulder setters.
211 void set_shoulder_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000212 superstructure_encoder_filter_.Add(encoder.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000213 shoulder_encoder_.set_encoder(::std::move(encoder));
214 }
215
216 void set_shoulder_potentiometer(
217 ::std::unique_ptr<AnalogInput> potentiometer) {
218 shoulder_encoder_.set_potentiometer(::std::move(potentiometer));
219 }
220
221 void set_shoulder_index(::std::unique_ptr<DigitalInput> index) {
Comran Morshed1b764322016-02-14 20:18:12 +0000222 superstructure_encoder_filter_.Add(index.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000223 shoulder_encoder_.set_index(::std::move(index));
224 }
225
226 // Wrist setters.
227 void set_wrist_encoder(::std::unique_ptr<Encoder> encoder) {
Comran Morshed1b764322016-02-14 20:18:12 +0000228 superstructure_encoder_filter_.Add(encoder.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000229 wrist_encoder_.set_encoder(::std::move(encoder));
230 }
231
232 void set_wrist_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
233 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
234 }
235
236 void set_wrist_index(::std::unique_ptr<DigitalInput> index) {
Comran Morshed1b764322016-02-14 20:18:12 +0000237 superstructure_encoder_filter_.Add(index.get());
Comran Morshed225f0b92016-02-10 20:34:27 +0000238 wrist_encoder_.set_index(::std::move(index));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000239 }
240
Comran Morshed9a9948c2016-01-16 15:58:04 +0000241 // All of the DMA-related set_* calls must be made before this, and it doesn't
242 // hurt to do all of them.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000243
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000244 // TODO(comran): Add 2016 things down below for dma synchronization.
245 void set_dma(::std::unique_ptr<DMA> dma) {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000246 dma_synchronizer_.reset(
247 new ::frc971::wpilib::DMASynchronizer(::std::move(dma)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000248 dma_synchronizer_->Add(&intake_encoder_);
249 dma_synchronizer_->Add(&shoulder_encoder_);
250 dma_synchronizer_->Add(&wrist_encoder_);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000251 }
252
253 void operator()() {
254 ::aos::SetCurrentThreadName("SensorReader");
255
256 my_pid_ = getpid();
257 ds_ =
258#ifdef WPILIB2015
259 DriverStation::GetInstance();
260#else
261 &DriverStation::GetInstance();
262#endif
263
Comran Morshed9a9948c2016-01-16 15:58:04 +0000264 dma_synchronizer_->Start();
265
266 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(5),
267 ::aos::time::Time::InMS(4));
268
269 ::aos::SetCurrentThreadRealtimePriority(40);
270 while (run_) {
271 {
272 const int iterations = phased_loop.SleepUntilNext();
273 if (iterations != 1) {
274 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
275 }
276 }
277 RunIteration();
278 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000279 }
280
281 void RunIteration() {
282 ::frc971::wpilib::SendRobotState(my_pid_, ds_);
283
284 const auto &values = constants::GetValues();
285
286 {
287 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
288 drivetrain_message->right_encoder =
289 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
290 drivetrain_message->left_encoder =
291 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
292 drivetrain_message->left_speed =
293 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
294 drivetrain_message->right_speed =
295 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
296
Comran Morshed9a9948c2016-01-16 15:58:04 +0000297 drivetrain_message->left_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000298 hall_translate(drivetrain_left_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000299 drivetrain_message->right_shifter_position =
Comran Morshed225f0b92016-02-10 20:34:27 +0000300 hall_translate(drivetrain_right_hall_->GetVoltage());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000301
302 drivetrain_message.Send();
303 }
304
Comran Morshed9a9948c2016-01-16 15:58:04 +0000305 dma_synchronizer_->RunIteration();
Comran Morshed225f0b92016-02-10 20:34:27 +0000306
307 {
308 auto shooter_message = shooter_queue.position.MakeMessage();
309 shooter_message->theta_left =
310 shooter_translate(shooter_left_encoder_->GetRaw());
311 shooter_message->theta_right =
312 shooter_translate(shooter_right_encoder_->GetRaw());
313 shooter_message.Send();
314 }
315
316 {
317 auto superstructure_message = superstructure_queue.position.MakeMessage();
318 CopyPotAndIndexPosition(intake_encoder_, &superstructure_message->intake,
319 intake_translate, intake_pot_translate, false,
320 values.intake.pot_offset);
321 CopyPotAndIndexPosition(shoulder_encoder_,
322 &superstructure_message->shoulder,
323 shoulder_translate, shoulder_pot_translate, false,
324 values.shoulder.pot_offset);
325 CopyPotAndIndexPosition(wrist_encoder_, &superstructure_message->wrist,
326 wrist_translate, wrist_pot_translate, false,
327 values.wrist.pot_offset);
328
329 superstructure_message.Send();
330 }
Comran Morshed9a9948c2016-01-16 15:58:04 +0000331 }
332
333 void Quit() { run_ = false; }
334
335 private:
Comran Morshed225f0b92016-02-10 20:34:27 +0000336 void CopyPotAndIndexPosition(
337 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
338 ::frc971::PotAndIndexPosition *position,
339 ::std::function<double(int32_t)> encoder_translate,
340 ::std::function<double(double)> potentiometer_translate, bool reverse,
341 double pot_offset) {
342 const double multiplier = reverse ? -1.0 : 1.0;
343 position->encoder =
344 multiplier * encoder_translate(encoder.polled_encoder_value());
345 position->pot = multiplier * potentiometer_translate(
346 encoder.polled_potentiometer_voltage()) +
347 pot_offset;
348 position->latched_encoder =
349 multiplier * encoder_translate(encoder.last_encoder_value());
350 position->latched_pot =
351 multiplier *
352 potentiometer_translate(encoder.last_potentiometer_voltage()) +
353 pot_offset;
354 position->index_pulses = encoder.index_posedge_count();
355 }
356
Comran Morshed9a9948c2016-01-16 15:58:04 +0000357 int32_t my_pid_;
358 DriverStation *ds_;
359
360 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
361
Comran Morshed225f0b92016-02-10 20:34:27 +0000362 ::std::unique_ptr<Encoder> drivetrain_left_encoder_,
363 drivetrain_right_encoder_;
364 ::std::unique_ptr<AnalogInput> drivetrain_left_hall_, drivetrain_right_hall_;
365
366 ::std::unique_ptr<Encoder> shooter_left_encoder_, shooter_right_encoder_;
Comran Morshedb79c4242016-02-06 18:27:26 +0000367 ::frc971::wpilib::DMAEncoderAndPotentiometer intake_encoder_,
368 shoulder_encoder_, wrist_encoder_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000369
Comran Morshed9a9948c2016-01-16 15:58:04 +0000370 ::std::atomic<bool> run_{true};
Comran Morshed1b764322016-02-14 20:18:12 +0000371 DigitalGlitchFilter drivetrain_shooter_encoder_filter_, hall_filter_,
372 superstructure_encoder_filter_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000373};
374
375class SolenoidWriter {
376 public:
377 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
378 : pcm_(pcm),
Comran Morshedb79c4242016-02-06 18:27:26 +0000379 drivetrain_(".frc971.control_loops.drivetrain_queue.output"),
380 shooter_(".y2016.control_loops.shooter_queue.output") {}
Comran Morshed9a9948c2016-01-16 15:58:04 +0000381
382 void set_pressure_switch(::std::unique_ptr<DigitalInput> pressure_switch) {
383 pressure_switch_ = ::std::move(pressure_switch);
384 }
385
386 void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
387 compressor_relay_ = ::std::move(compressor_relay);
388 }
389
390 void set_drivetrain_left(
391 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
392 drivetrain_left_ = ::std::move(s);
393 }
394
395 void set_drivetrain_right(
396 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
397 drivetrain_right_ = ::std::move(s);
398 }
399
Comran Morshedb79c4242016-02-06 18:27:26 +0000400 void set_shooter_clamp(
401 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
402 shooter_clamp_ = ::std::move(s);
403 }
404
405 void set_shooter_pusher(
406 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
407 shooter_pusher_ = ::std::move(s);
408 }
409
Comran Morshed9a9948c2016-01-16 15:58:04 +0000410 void operator()() {
411 ::aos::SetCurrentThreadName("Solenoids");
412 ::aos::SetCurrentThreadRealtimePriority(27);
413
414 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(20),
415 ::aos::time::Time::InMS(1));
416
417 while (run_) {
418 {
419 const int iterations = phased_loop.SleepUntilNext();
420 if (iterations != 1) {
421 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
422 }
423 }
424
425 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000426 drivetrain_.FetchLatest();
427 if (drivetrain_.get()) {
428 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
429 drivetrain_left_->Set(!drivetrain_->left_high);
430 drivetrain_right_->Set(!drivetrain_->right_high);
431 }
432 }
433
434 {
Comran Morshedb79c4242016-02-06 18:27:26 +0000435 shooter_.FetchLatest();
436 if (shooter_.get()) {
437 LOG_STRUCT(DEBUG, "solenoids", *shooter_);
438 shooter_clamp_->Set(shooter_->clamp_open);
439 shooter_pusher_->Set(shooter_->push_to_shooter);
440 }
441 }
442
443 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000444 ::frc971::wpilib::PneumaticsToLog to_log;
445 {
446 const bool compressor_on = !pressure_switch_->Get();
447 to_log.compressor_on = compressor_on;
448 if (compressor_on) {
449 compressor_relay_->Set(Relay::kForward);
450 } else {
451 compressor_relay_->Set(Relay::kOff);
452 }
453 }
454
455 pcm_->Flush();
456 to_log.read_solenoids = pcm_->GetAll();
457 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
458 }
459 }
460 }
461
462 void Quit() { run_ = false; }
463
464 private:
465 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
466
Comran Morshed225f0b92016-02-10 20:34:27 +0000467 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_left_,
Comran Morshedb79c4242016-02-06 18:27:26 +0000468 drivetrain_right_, shooter_clamp_, shooter_pusher_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000469 ::std::unique_ptr<DigitalInput> pressure_switch_;
470 ::std::unique_ptr<Relay> compressor_relay_;
471
Comran Morshed9a9948c2016-01-16 15:58:04 +0000472 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
Comran Morshed3263e8f2016-02-14 17:55:45 +0000473 ::aos::Queue<::y2016::control_loops::shooter::ShooterQueue::Output> shooter_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000474
475 ::std::atomic<bool> run_{true};
476};
477
478class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
479 public:
Comran Morshed225f0b92016-02-10 20:34:27 +0000480 void set_drivetrain_left_talon(::std::unique_ptr<Talon> t) {
481 drivetrain_left_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000482 }
483
Comran Morshed225f0b92016-02-10 20:34:27 +0000484 void set_drivetrain_right_talon(::std::unique_ptr<Talon> t) {
485 drivetrain_right_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000486 }
487
488 private:
489 virtual void Read() override {
490 ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
491 }
492
493 virtual void Write() override {
494 auto &queue = ::frc971::control_loops::drivetrain_queue.output;
495 LOG_STRUCT(DEBUG, "will output", *queue);
Comran Morshed225f0b92016-02-10 20:34:27 +0000496 drivetrain_left_talon_->Set(-queue->left_voltage / 12.0);
497 drivetrain_right_talon_->Set(queue->right_voltage / 12.0);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000498 }
499
500 virtual void Stop() override {
501 LOG(WARNING, "drivetrain output too old\n");
Comran Morshed225f0b92016-02-10 20:34:27 +0000502 drivetrain_left_talon_->Disable();
503 drivetrain_right_talon_->Disable();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000504 }
505
Comran Morshed225f0b92016-02-10 20:34:27 +0000506 ::std::unique_ptr<Talon> drivetrain_left_talon_, drivetrain_right_talon_;
507};
508
509class ShooterWriter : public ::frc971::wpilib::LoopOutputHandler {
510 public:
511 void set_shooter_left_talon(::std::unique_ptr<Talon> t) {
512 shooter_left_talon_ = ::std::move(t);
513 }
514
515 void set_shooter_right_talon(::std::unique_ptr<Talon> t) {
516 shooter_right_talon_ = ::std::move(t);
517 }
518
519 private:
520 virtual void Read() override {
521 ::y2016::control_loops::shooter::shooter_queue.output.FetchAnother();
522 }
523
524 virtual void Write() override {
525 auto &queue = ::y2016::control_loops::shooter::shooter_queue.output;
526 LOG_STRUCT(DEBUG, "will output", *queue);
527 shooter_left_talon_->Set(queue->voltage_left / 12.0);
528 shooter_right_talon_->Set(queue->voltage_right / 12.0);
529 }
530
531 virtual void Stop() override {
532 LOG(WARNING, "Shooter output too old.\n");
533 shooter_left_talon_->Disable();
534 shooter_right_talon_->Disable();
535 }
536
537 ::std::unique_ptr<Talon> shooter_left_talon_, shooter_right_talon_;
538};
539
540class SuperstructureWriter : public ::frc971::wpilib::LoopOutputHandler {
541 public:
542 void set_intake_talon(::std::unique_ptr<Talon> t) {
543 intake_talon_ = ::std::move(t);
544 }
545
546 void set_shoulder_talon(::std::unique_ptr<Talon> t) {
547 shoulder_talon_ = ::std::move(t);
548 }
549
550 void set_wrist_talon(::std::unique_ptr<Talon> t) {
551 wrist_talon_ = ::std::move(t);
552 }
553
Comran Morshedf4cd7642016-02-15 20:40:49 +0000554 void set_rollers_talon(::std::unique_ptr<Talon> t) {
555 rollers_talon_ = ::std::move(t);
556 }
557
Comran Morshed225f0b92016-02-10 20:34:27 +0000558 private:
559 virtual void Read() override {
560 ::y2016::control_loops::superstructure_queue.output.FetchAnother();
561 }
562
563 virtual void Write() override {
564 auto &queue = ::y2016::control_loops::superstructure_queue.output;
565 LOG_STRUCT(DEBUG, "will output", *queue);
566 intake_talon_->Set(queue->voltage_intake / 12.0);
567 shoulder_talon_->Set(-queue->voltage_shoulder / 12.0);
568 wrist_talon_->Set(queue->voltage_wrist / 12.0);
Comran Morshedf4cd7642016-02-15 20:40:49 +0000569 rollers_talon_->Set(queue->voltage_rollers / 12.0);
Comran Morshed225f0b92016-02-10 20:34:27 +0000570 }
571
572 virtual void Stop() override {
573 LOG(WARNING, "Superstructure output too old.\n");
574 intake_talon_->Disable();
575 shoulder_talon_->Disable();
576 wrist_talon_->Disable();
577 }
578
Comran Morshedf4cd7642016-02-15 20:40:49 +0000579 ::std::unique_ptr<Talon> intake_talon_, shoulder_talon_, wrist_talon_,
580 rollers_talon_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000581};
582
Comran Morshed9a9948c2016-01-16 15:58:04 +0000583class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
584 public:
585 ::std::unique_ptr<Encoder> make_encoder(int index) {
586 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
587 Encoder::k4X);
588 }
589
590 void Run() override {
591 ::aos::InitNRT();
592 ::aos::SetCurrentThreadName("StartCompetition");
593
594 ::frc971::wpilib::JoystickSender joystick_sender;
595 ::std::thread joystick_thread(::std::ref(joystick_sender));
596
597 ::frc971::wpilib::PDPFetcher pdp_fetcher;
598 ::std::thread pdp_fetcher_thread(::std::ref(pdp_fetcher));
599 SensorReader reader;
600
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000601 // TODO(constants): Update these input numbers.
Comran Morshed9a9948c2016-01-16 15:58:04 +0000602 reader.set_drivetrain_left_encoder(make_encoder(0));
603 reader.set_drivetrain_right_encoder(make_encoder(1));
Comran Morshed225f0b92016-02-10 20:34:27 +0000604 reader.set_drivetrain_left_hall(make_unique<AnalogInput>(1));
605 reader.set_drivetrain_right_hall(make_unique<AnalogInput>(2));
606
607 reader.set_shooter_left_encoder(make_encoder(0));
608 reader.set_shooter_right_encoder(make_encoder(0));
609
610 reader.set_intake_encoder(make_encoder(0));
611 reader.set_intake_index(make_unique<DigitalInput>(0));
612 reader.set_intake_potentiometer(make_unique<AnalogInput>(0));
613
614 reader.set_shoulder_encoder(make_encoder(0));
615 reader.set_shoulder_index(make_unique<DigitalInput>(0));
616 reader.set_shoulder_potentiometer(make_unique<AnalogInput>(0));
617
618 reader.set_wrist_encoder(make_encoder(0));
619 reader.set_wrist_index(make_unique<DigitalInput>(0));
620 reader.set_wrist_potentiometer(make_unique<AnalogInput>(0));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000621
Comran Morshed9a9948c2016-01-16 15:58:04 +0000622 reader.set_dma(make_unique<DMA>());
623 ::std::thread reader_thread(::std::ref(reader));
624
625 ::frc971::wpilib::GyroSender gyro_sender;
626 ::std::thread gyro_thread(::std::ref(gyro_sender));
627
628 DrivetrainWriter drivetrain_writer;
Comran Morshed225f0b92016-02-10 20:34:27 +0000629 drivetrain_writer.set_drivetrain_left_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000630 ::std::unique_ptr<Talon>(new Talon(5)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000631 drivetrain_writer.set_drivetrain_right_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000632 ::std::unique_ptr<Talon>(new Talon(2)));
633 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
634
Comran Morshed225f0b92016-02-10 20:34:27 +0000635 ShooterWriter shooter_writer;
636 shooter_writer.set_shooter_left_talon(
637 ::std::unique_ptr<Talon>(new Talon(0)));
638 shooter_writer.set_shooter_right_talon(
639 ::std::unique_ptr<Talon>(new Talon(0)));
640 ::std::thread shooter_writer_thread(::std::ref(shooter_writer));
641
642 SuperstructureWriter superstructure_writer;
643 superstructure_writer.set_intake_talon(
644 ::std::unique_ptr<Talon>(new Talon(0)));
645 superstructure_writer.set_shoulder_talon(
646 ::std::unique_ptr<Talon>(new Talon(0)));
647 superstructure_writer.set_wrist_talon(
648 ::std::unique_ptr<Talon>(new Talon(0)));
Comran Morshedf4cd7642016-02-15 20:40:49 +0000649 superstructure_writer.set_rollers_talon(
650 ::std::unique_ptr<Talon>(new Talon(0)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000651 ::std::thread superstructure_writer_thread(
652 ::std::ref(superstructure_writer));
653
Comran Morshed9a9948c2016-01-16 15:58:04 +0000654 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
655 new ::frc971::wpilib::BufferedPcm());
656 SolenoidWriter solenoid_writer(pcm);
657 solenoid_writer.set_drivetrain_left(pcm->MakeSolenoid(6));
658 solenoid_writer.set_drivetrain_right(pcm->MakeSolenoid(7));
Comran Morshedb79c4242016-02-06 18:27:26 +0000659 solenoid_writer.set_shooter_clamp(pcm->MakeSolenoid(6));
660 solenoid_writer.set_shooter_pusher(pcm->MakeSolenoid(7));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000661
662 solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(25));
663 solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
664 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
665
666 // Wait forever. Not much else to do...
667 while (true) {
668 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
669 if (r != 0) {
670 PLOG(WARNING, "infinite select failed");
671 } else {
672 PLOG(WARNING, "infinite select succeeded??\n");
673 }
674 }
675
676 LOG(ERROR, "Exiting WPILibRobot\n");
677
678 joystick_sender.Quit();
679 joystick_thread.join();
680 pdp_fetcher.Quit();
681 pdp_fetcher_thread.join();
682 reader.Quit();
683 reader_thread.join();
684 gyro_sender.Quit();
685 gyro_thread.join();
686
687 drivetrain_writer.Quit();
688 drivetrain_writer_thread.join();
Comran Morshed225f0b92016-02-10 20:34:27 +0000689 shooter_writer.Quit();
690 shooter_writer_thread.join();
691 superstructure_writer.Quit();
692 superstructure_writer_thread.join();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000693 solenoid_writer.Quit();
694 solenoid_thread.join();
695
696 ::aos::Cleanup();
697 }
698};
699
700} // namespace wpilib
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000701} // namespace y2016
Comran Morshed9a9948c2016-01-16 15:58:04 +0000702
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000703AOS_ROBOT_CLASS(::y2016::wpilib::WPILibRobot);