blob: d950c021886f6cfd3d55f9f7ead81b1f73ee2f46 [file] [log] [blame]
Austin Schuh010eb812014-10-25 18:06:49 -07001#include <stdio.h>
2#include <string.h>
Austin Schuh010eb812014-10-25 18:06:49 -07003#include <unistd.h>
4#include <inttypes.h>
5
Brian Silvermand8f403a2014-12-13 19:12:04 -05006#include <thread>
7#include <mutex>
8#include <functional>
9
Austin Schuh010eb812014-10-25 18:06:49 -070010#include "aos/common/logging/logging.h"
11#include "aos/common/logging/queue_logging.h"
Austin Schuh010eb812014-10-25 18:06:49 -070012#include "aos/common/time.h"
13#include "aos/common/util/log_interval.h"
14#include "aos/common/util/phased_loop.h"
15#include "aos/common/util/wrapping_counter.h"
Brian Silvermanb073f242014-09-08 16:29:57 -040016#include "aos/common/stl_mutex.h"
Austin Schuh010eb812014-10-25 18:06:49 -070017#include "aos/linux_code/init.h"
Brian Silverman699f0cb2015-02-05 19:45:01 -050018#include "aos/common/messages/robot_state.q.h"
Austin Schuh010eb812014-10-25 18:06:49 -070019
Brian Silverman335c20e2015-01-26 21:47:58 -050020#include "frc971/control_loops/control_loops.q.h"
Austin Schuh010eb812014-10-25 18:06:49 -070021#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Daniel Pettiadf38432015-01-26 17:13:35 -080022#include "frc971/control_loops/fridge/fridge.q.h"
23#include "frc971/control_loops/claw/claw.q.h"
Austin Schuh010eb812014-10-25 18:06:49 -070024
Brian Silvermanda45b6c2014-12-28 11:36:50 -080025#include "frc971/wpilib/hall_effect.h"
26#include "frc971/wpilib/joystick_sender.h"
Brian Silvermand8f403a2014-12-13 19:12:04 -050027#include "frc971/wpilib/loop_output_handler.h"
28#include "frc971/wpilib/buffered_solenoid.h"
29#include "frc971/wpilib/buffered_pcm.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080030#include "frc971/wpilib/gyro_sender.h"
Brian Silvermanff7b3472015-01-26 17:53:04 -050031#include "frc971/wpilib/dma_edge_counting.h"
Brian Silverman70ec7192015-01-26 17:52:40 -050032#include "frc971/wpilib/interrupt_edge_counting.h"
Brian Silverman4da58072015-01-26 20:18:52 -050033#include "frc971/wpilib/encoder_and_potentiometer.h"
Brian Silvermanda45b6c2014-12-28 11:36:50 -080034
Brian Silvermancb77f232014-12-19 21:48:36 -080035#include "Encoder.h"
Brian Silvermancb77f232014-12-19 21:48:36 -080036#include "Talon.h"
37#include "DriverStation.h"
38#include "AnalogInput.h"
Brian Silvermancb77f232014-12-19 21:48:36 -080039#include "Compressor.h"
40#include "RobotBase.h"
Brian Silverman335c20e2015-01-26 21:47:58 -050041#include "dma.h"
Brian Silverman699f0cb2015-02-05 19:45:01 -050042#include "ControllerPower.h"
Austin Schuh010eb812014-10-25 18:06:49 -070043
44#ifndef M_PI
45#define M_PI 3.14159265358979323846
46#endif
47
48using ::aos::util::SimpleLogInterval;
Brian Silvermanada5f2c2015-02-01 02:41:14 -050049using ::frc971::control_loops::drivetrain_queue;
Brian Silverman335c20e2015-01-26 21:47:58 -050050using ::frc971::control_loops::fridge_queue;
51using ::frc971::control_loops::claw_queue;
Austin Schuh010eb812014-10-25 18:06:49 -070052
53namespace frc971 {
Brian Silvermanda45b6c2014-12-28 11:36:50 -080054namespace wpilib {
Austin Schuh010eb812014-10-25 18:06:49 -070055
Austin Schuh010eb812014-10-25 18:06:49 -070056double drivetrain_translate(int32_t in) {
Austin Schuhdb516032014-12-28 00:12:38 -080057 return static_cast<double>(in) /
Daniel Pettiadf38432015-01-26 17:13:35 -080058 (256.0 /*cpr*/ * 4.0 /*4x*/) *
59 (20.0 / 50.0 /*output stage*/) *
Austin Schuhdb516032014-12-28 00:12:38 -080060 // * constants::GetValues().drivetrain_encoder_ratio
Daniel Pettiadf38432015-01-26 17:13:35 -080061 (4 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
62}
63
64double arm_translate(int32_t in) {
65 return static_cast<double>(in) /
66 (512.0 /*cpr*/ * 4.0 /*4x*/) *
67 (14.0 / 17.0 /*output sprockets*/) *
68 (18.0 / 48.0 /*encoder pulleys*/) *
69 (2 * M_PI /*radians*/);
70}
71
Brian Silverman8bca4a92015-02-05 15:19:06 -050072double arm_pot_translate(double voltage) {
73 return voltage /
Daniel Pettiadf38432015-01-26 17:13:35 -080074 (14.0 / 17.0 /*output sprockets*/) *
75 (5.0 /*volts*/ / 5.0 /*turns*/) *
76 (2 * M_PI /*radians*/);
77}
78
79double elevator_translate(int32_t in) {
80 return static_cast<double>(in) /
81 (512.0 /*cpr*/ * 4.0 /*4x*/) *
82 (14.0 / 84.0 /*output stage*/) *
83 (32 * 5 / 2.54 / 10 /*pulley circumference (in)*/);
84}
85
Brian Silverman8bca4a92015-02-05 15:19:06 -050086double elevator_pot_translate(double voltage) {
87 return voltage /
Daniel Pettiadf38432015-01-26 17:13:35 -080088 (32 * 5 / 2.54 / 10 /*pulley circumference (in)*/) *
89 (5.0 /*volts*/ / 5.0 /*turns*/);
90}
91
92double claw_translate(int32_t in) {
93 return static_cast<double>(in) /
94 (512.0 /*cpr*/ * 4.0 /*4x*/) *
95 (16.0 / 72.0 /*output sprockets*/) *
96 (2 * M_PI /*radians*/);
97}
98
Brian Silverman8bca4a92015-02-05 15:19:06 -050099double claw_pot_translate(double voltage) {
100 return voltage /
Daniel Pettiadf38432015-01-26 17:13:35 -0800101 (16.0 / 72.0 /*output sprockets*/) *
102 (5.0 /*volts*/ / 5.0 /*turns*/) *
103 (2 * M_PI /*radians*/);
Austin Schuh010eb812014-10-25 18:06:49 -0700104}
105
Brian Silverman335c20e2015-01-26 21:47:58 -0500106static const double kMaximumEncoderPulsesPerSecond =
107 19500.0 /* free speed RPM */ * 12.0 / 56.0 /* belt reduction */ /
108 60.0 /* seconds / minute */ * 256.0 /* CPR */ *
109 4.0 /* index pulse = 1/4 cycle */;
110
Austin Schuh010eb812014-10-25 18:06:49 -0700111class SensorReader {
112 public:
Brian Silverman1f90d672015-01-26 20:20:45 -0500113 SensorReader() {
Brian Silverman335c20e2015-01-26 21:47:58 -0500114 // Set it to filter out anything shorter than 1/4 of the minimum pulse width
115 // we should ever see.
116 filter_.SetPeriodNanoSeconds(
117 static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
118 }
119
120 void set_arm_left_encoder(::std::unique_ptr<Encoder> encoder) {
121 filter_.Add(encoder.get());
122 arm_left_encoder_.set_encoder(::std::move(encoder));
123 }
124
125 void set_arm_left_index(::std::unique_ptr<DigitalSource> index) {
126 filter_.Add(index.get());
127 arm_left_encoder_.set_index(::std::move(index));
128 }
129
130 void set_arm_left_potentiometer(
131 ::std::unique_ptr<AnalogInput> potentiometer) {
132 arm_left_encoder_.set_potentiometer(::std::move(potentiometer));
133 }
134
135 void set_arm_right_encoder(::std::unique_ptr<Encoder> encoder) {
136 filter_.Add(encoder.get());
137 arm_right_encoder_.set_encoder(::std::move(encoder));
138 }
139
140 void set_arm_right_index(::std::unique_ptr<DigitalSource> index) {
141 filter_.Add(index.get());
142 arm_right_encoder_.set_index(::std::move(index));
143 }
144
145 void set_arm_right_potentiometer(
146 ::std::unique_ptr<AnalogInput> potentiometer) {
147 arm_right_encoder_.set_potentiometer(::std::move(potentiometer));
148 }
149
150 void set_elevator_left_encoder(::std::unique_ptr<Encoder> encoder) {
151 filter_.Add(encoder.get());
152 elevator_left_encoder_.set_encoder(::std::move(encoder));
153 }
154
155 void set_elevator_left_index(::std::unique_ptr<DigitalSource> index) {
156 filter_.Add(index.get());
157 elevator_left_encoder_.set_index(::std::move(index));
158 }
159
160 void set_elevator_left_potentiometer(
161 ::std::unique_ptr<AnalogInput> potentiometer) {
162 elevator_left_encoder_.set_potentiometer(::std::move(potentiometer));
163 }
164
165 void set_elevator_right_encoder(::std::unique_ptr<Encoder> encoder) {
166 filter_.Add(encoder.get());
167 elevator_right_encoder_.set_encoder(::std::move(encoder));
168 }
169
170 void set_elevator_right_index(::std::unique_ptr<DigitalSource> index) {
171 filter_.Add(index.get());
172 elevator_right_encoder_.set_index(::std::move(index));
173 }
174
175 void set_elevator_right_potentiometer(
176 ::std::unique_ptr<AnalogInput> potentiometer) {
177 elevator_right_encoder_.set_potentiometer(::std::move(potentiometer));
178 }
179
180 void set_wrist_encoder(::std::unique_ptr<Encoder> encoder) {
181 filter_.Add(encoder.get());
182 wrist_encoder_.set_encoder(::std::move(encoder));
183 }
184
185 void set_wrist_index(::std::unique_ptr<DigitalSource> index) {
186 filter_.Add(index.get());
187 wrist_encoder_.set_index(::std::move(index));
188 }
189
190 void set_wrist_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
191 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
Austin Schuh010eb812014-10-25 18:06:49 -0700192 }
193
Brian Silverman1f90d672015-01-26 20:20:45 -0500194 void set_left_encoder(::std::unique_ptr<Encoder> left_encoder) {
195 left_encoder_ = ::std::move(left_encoder);
196 }
197
198 void set_right_encoder(::std::unique_ptr<Encoder> right_encoder) {
199 right_encoder_ = ::std::move(right_encoder);
200 }
201
Brian Silverman335c20e2015-01-26 21:47:58 -0500202 // All of the DMA-related set_* calls must be made before this, and it doesn't
203 // hurt to do all of them.
204 void set_dma(::std::unique_ptr<DMA> dma) {
205 dma_synchronizer_.reset(new DMASynchronizer(::std::move(dma)));
206 dma_synchronizer_->Add(&arm_left_encoder_);
207 dma_synchronizer_->Add(&arm_right_encoder_);
208 dma_synchronizer_->Add(&elevator_left_encoder_);
209 dma_synchronizer_->Add(&elevator_right_encoder_);
210 }
211
Austin Schuh010eb812014-10-25 18:06:49 -0700212 void operator()() {
Brian Silverman2fe007c2014-12-28 12:20:01 -0800213 ::aos::SetCurrentThreadName("SensorReader");
214
Brian Silverman699f0cb2015-02-05 19:45:01 -0500215 my_pid_ = getpid();
216 ds_ = DriverStation::GetInstance();
217
Brian Silverman335c20e2015-01-26 21:47:58 -0500218 wrist_encoder_.Start();
219 dma_synchronizer_->Start();
Austin Schuh010eb812014-10-25 18:06:49 -0700220
Brian Silverman2fe007c2014-12-28 12:20:01 -0800221 ::aos::SetCurrentThreadRealtimePriority(kPriority);
Austin Schuh010eb812014-10-25 18:06:49 -0700222 while (run_) {
Brian Silverman20141f92015-01-05 17:39:01 -0800223 ::aos::time::PhasedLoopXMS(5, 9000);
Austin Schuh010eb812014-10-25 18:06:49 -0700224 RunIteration();
Austin Schuh010eb812014-10-25 18:06:49 -0700225 }
Brian Silverman335c20e2015-01-26 21:47:58 -0500226
227 wrist_encoder_.Stop();
Austin Schuh010eb812014-10-25 18:06:49 -0700228 }
229
230 void RunIteration() {
Brian Silverman699f0cb2015-02-05 19:45:01 -0500231 {
232 auto new_state = ::aos::robot_state.MakeMessage();
Austin Schuh010eb812014-10-25 18:06:49 -0700233
Brian Silverman699f0cb2015-02-05 19:45:01 -0500234 new_state->outputs_enabled = ds_->IsSysActive();
235 new_state->browned_out = ds_->IsSysBrownedOut();
236
237 new_state->is_3v3_active = ControllerPower::GetEnabled3V3();
238 new_state->is_5v_active = ControllerPower::GetEnabled5V();
239 new_state->voltage_3v3 = ControllerPower::GetVoltage3V3();
240 new_state->voltage_5v = ControllerPower::GetVoltage5V();
241
242 new_state->voltage_roborio_in = ControllerPower::GetInputVoltage();
243 new_state->voltage_battery = ds_->GetBatteryVoltage();
244
245 new_state.Send();
Austin Schuh010eb812014-10-25 18:06:49 -0700246 }
247
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500248 drivetrain_queue.position.MakeWithBuilder()
Austin Schuh010eb812014-10-25 18:06:49 -0700249 .right_encoder(drivetrain_translate(right_encoder_->GetRaw()))
250 .left_encoder(-drivetrain_translate(left_encoder_->GetRaw()))
Austin Schuh010eb812014-10-25 18:06:49 -0700251 .Send();
Brian Silverman335c20e2015-01-26 21:47:58 -0500252
253 dma_synchronizer_->RunIteration();
254
255 {
256 auto fridge_message = fridge_queue.position.MakeMessage();
257 CopyPotAndIndexPosition(arm_left_encoder_, &fridge_message->arm.left,
258 arm_translate, arm_pot_translate, false);
259 CopyPotAndIndexPosition(arm_right_encoder_, &fridge_message->arm.right,
260 arm_translate, arm_pot_translate, true);
261 CopyPotAndIndexPosition(
262 elevator_left_encoder_, &fridge_message->elevator.left,
263 elevator_translate, elevator_pot_translate, false);
264 CopyPotAndIndexPosition(elevator_right_encoder_,
265 &fridge_message->elevator.right,
266 elevator_translate, elevator_pot_translate, true);
267 fridge_message.Send();
268 }
269
270 {
271 auto claw_message = claw_queue.position.MakeMessage();
272 CopyPotAndIndexPosition(wrist_encoder_, &claw_message->joint,
273 claw_translate, claw_pot_translate, false);
274 claw_message.Send();
275 }
Austin Schuh010eb812014-10-25 18:06:49 -0700276 }
277
278 void Quit() { run_ = false; }
279
280 private:
Brian Silverman335c20e2015-01-26 21:47:58 -0500281 static const int kPriority = 30;
282 static const int kInterruptPriority = 55;
283
Brian Silverman699f0cb2015-02-05 19:45:01 -0500284 int32_t my_pid_;
285 DriverStation *ds_;
286
Brian Silverman335c20e2015-01-26 21:47:58 -0500287 void CopyPotAndIndexPosition(
288 const DMAEncoderAndPotentiometer &encoder, PotAndIndexPosition *position,
289 ::std::function<double(int32_t)> encoder_translate,
290 ::std::function<double(double)> pot_translate, bool reverse) {
291 const double multiplier = reverse ? -1.0 : 1.0;
292 position->encoder =
293 multiplier * encoder_translate(encoder.polled_encoder_value());
294 position->pot =
295 multiplier * pot_translate(encoder.polled_potentiometer_voltage());
296 position->latched_encoder =
297 multiplier * encoder_translate(encoder.last_encoder_value());
298 position->latched_pot =
299 multiplier * pot_translate(encoder.last_potentiometer_voltage());
300 position->index_pulses = encoder.index_posedge_count();
301 }
302
303 void CopyPotAndIndexPosition(
304 const InterruptEncoderAndPotentiometer &encoder,
305 PotAndIndexPosition *position,
306 ::std::function<double(int32_t)> encoder_translate,
307 ::std::function<double(double)> pot_translate, bool reverse) {
308 const double multiplier = reverse ? -1.0 : 1.0;
309 position->encoder =
310 multiplier * encoder_translate(encoder.encoder()->GetRaw());
311 position->pot =
312 multiplier * pot_translate(encoder.potentiometer()->GetVoltage());
313 position->latched_encoder =
314 multiplier * encoder_translate(encoder.last_encoder_value());
315 position->latched_pot =
316 multiplier * pot_translate(encoder.last_potentiometer_voltage());
317 position->index_pulses = encoder.index_posedge_count();
318 }
319
320
321 ::std::unique_ptr<DMASynchronizer> dma_synchronizer_;
322
323 DMAEncoderAndPotentiometer arm_left_encoder_, arm_right_encoder_,
324 elevator_left_encoder_, elevator_right_encoder_;
325
326 InterruptEncoderAndPotentiometer wrist_encoder_{kInterruptPriority};
327
Austin Schuh010eb812014-10-25 18:06:49 -0700328 ::std::unique_ptr<Encoder> left_encoder_;
329 ::std::unique_ptr<Encoder> right_encoder_;
Austin Schuh010eb812014-10-25 18:06:49 -0700330
Brian Silverman1f90d672015-01-26 20:20:45 -0500331 ::std::atomic<bool> run_{true};
Austin Schuh010eb812014-10-25 18:06:49 -0700332 DigitalGlitchFilter filter_;
333};
334
Brian Silvermand8f403a2014-12-13 19:12:04 -0500335class SolenoidWriter {
Austin Schuh010eb812014-10-25 18:06:49 -0700336 public:
Brian Silvermand8f403a2014-12-13 19:12:04 -0500337 SolenoidWriter(const ::std::unique_ptr<BufferedPcm> &pcm)
Daniel Pettiadf38432015-01-26 17:13:35 -0800338 : pcm_(pcm),
339 fridge_(".frc971.control_loops.fridge.output"),
340 claw_(".frc971.control_loops.claw.output") {}
Brian Silvermand8f403a2014-12-13 19:12:04 -0500341
Daniel Pettiadf38432015-01-26 17:13:35 -0800342 void set_fridge_grabbers_top_front(::std::unique_ptr<BufferedSolenoid> s) {
343 fridge_grabbers_top_front_ = ::std::move(s);
Austin Schuh010eb812014-10-25 18:06:49 -0700344 }
345
Daniel Pettiadf38432015-01-26 17:13:35 -0800346 void set_fridge_grabbers_top_back(::std::unique_ptr<BufferedSolenoid> s) {
347 fridge_grabbers_top_back_ = ::std::move(s);
348 }
349
350 void set_fridge_grabbers_bottom_front(
351 ::std::unique_ptr<BufferedSolenoid> s) {
352 fridge_grabbers_bottom_front_ = ::std::move(s);
353 }
354
355 void set_fridge_grabbers_bottom_back(
356 ::std::unique_ptr<BufferedSolenoid> s) {
357 fridge_grabbers_bottom_back_ = ::std::move(s);
358 }
359
360 void set_claw_pinchers(::std::unique_ptr<BufferedSolenoid> s) {
361 claw_pinchers_ = ::std::move(s);
Brian Silvermand8f403a2014-12-13 19:12:04 -0500362 }
Austin Schuh010eb812014-10-25 18:06:49 -0700363
Brian Silvermand8f403a2014-12-13 19:12:04 -0500364 void operator()() {
365 ::aos::SetCurrentThreadName("Solenoids");
366 ::aos::SetCurrentThreadRealtimePriority(30);
367
368 while (run_) {
369 ::aos::time::PhasedLoopXMS(20, 1000);
370
371 {
Daniel Pettiadf38432015-01-26 17:13:35 -0800372 fridge_.FetchLatest();
373 if (fridge_.get()) {
374 LOG_STRUCT(DEBUG, "solenoids", *fridge_);
375 fridge_grabbers_top_front_->Set(fridge_->grabbers.top_front);
376 fridge_grabbers_top_back_->Set(fridge_->grabbers.top_back);
377 fridge_grabbers_bottom_front_->Set(fridge_->grabbers.bottom_front);
378 fridge_grabbers_bottom_back_->Set(fridge_->grabbers.bottom_back);
379 }
380 }
381
382 {
383 claw_.FetchLatest();
384 if (claw_.get()) {
385 LOG_STRUCT(DEBUG, "solenoids", *claw_);
386 claw_pinchers_->Set(claw_->rollers_closed);
Brian Silvermand8f403a2014-12-13 19:12:04 -0500387 }
388 }
389
Brian Silvermand8f403a2014-12-13 19:12:04 -0500390 pcm_->Flush();
Austin Schuh010eb812014-10-25 18:06:49 -0700391 }
392 }
393
Brian Silvermand8f403a2014-12-13 19:12:04 -0500394 void Quit() { run_ = false; }
Austin Schuh010eb812014-10-25 18:06:49 -0700395
Brian Silvermand8f403a2014-12-13 19:12:04 -0500396 private:
397 const ::std::unique_ptr<BufferedPcm> &pcm_;
Daniel Pettiadf38432015-01-26 17:13:35 -0800398 ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_top_front_;
399 ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_top_back_;
400 ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_bottom_front_;
401 ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_bottom_back_;
402 ::std::unique_ptr<BufferedSolenoid> claw_pinchers_;
Austin Schuh010eb812014-10-25 18:06:49 -0700403
Daniel Pettiadf38432015-01-26 17:13:35 -0800404 ::aos::Queue<::frc971::control_loops::FridgeQueue::Output> fridge_;
405 ::aos::Queue<::frc971::control_loops::ClawQueue::Output> claw_;
Austin Schuh010eb812014-10-25 18:06:49 -0700406
Brian Silvermand8f403a2014-12-13 19:12:04 -0500407 ::std::atomic<bool> run_{true};
408};
409
410class DrivetrainWriter : public LoopOutputHandler {
411 public:
412 void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
413 left_drivetrain_talon_ = ::std::move(t);
Austin Schuh010eb812014-10-25 18:06:49 -0700414 }
415
Brian Silvermand8f403a2014-12-13 19:12:04 -0500416 void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
417 right_drivetrain_talon_ = ::std::move(t);
418 }
Austin Schuh010eb812014-10-25 18:06:49 -0700419
Brian Silvermand8f403a2014-12-13 19:12:04 -0500420 private:
421 virtual void Read() override {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500422 ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
Brian Silvermand8f403a2014-12-13 19:12:04 -0500423 }
424
425 virtual void Write() override {
Brian Silvermanada5f2c2015-02-01 02:41:14 -0500426 auto &queue = ::frc971::control_loops::drivetrain_queue.output;
Brian Silvermand8f403a2014-12-13 19:12:04 -0500427 LOG_STRUCT(DEBUG, "will output", *queue);
428 left_drivetrain_talon_->Set(-queue->left_voltage / 12.0);
429 right_drivetrain_talon_->Set(queue->right_voltage / 12.0);
430 }
431
432 virtual void Stop() override {
433 LOG(WARNING, "drivetrain output too old\n");
434 left_drivetrain_talon_->Disable();
435 right_drivetrain_talon_->Disable();
436 }
437
Austin Schuh010eb812014-10-25 18:06:49 -0700438 ::std::unique_ptr<Talon> left_drivetrain_talon_;
Brian Silvermand8f403a2014-12-13 19:12:04 -0500439 ::std::unique_ptr<Talon> right_drivetrain_talon_;
440};
441
Daniel Pettiadf38432015-01-26 17:13:35 -0800442class FridgeWriter : public LoopOutputHandler {
443 public:
444 void set_left_arm_talon(::std::unique_ptr<Talon> t) {
445 left_arm_talon_ = ::std::move(t);
446 }
447
448 void set_right_arm_talon(::std::unique_ptr<Talon> t) {
449 right_arm_talon_ = ::std::move(t);
450 }
451
452 void set_left_elevator_talon(::std::unique_ptr<Talon> t) {
453 left_elevator_talon_ = ::std::move(t);
454 }
455
456 void set_right_elevator_talon(::std::unique_ptr<Talon> t) {
457 right_elevator_talon_ = ::std::move(t);
458 }
459
460 private:
461 virtual void Read() override {
462 ::frc971::control_loops::fridge_queue.output.FetchAnother();
463 }
464
465 virtual void Write() override {
466 auto &queue = ::frc971::control_loops::fridge_queue.output;
467 LOG_STRUCT(DEBUG, "will output", *queue);
468 left_arm_talon_->Set(-queue->left_arm / 12.0);
469 right_arm_talon_->Set(queue->right_arm / 12.0);
470 left_elevator_talon_->Set(-queue->left_elevator / 12.0);
471 right_elevator_talon_->Set(queue->right_elevator / 12.0);
472 }
473
474 virtual void Stop() override {
475 LOG(WARNING, "Fridge output too old.\n");
476 left_arm_talon_->Disable();
477 right_arm_talon_->Disable();
478 left_elevator_talon_->Disable();
479 right_elevator_talon_->Disable();
480 }
481
482 ::std::unique_ptr<Talon> left_arm_talon_;
483 ::std::unique_ptr<Talon> right_arm_talon_;
484 ::std::unique_ptr<Talon> left_elevator_talon_;
485 ::std::unique_ptr<Talon> right_elevator_talon_;
486};
487
488class ClawWriter : public LoopOutputHandler {
489 public:
490 void set_intake_talon(::std::unique_ptr<Talon> t) {
491 intake_talon_ = ::std::move(t);
492 }
493
494 void set_wrist_talon(::std::unique_ptr<Talon> t) {
495 wrist_talon_ = ::std::move(t);
496 }
497
498 private:
499 virtual void Read() override {
500 ::frc971::control_loops::claw_queue.output.FetchAnother();
501 }
502
503 virtual void Write() override {
504 auto &queue = ::frc971::control_loops::claw_queue.output;
505 LOG_STRUCT(DEBUG, "will output", *queue);
506 intake_talon_->Set(queue->intake_voltage / 12.0);
507 wrist_talon_->Set(queue->voltage / 12.0);
508 }
509
510 virtual void Stop() override {
511 LOG(WARNING, "Claw output too old.\n");
512 intake_talon_->Disable();
513 wrist_talon_->Disable();
514 }
515
516 ::std::unique_ptr<Talon> intake_talon_;
517 ::std::unique_ptr<Talon> wrist_talon_;
518};
519
Brian Silverman1f90d672015-01-26 20:20:45 -0500520// TODO(brian): Replace this with ::std::make_unique once all our toolchains
521// have support.
522template <class T, class... U>
523std::unique_ptr<T> make_unique(U &&... u) {
524 return std::unique_ptr<T>(new T(std::forward<U>(u)...));
525}
526
Austin Schuh010eb812014-10-25 18:06:49 -0700527class WPILibRobot : public RobotBase {
528 public:
529 virtual void StartCompetition() {
Brian Silvermand8f403a2014-12-13 19:12:04 -0500530 ::aos::InitNRT();
Brian Silverman2fe007c2014-12-28 12:20:01 -0800531 ::aos::SetCurrentThreadName("StartCompetition");
Brian Silvermand8f403a2014-12-13 19:12:04 -0500532
Brian Silverman98f6ee22015-01-26 17:50:12 -0500533 JoystickSender joystick_sender;
Austin Schuh010eb812014-10-25 18:06:49 -0700534 ::std::thread joystick_thread(::std::ref(joystick_sender));
Brian Silvermand8f403a2014-12-13 19:12:04 -0500535 ::std::unique_ptr<Compressor> compressor(new Compressor());
536 compressor->SetClosedLoopControl(true);
537
Brian Silverman98f6ee22015-01-26 17:50:12 -0500538 SensorReader reader;
Brian Silverman1f90d672015-01-26 20:20:45 -0500539 // TODO(sensors): Replace all the 99s with real port numbers.
Brian Silverman335c20e2015-01-26 21:47:58 -0500540 reader.set_arm_left_encoder(
541 make_unique<Encoder>(99, 99, false, Encoder::k4X));
542 reader.set_arm_left_index(make_unique<DigitalInput>(99));
543 reader.set_arm_left_potentiometer(make_unique<AnalogInput>(99));
544 reader.set_arm_right_encoder(
545 make_unique<Encoder>(99, 99, false, Encoder::k4X));
546 reader.set_arm_right_index(make_unique<DigitalInput>(99));
547 reader.set_arm_right_potentiometer(make_unique<AnalogInput>(99));
548 reader.set_elevator_left_encoder(
549 make_unique<Encoder>(99, 99, false, Encoder::k4X));
550 reader.set_elevator_left_index(make_unique<DigitalInput>(99));
551 reader.set_elevator_left_potentiometer(make_unique<AnalogInput>(99));
552 reader.set_elevator_right_encoder(
553 make_unique<Encoder>(99, 99, false, Encoder::k4X));
554 reader.set_elevator_right_index(make_unique<DigitalInput>(99));
555 reader.set_elevator_right_potentiometer(make_unique<AnalogInput>(99));
556 reader.set_wrist_encoder(make_unique<Encoder>(99, 99, false, Encoder::k4X));
557 reader.set_wrist_index(make_unique<DigitalInput>(99));
558 reader.set_wrist_potentiometer(make_unique<AnalogInput>(99));
Brian Silverman1f90d672015-01-26 20:20:45 -0500559 reader.set_left_encoder(make_unique<Encoder>(99, 99, false, Encoder::k4X));
560 reader.set_right_encoder(make_unique<Encoder>(99, 99, false, Encoder::k4X));
Brian Silverman335c20e2015-01-26 21:47:58 -0500561 reader.set_dma(make_unique<DMA>());
Brian Silverman98f6ee22015-01-26 17:50:12 -0500562 ::std::thread reader_thread(::std::ref(reader));
563 GyroSender gyro_sender;
564 ::std::thread gyro_thread(::std::ref(gyro_sender));
565
566 DrivetrainWriter drivetrain_writer;
Brian Silvermand8f403a2014-12-13 19:12:04 -0500567 drivetrain_writer.set_left_drivetrain_talon(
568 ::std::unique_ptr<Talon>(new Talon(5)));
569 drivetrain_writer.set_right_drivetrain_talon(
570 ::std::unique_ptr<Talon>(new Talon(2)));
571 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
572
Daniel Pettiadf38432015-01-26 17:13:35 -0800573 // TODO(sensors): Get real PWM output and relay numbers for the fridge and
574 // claw.
575 FridgeWriter fridge_writer;
576 fridge_writer.set_left_arm_talon(
577 ::std::unique_ptr<Talon>(new Talon(99)));
578 fridge_writer.set_right_arm_talon(
579 ::std::unique_ptr<Talon>(new Talon(99)));
580 fridge_writer.set_left_elevator_talon(
581 ::std::unique_ptr<Talon>(new Talon(99)));
582 fridge_writer.set_right_elevator_talon(
583 ::std::unique_ptr<Talon>(new Talon(99)));
584 ::std::thread fridge_writer_thread(::std::ref(fridge_writer));
585
586 ClawWriter claw_writer;
587 claw_writer.set_intake_talon(
588 ::std::unique_ptr<Talon>(new Talon(99)));
589 claw_writer.set_wrist_talon(
590 ::std::unique_ptr<Talon>(new Talon(99)));
591 ::std::thread claw_writer_thread(::std::ref(claw_writer));
592
593 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
594 new ::frc971::wpilib::BufferedPcm());
Brian Silverman98f6ee22015-01-26 17:50:12 -0500595 SolenoidWriter solenoid_writer(pcm);
Daniel Pettiadf38432015-01-26 17:13:35 -0800596 solenoid_writer.set_fridge_grabbers_top_front(pcm->MakeSolenoid(99));
597 solenoid_writer.set_fridge_grabbers_top_back(pcm->MakeSolenoid(99));
598 solenoid_writer.set_fridge_grabbers_bottom_front(pcm->MakeSolenoid(99));
599 solenoid_writer.set_fridge_grabbers_bottom_back(pcm->MakeSolenoid(99));
600 solenoid_writer.set_claw_pinchers(pcm->MakeSolenoid(99));
Brian Silvermand8f403a2014-12-13 19:12:04 -0500601 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
602
603 // Wait forever. Not much else to do...
604 PCHECK(select(0, nullptr, nullptr, nullptr, nullptr));
605
Austin Schuh010eb812014-10-25 18:06:49 -0700606 LOG(ERROR, "Exiting WPILibRobot\n");
Brian Silverman07ec88e2014-12-28 00:13:08 -0800607
Austin Schuh010eb812014-10-25 18:06:49 -0700608 joystick_sender.Quit();
609 joystick_thread.join();
Brian Silvermand8f403a2014-12-13 19:12:04 -0500610 reader.Quit();
611 reader_thread.join();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800612 gyro_sender.Quit();
613 gyro_thread.join();
Brian Silvermand8f403a2014-12-13 19:12:04 -0500614
615 drivetrain_writer.Quit();
616 drivetrain_writer_thread.join();
Brian Silvermand8f403a2014-12-13 19:12:04 -0500617 solenoid_writer.Quit();
618 solenoid_thread.join();
619
Austin Schuh010eb812014-10-25 18:06:49 -0700620 ::aos::Cleanup();
621 }
622};
623
Brian Silverman98f6ee22015-01-26 17:50:12 -0500624} // namespace wpilib
625} // namespace frc971
Austin Schuhdb516032014-12-28 00:12:38 -0800626
Brian Silverman98f6ee22015-01-26 17:50:12 -0500627
628START_ROBOT_CLASS(::frc971::wpilib::WPILibRobot);