blob: 4eb2e0d7a878474fba914cd5d47f1f6067e0104f [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"
Comran Morshed9a9948c2016-01-16 15:58:04 +000015#include "frc971/wpilib/wpilib_robot_base.h"
16#include "dma.h"
17#ifndef WPILIB2015
18#include "DigitalGlitchFilter.h"
19#endif
20#undef ERROR
21
22#include "aos/common/logging/logging.h"
23#include "aos/common/logging/queue_logging.h"
24#include "aos/common/time.h"
25#include "aos/common/util/log_interval.h"
26#include "aos/common/util/phased_loop.h"
27#include "aos/common/util/wrapping_counter.h"
28#include "aos/common/stl_mutex.h"
29#include "aos/linux_code/init.h"
30#include "aos/common/messages/robot_state.q.h"
31
Comran Morshed225f0b92016-02-10 20:34:27 +000032#include "frc971/control_loops/control_loops.q.h"
Comran Morshed9a9948c2016-01-16 15:58:04 +000033#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Comran Morshedb79c4242016-02-06 18:27:26 +000034#include "y2016/control_loops/shooter/shooter.q.h"
Comran Morshed6c6a0a92016-01-17 12:45:16 +000035#include "y2016/constants.h"
Comran Morshed5bb12112016-02-16 13:48:57 +000036#include "y2016/control_loops/drivetrain/drivetrain_dog_motor_plant.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 *
Austin Schuh9f77fd22016-02-21 02:53:58 -080086 control_loops::drivetrain::kWheelRadius * 2.0 * M_PI;
Comran Morshed9a9948c2016-01-16 15:58:04 +000087}
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 *
Austin Schuh9f77fd22016-02-21 02:53:58 -080092 control_loops::drivetrain::kWheelRadius * 2.0 * M_PI;
Comran Morshed9a9948c2016-01-16 15:58:04 +000093}
94
Comran Morshed225f0b92016-02-10 20:34:27 +000095double shooter_translate(int32_t in) {
Comran Morshed5bb12112016-02-16 13:48:57 +000096 return -static_cast<double>(in) / (128.0 /*cpr*/ * 4.0 /*4x*/) *
Comran Morshed225f0b92016-02-10 20:34:27 +000097 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) {
Austin Schuh9f77fd22016-02-21 02:53:58 -0800101 return static_cast<double>(in) / (512.0 /*cpr*/ * 4.0 /*4x*/) *
Comran Morshed225f0b92016-02-10 20:34:27 +0000102 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 *
Comran Morshed5bb12112016-02-16 13:48:57 +0000117 (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Comran Morshed225f0b92016-02-10 20:34:27 +0000118}
119
120double shoulder_pot_translate(double voltage) {
121 return voltage * constants::Values::kShoulderPotRatio *
Comran Morshed5bb12112016-02-16 13:48:57 +0000122 (3.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Comran Morshed225f0b92016-02-10 20:34:27 +0000123}
124
125double wrist_pot_translate(double voltage) {
126 return voltage * constants::Values::kWristPotRatio *
Comran Morshed5bb12112016-02-16 13:48:57 +0000127 (3.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 =
Austin Schuh9f77fd22016-02-21 02:53:58 -0800289 drivetrain_translate(-drivetrain_right_encoder_->GetRaw());
Comran Morshed9a9948c2016-01-16 15:58:04 +0000290 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 =
Austin Schuh9f77fd22016-02-21 02:53:58 -0800310 shooter_translate(-shooter_left_encoder_->GetRaw());
Comran Morshed225f0b92016-02-10 20:34:27 +0000311 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,
Austin Schuh9f77fd22016-02-21 02:53:58 -0800326 wrist_translate, wrist_pot_translate, true,
Comran Morshed225f0b92016-02-10 20:34:27 +0000327 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
Campbell Crowley1ab5fab2016-02-21 13:39:31 -0800382 void set_compressor(::std::unique_ptr<Compressor> compressor) {
383 compressor_ = ::std::move(compressor);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000384 }
385
386 void set_drivetrain_left(
387 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
388 drivetrain_left_ = ::std::move(s);
389 }
390
391 void set_drivetrain_right(
392 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
393 drivetrain_right_ = ::std::move(s);
394 }
395
Comran Morshedb79c4242016-02-06 18:27:26 +0000396 void set_shooter_clamp(
397 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
398 shooter_clamp_ = ::std::move(s);
399 }
400
401 void set_shooter_pusher(
402 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
403 shooter_pusher_ = ::std::move(s);
404 }
405
Comran Morshed9a9948c2016-01-16 15:58:04 +0000406 void operator()() {
Campbell Crowley1ab5fab2016-02-21 13:39:31 -0800407 compressor_->Start();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000408 ::aos::SetCurrentThreadName("Solenoids");
409 ::aos::SetCurrentThreadRealtimePriority(27);
410
411 ::aos::time::PhasedLoop phased_loop(::aos::time::Time::InMS(20),
412 ::aos::time::Time::InMS(1));
413
414 while (run_) {
415 {
416 const int iterations = phased_loop.SleepUntilNext();
417 if (iterations != 1) {
418 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
419 }
420 }
421
422 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000423 drivetrain_.FetchLatest();
424 if (drivetrain_.get()) {
425 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
426 drivetrain_left_->Set(!drivetrain_->left_high);
427 drivetrain_right_->Set(!drivetrain_->right_high);
428 }
429 }
430
431 {
Comran Morshedb79c4242016-02-06 18:27:26 +0000432 shooter_.FetchLatest();
433 if (shooter_.get()) {
434 LOG_STRUCT(DEBUG, "solenoids", *shooter_);
435 shooter_clamp_->Set(shooter_->clamp_open);
436 shooter_pusher_->Set(shooter_->push_to_shooter);
437 }
438 }
439
440 {
Comran Morshed9a9948c2016-01-16 15:58:04 +0000441 ::frc971::wpilib::PneumaticsToLog to_log;
442 {
Campbell Crowley1ab5fab2016-02-21 13:39:31 -0800443 to_log.compressor_on = compressor_->Enabled();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000444 }
445
446 pcm_->Flush();
447 to_log.read_solenoids = pcm_->GetAll();
448 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
449 }
450 }
451 }
452
453 void Quit() { run_ = false; }
454
455 private:
456 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
457
Comran Morshed225f0b92016-02-10 20:34:27 +0000458 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_left_,
Comran Morshedb79c4242016-02-06 18:27:26 +0000459 drivetrain_right_, shooter_clamp_, shooter_pusher_;
Campbell Crowley1ab5fab2016-02-21 13:39:31 -0800460 ::std::unique_ptr<Compressor> compressor_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000461
Comran Morshed9a9948c2016-01-16 15:58:04 +0000462 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
Comran Morshed3263e8f2016-02-14 17:55:45 +0000463 ::aos::Queue<::y2016::control_loops::shooter::ShooterQueue::Output> shooter_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000464
465 ::std::atomic<bool> run_{true};
466};
467
468class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
469 public:
Comran Morshed225f0b92016-02-10 20:34:27 +0000470 void set_drivetrain_left_talon(::std::unique_ptr<Talon> t) {
471 drivetrain_left_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000472 }
473
Comran Morshed225f0b92016-02-10 20:34:27 +0000474 void set_drivetrain_right_talon(::std::unique_ptr<Talon> t) {
475 drivetrain_right_talon_ = ::std::move(t);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000476 }
477
478 private:
479 virtual void Read() override {
480 ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
481 }
482
483 virtual void Write() override {
484 auto &queue = ::frc971::control_loops::drivetrain_queue.output;
485 LOG_STRUCT(DEBUG, "will output", *queue);
Comran Morshed225f0b92016-02-10 20:34:27 +0000486 drivetrain_left_talon_->Set(-queue->left_voltage / 12.0);
487 drivetrain_right_talon_->Set(queue->right_voltage / 12.0);
Comran Morshed9a9948c2016-01-16 15:58:04 +0000488 }
489
490 virtual void Stop() override {
491 LOG(WARNING, "drivetrain output too old\n");
Comran Morshed225f0b92016-02-10 20:34:27 +0000492 drivetrain_left_talon_->Disable();
493 drivetrain_right_talon_->Disable();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000494 }
495
Comran Morshed225f0b92016-02-10 20:34:27 +0000496 ::std::unique_ptr<Talon> drivetrain_left_talon_, drivetrain_right_talon_;
497};
498
499class ShooterWriter : public ::frc971::wpilib::LoopOutputHandler {
500 public:
501 void set_shooter_left_talon(::std::unique_ptr<Talon> t) {
502 shooter_left_talon_ = ::std::move(t);
503 }
504
505 void set_shooter_right_talon(::std::unique_ptr<Talon> t) {
506 shooter_right_talon_ = ::std::move(t);
507 }
508
509 private:
510 virtual void Read() override {
511 ::y2016::control_loops::shooter::shooter_queue.output.FetchAnother();
512 }
513
514 virtual void Write() override {
515 auto &queue = ::y2016::control_loops::shooter::shooter_queue.output;
516 LOG_STRUCT(DEBUG, "will output", *queue);
517 shooter_left_talon_->Set(queue->voltage_left / 12.0);
518 shooter_right_talon_->Set(queue->voltage_right / 12.0);
519 }
520
521 virtual void Stop() override {
522 LOG(WARNING, "Shooter output too old.\n");
523 shooter_left_talon_->Disable();
524 shooter_right_talon_->Disable();
525 }
526
527 ::std::unique_ptr<Talon> shooter_left_talon_, shooter_right_talon_;
528};
529
530class SuperstructureWriter : public ::frc971::wpilib::LoopOutputHandler {
531 public:
532 void set_intake_talon(::std::unique_ptr<Talon> t) {
533 intake_talon_ = ::std::move(t);
534 }
535
536 void set_shoulder_talon(::std::unique_ptr<Talon> t) {
537 shoulder_talon_ = ::std::move(t);
538 }
539
540 void set_wrist_talon(::std::unique_ptr<Talon> t) {
541 wrist_talon_ = ::std::move(t);
542 }
543
Comran Morshedf4cd7642016-02-15 20:40:49 +0000544 void set_rollers_talon(::std::unique_ptr<Talon> t) {
545 rollers_talon_ = ::std::move(t);
546 }
547
Comran Morshed225f0b92016-02-10 20:34:27 +0000548 private:
549 virtual void Read() override {
550 ::y2016::control_loops::superstructure_queue.output.FetchAnother();
551 }
552
553 virtual void Write() override {
554 auto &queue = ::y2016::control_loops::superstructure_queue.output;
555 LOG_STRUCT(DEBUG, "will output", *queue);
556 intake_talon_->Set(queue->voltage_intake / 12.0);
557 shoulder_talon_->Set(-queue->voltage_shoulder / 12.0);
558 wrist_talon_->Set(queue->voltage_wrist / 12.0);
Comran Morshedf4cd7642016-02-15 20:40:49 +0000559 rollers_talon_->Set(queue->voltage_rollers / 12.0);
Comran Morshed225f0b92016-02-10 20:34:27 +0000560 }
561
562 virtual void Stop() override {
563 LOG(WARNING, "Superstructure output too old.\n");
564 intake_talon_->Disable();
565 shoulder_talon_->Disable();
566 wrist_talon_->Disable();
567 }
568
Comran Morshedf4cd7642016-02-15 20:40:49 +0000569 ::std::unique_ptr<Talon> intake_talon_, shoulder_talon_, wrist_talon_,
570 rollers_talon_;
Comran Morshed9a9948c2016-01-16 15:58:04 +0000571};
572
Comran Morshed9a9948c2016-01-16 15:58:04 +0000573class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
574 public:
575 ::std::unique_ptr<Encoder> make_encoder(int index) {
576 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
577 Encoder::k4X);
578 }
579
580 void Run() override {
581 ::aos::InitNRT();
582 ::aos::SetCurrentThreadName("StartCompetition");
583
584 ::frc971::wpilib::JoystickSender joystick_sender;
585 ::std::thread joystick_thread(::std::ref(joystick_sender));
586
587 ::frc971::wpilib::PDPFetcher pdp_fetcher;
588 ::std::thread pdp_fetcher_thread(::std::ref(pdp_fetcher));
589 SensorReader reader;
590
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000591 // TODO(constants): Update these input numbers.
Austin Schuh9f77fd22016-02-21 02:53:58 -0800592 reader.set_drivetrain_left_encoder(make_encoder(5));
593 reader.set_drivetrain_right_encoder(make_encoder(6));
594 reader.set_drivetrain_left_hall(make_unique<AnalogInput>(5));
595 reader.set_drivetrain_right_hall(make_unique<AnalogInput>(6));
Comran Morshed225f0b92016-02-10 20:34:27 +0000596
Austin Schuh9f77fd22016-02-21 02:53:58 -0800597 reader.set_shooter_left_encoder(make_encoder(3));
598 reader.set_shooter_right_encoder(make_encoder(4));
Comran Morshed225f0b92016-02-10 20:34:27 +0000599
600 reader.set_intake_encoder(make_encoder(0));
601 reader.set_intake_index(make_unique<DigitalInput>(0));
602 reader.set_intake_potentiometer(make_unique<AnalogInput>(0));
603
Austin Schuh9f77fd22016-02-21 02:53:58 -0800604 reader.set_shoulder_encoder(make_encoder(2));
605 reader.set_shoulder_index(make_unique<DigitalInput>(2));
606 reader.set_shoulder_potentiometer(make_unique<AnalogInput>(2));
Comran Morshed225f0b92016-02-10 20:34:27 +0000607
Austin Schuh9f77fd22016-02-21 02:53:58 -0800608 reader.set_wrist_encoder(make_encoder(1));
609 reader.set_wrist_index(make_unique<DigitalInput>(1));
610 reader.set_wrist_potentiometer(make_unique<AnalogInput>(1));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000611
Comran Morshed9a9948c2016-01-16 15:58:04 +0000612 reader.set_dma(make_unique<DMA>());
613 ::std::thread reader_thread(::std::ref(reader));
614
615 ::frc971::wpilib::GyroSender gyro_sender;
616 ::std::thread gyro_thread(::std::ref(gyro_sender));
617
618 DrivetrainWriter drivetrain_writer;
Comran Morshed225f0b92016-02-10 20:34:27 +0000619 drivetrain_writer.set_drivetrain_left_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000620 ::std::unique_ptr<Talon>(new Talon(5)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000621 drivetrain_writer.set_drivetrain_right_talon(
Comran Morshed9a9948c2016-01-16 15:58:04 +0000622 ::std::unique_ptr<Talon>(new Talon(2)));
623 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
624
Comran Morshed225f0b92016-02-10 20:34:27 +0000625 ShooterWriter shooter_writer;
626 shooter_writer.set_shooter_left_talon(
627 ::std::unique_ptr<Talon>(new Talon(0)));
628 shooter_writer.set_shooter_right_talon(
629 ::std::unique_ptr<Talon>(new Talon(0)));
630 ::std::thread shooter_writer_thread(::std::ref(shooter_writer));
631
632 SuperstructureWriter superstructure_writer;
633 superstructure_writer.set_intake_talon(
634 ::std::unique_ptr<Talon>(new Talon(0)));
635 superstructure_writer.set_shoulder_talon(
636 ::std::unique_ptr<Talon>(new Talon(0)));
637 superstructure_writer.set_wrist_talon(
638 ::std::unique_ptr<Talon>(new Talon(0)));
Comran Morshedf4cd7642016-02-15 20:40:49 +0000639 superstructure_writer.set_rollers_talon(
640 ::std::unique_ptr<Talon>(new Talon(0)));
Comran Morshed225f0b92016-02-10 20:34:27 +0000641 ::std::thread superstructure_writer_thread(
642 ::std::ref(superstructure_writer));
643
Comran Morshed9a9948c2016-01-16 15:58:04 +0000644 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
645 new ::frc971::wpilib::BufferedPcm());
646 SolenoidWriter solenoid_writer(pcm);
647 solenoid_writer.set_drivetrain_left(pcm->MakeSolenoid(6));
648 solenoid_writer.set_drivetrain_right(pcm->MakeSolenoid(7));
Comran Morshedb79c4242016-02-06 18:27:26 +0000649 solenoid_writer.set_shooter_clamp(pcm->MakeSolenoid(6));
650 solenoid_writer.set_shooter_pusher(pcm->MakeSolenoid(7));
Comran Morshed9a9948c2016-01-16 15:58:04 +0000651
Campbell Crowley1ab5fab2016-02-21 13:39:31 -0800652 solenoid_writer.set_compressor(make_unique<Compressor>());
653
Comran Morshed9a9948c2016-01-16 15:58:04 +0000654 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
655
656 // Wait forever. Not much else to do...
657 while (true) {
658 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
659 if (r != 0) {
660 PLOG(WARNING, "infinite select failed");
661 } else {
662 PLOG(WARNING, "infinite select succeeded??\n");
663 }
664 }
665
666 LOG(ERROR, "Exiting WPILibRobot\n");
667
668 joystick_sender.Quit();
669 joystick_thread.join();
670 pdp_fetcher.Quit();
671 pdp_fetcher_thread.join();
672 reader.Quit();
673 reader_thread.join();
674 gyro_sender.Quit();
675 gyro_thread.join();
676
677 drivetrain_writer.Quit();
678 drivetrain_writer_thread.join();
Comran Morshed225f0b92016-02-10 20:34:27 +0000679 shooter_writer.Quit();
680 shooter_writer_thread.join();
681 superstructure_writer.Quit();
682 superstructure_writer_thread.join();
Comran Morshed9a9948c2016-01-16 15:58:04 +0000683 solenoid_writer.Quit();
684 solenoid_thread.join();
685
686 ::aos::Cleanup();
687 }
688};
689
690} // namespace wpilib
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000691} // namespace y2016
Comran Morshed9a9948c2016-01-16 15:58:04 +0000692
Comran Morshed6c6a0a92016-01-17 12:45:16 +0000693AOS_ROBOT_CLASS(::y2016::wpilib::WPILibRobot);