blob: 6d4fcffeda901d04d513e117c29cab546b4a23b0 [file] [log] [blame]
Brian Silvermanc71537c2016-01-01 13:43:14 -08001#include <stdio.h>
2#include <string.h>
3#include <unistd.h>
4#include <inttypes.h>
5
Austin Schuh8aec1ed2016-05-01 13:29:20 -07006#include <chrono>
Brian Silvermanc71537c2016-01-01 13:43:14 -08007#include <thread>
8#include <mutex>
9#include <functional>
10
Parker Schuhd3b7a8872018-02-19 16:42:27 -080011#include "frc971/wpilib/ahal/AnalogInput.h"
12#include "frc971/wpilib/ahal/Compressor.h"
13#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
14#include "frc971/wpilib/ahal/DriverStation.h"
15#include "frc971/wpilib/ahal/Encoder.h"
16#include "frc971/wpilib/ahal/PowerDistributionPanel.h"
17#include "frc971/wpilib/ahal/Relay.h"
18#include "frc971/wpilib/ahal/Talon.h"
Brian Silverman5090c432016-01-02 14:44:26 -080019#include "frc971/wpilib/wpilib_robot_base.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080020#undef ERROR
21
John Park33858a32018-09-28 23:05:48 -070022#include "aos/logging/logging.h"
23#include "aos/logging/queue_logging.h"
24#include "aos/time/time.h"
25#include "aos/util/log_interval.h"
26#include "aos/util/phased_loop.h"
27#include "aos/util/wrapping_counter.h"
28#include "aos/stl_mutex/stl_mutex.h"
John Park398c74a2018-10-20 21:17:39 -070029#include "aos/init.h"
John Park33858a32018-09-28 23:05:48 -070030#include "aos/robot_state/robot_state.q.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080031
Austin Schuh2a671df2016-11-26 15:00:06 -080032#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080033#include "frc971/wpilib/buffered_pcm.h"
Austin Schuh2a671df2016-11-26 15:00:06 -080034#include "frc971/wpilib/buffered_solenoid.h"
Brian Silvermanb5b46ca2016-03-13 01:14:17 -050035#include "frc971/wpilib/dma.h"
Austin Schuh2a671df2016-11-26 15:00:06 -080036#include "frc971/wpilib/dma_edge_counting.h"
37#include "frc971/wpilib/encoder_and_potentiometer.h"
38#include "frc971/wpilib/gyro_sender.h"
39#include "frc971/wpilib/interrupt_edge_counting.h"
40#include "frc971/wpilib/joystick_sender.h"
41#include "frc971/wpilib/logging.q.h"
42#include "frc971/wpilib/loop_output_handler.h"
43#include "frc971/wpilib/wpilib_interface.h"
44#include "y2012/control_loops/accessories/accessories.q.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080045
46#ifndef M_PI
47#define M_PI 3.14159265358979323846
48#endif
49
Austin Schuh2a671df2016-11-26 15:00:06 -080050using ::frc971::control_loops::drivetrain_queue;
Brian Silvermanc71537c2016-01-01 13:43:14 -080051using ::y2012::control_loops::accessories_queue;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080052using namespace frc;
Brian Silvermanc71537c2016-01-01 13:43:14 -080053
54namespace y2012 {
55namespace wpilib {
56
57template <class T, class... U>
58std::unique_ptr<T> make_unique(U &&... u) {
59 return std::unique_ptr<T>(new T(std::forward<U>(u)...));
60}
61
62double drivetrain_translate(int32_t in) {
63 return -static_cast<double>(in) /
64 (256.0 /*cpr*/ * 4.0 /*4x*/) *
65 1 *
66 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
67}
68
69double drivetrain_velocity_translate(double in) {
70 return (1.0 / in) / 256.0 /*cpr*/ *
71 1 *
72 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
73}
74
Brian Silvermanc71537c2016-01-01 13:43:14 -080075class SensorReader {
76 public:
77 SensorReader() {}
78
79 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
80 drivetrain_left_encoder_ = ::std::move(encoder);
81 drivetrain_left_encoder_->SetMaxPeriod(0.005);
82 }
83
84 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
85 drivetrain_right_encoder_ = ::std::move(encoder);
86 drivetrain_right_encoder_->SetMaxPeriod(0.005);
87 }
88
89 void operator()() {
90 ::aos::SetCurrentThreadName("SensorReader");
91
92 my_pid_ = getpid();
Brian Silverman5090c432016-01-02 14:44:26 -080093
Austin Schuh8aec1ed2016-05-01 13:29:20 -070094 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
95 ::std::chrono::milliseconds(4));
Brian Silvermanc71537c2016-01-01 13:43:14 -080096
Brian Silverman5090c432016-01-02 14:44:26 -080097 ::aos::SetCurrentThreadRealtimePriority(40);
Brian Silvermanc71537c2016-01-01 13:43:14 -080098 while (run_) {
99 {
100 const int iterations = phased_loop.SleepUntilNext();
101 if (iterations != 1) {
102 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
103 }
104 }
105 RunIteration();
106 }
107 }
108
109 void RunIteration() {
Austin Schuh94f51e92017-10-30 19:25:32 -0700110 ::frc971::wpilib::SendRobotState(my_pid_);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800111
112 {
113 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
114 drivetrain_message->right_encoder =
115 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
116 drivetrain_message->left_encoder =
117 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
118 drivetrain_message->left_speed =
119 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
120 drivetrain_message->right_speed =
121 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
122
123 drivetrain_message.Send();
124 }
125
126 accessories_queue.position.MakeMessage().Send();
127 }
128
129 void Quit() { run_ = false; }
130
131 private:
Brian Silvermanc71537c2016-01-01 13:43:14 -0800132 int32_t my_pid_;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800133
134 ::std::unique_ptr<Encoder> drivetrain_left_encoder_;
135 ::std::unique_ptr<Encoder> drivetrain_right_encoder_;
136 ::std::atomic<bool> run_{true};
137};
138
139class SolenoidWriter {
140 public:
141 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
142 : pcm_(pcm),
143 drivetrain_(".y2012.control_loops.drivetrain_queue.output"),
144 accessories_(".y2012.control_loops.accessories_queue.output") {}
145
146 void set_drivetrain_high(
147 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
148 drivetrain_high_ = ::std::move(s);
149 }
150
151 void set_drivetrain_low(
152 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
153 drivetrain_low_ = ::std::move(s);
154 }
155
156 void set_s1(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
157 s1_ = ::std::move(s);
158 }
159
160 void set_s2(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
161 s2_ = ::std::move(s);
162 }
163
164 void set_s3(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
165 s3_ = ::std::move(s);
166 }
167
168 void operator()() {
169 ::aos::SetCurrentThreadName("Solenoids");
Brian Silverman5090c432016-01-02 14:44:26 -0800170 ::aos::SetCurrentThreadRealtimePriority(27);
171
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700172 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(20),
173 ::std::chrono::milliseconds(1));
Brian Silvermanc71537c2016-01-01 13:43:14 -0800174
175 while (run_) {
Brian Silverman5090c432016-01-02 14:44:26 -0800176 {
177 const int iterations = phased_loop.SleepUntilNext();
178 if (iterations != 1) {
179 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
180 }
181 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800182
183 {
184 accessories_.FetchLatest();
185 if (accessories_.get()) {
186 LOG_STRUCT(DEBUG, "solenoids", *accessories_);
187 s1_->Set(accessories_->solenoids[0]);
188 s2_->Set(accessories_->solenoids[1]);
189 s3_->Set(accessories_->solenoids[2]);
190 }
191 }
192
193 {
194 drivetrain_.FetchLatest();
195 if (drivetrain_.get()) {
196 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
197 const bool high = drivetrain_->left_high || drivetrain_->right_high;
198 drivetrain_high_->Set(high);
199 drivetrain_low_->Set(!high);
200 }
201 }
202
203 {
204 ::frc971::wpilib::PneumaticsToLog to_log;
205 pcm_->Flush();
206 to_log.read_solenoids = pcm_->GetAll();
207 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
208 }
209 }
210 }
211
212 void Quit() { run_ = false; }
213
214 private:
215 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
216
217 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_high_;
218 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_low_;
219 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s1_, s2_, s3_;
220
221 ::std::unique_ptr<Compressor> compressor_;
222
Austin Schuh2a671df2016-11-26 15:00:06 -0800223 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800224 ::aos::Queue<::y2012::control_loops::AccessoriesQueue::Message> accessories_;
225
226 ::std::atomic<bool> run_{true};
227};
228
229class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
230 public:
231 void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
232 left_drivetrain_talon_ = ::std::move(t);
233 }
234
235 void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
236 right_drivetrain_talon_ = ::std::move(t);
237 }
238
239 private:
240 virtual void Read() override {
Austin Schuh2a671df2016-11-26 15:00:06 -0800241 drivetrain_queue.output.FetchAnother();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800242 }
243
244 virtual void Write() override {
Austin Schuh2a671df2016-11-26 15:00:06 -0800245 auto &queue = drivetrain_queue.output;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800246 LOG_STRUCT(DEBUG, "will output", *queue);
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800247 left_drivetrain_talon_->SetSpeed(-queue->left_voltage / 12.0);
248 right_drivetrain_talon_->SetSpeed(queue->right_voltage / 12.0);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800249 }
250
251 virtual void Stop() override {
252 LOG(WARNING, "drivetrain output too old\n");
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800253 left_drivetrain_talon_->SetDisabled();
254 right_drivetrain_talon_->SetDisabled();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800255 }
256
257 ::std::unique_ptr<Talon> left_drivetrain_talon_;
258 ::std::unique_ptr<Talon> right_drivetrain_talon_;
259};
260
261class AccessoriesWriter : public ::frc971::wpilib::LoopOutputHandler {
262 public:
263 void set_talon1(::std::unique_ptr<Talon> t) {
264 talon1_ = ::std::move(t);
265 }
266
267 void set_talon2(::std::unique_ptr<Talon> t) {
268 talon2_ = ::std::move(t);
269 }
270
271 private:
272 virtual void Read() override {
273 ::y2012::control_loops::accessories_queue.output.FetchAnother();
274 }
275
276 virtual void Write() override {
277 auto &queue = ::y2012::control_loops::accessories_queue.output;
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800278 talon1_->SetSpeed(queue->sticks[0]);
279 talon2_->SetSpeed(queue->sticks[1]);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800280 LOG_STRUCT(DEBUG, "will output", *queue);
281 }
282
283 virtual void Stop() override {
284 LOG(WARNING, "shooter output too old\n");
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800285 talon1_->SetDisabled();
286 talon2_->SetDisabled();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800287 }
288
289 ::std::unique_ptr<Talon> talon1_, talon2_;
290};
291
Brian Silverman5090c432016-01-02 14:44:26 -0800292class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800293 public:
294 ::std::unique_ptr<Encoder> make_encoder(int index) {
295 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
296 Encoder::k4X);
297 }
298
Brian Silverman5090c432016-01-02 14:44:26 -0800299 void Run() override {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800300 ::aos::InitNRT();
301 ::aos::SetCurrentThreadName("StartCompetition");
302
303 ::frc971::wpilib::JoystickSender joystick_sender;
304 ::std::thread joystick_thread(::std::ref(joystick_sender));
305
306 SensorReader reader;
307
308 reader.set_drivetrain_left_encoder(make_encoder(0));
309 reader.set_drivetrain_right_encoder(make_encoder(1));
310
311 ::std::thread reader_thread(::std::ref(reader));
312
313 DrivetrainWriter drivetrain_writer;
314 drivetrain_writer.set_left_drivetrain_talon(
315 ::std::unique_ptr<Talon>(new Talon(3)));
316 drivetrain_writer.set_right_drivetrain_talon(
317 ::std::unique_ptr<Talon>(new Talon(4)));
318 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
319
320 ::y2012::wpilib::AccessoriesWriter accessories_writer;
321 accessories_writer.set_talon1(::std::unique_ptr<Talon>(new Talon(5)));
322 accessories_writer.set_talon2(::std::unique_ptr<Talon>(new Talon(6)));
323 ::std::thread accessories_writer_thread(::std::ref(accessories_writer));
324
325 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
326 new ::frc971::wpilib::BufferedPcm());
327 SolenoidWriter solenoid_writer(pcm);
328 solenoid_writer.set_drivetrain_high(pcm->MakeSolenoid(0));
329 solenoid_writer.set_drivetrain_low(pcm->MakeSolenoid(2));
330 solenoid_writer.set_s1(pcm->MakeSolenoid(1));
331 solenoid_writer.set_s2(pcm->MakeSolenoid(3));
332 solenoid_writer.set_s3(pcm->MakeSolenoid(4));
333
334 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
335
336 // Wait forever. Not much else to do...
Brian Silverman5090c432016-01-02 14:44:26 -0800337 while (true) {
338 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
339 if (r != 0) {
340 PLOG(WARNING, "infinite select failed");
341 } else {
342 PLOG(WARNING, "infinite select succeeded??\n");
343 }
344 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800345
346 LOG(ERROR, "Exiting WPILibRobot\n");
347
348 joystick_sender.Quit();
349 joystick_thread.join();
350 reader.Quit();
351 reader_thread.join();
352
353 drivetrain_writer.Quit();
354 drivetrain_writer_thread.join();
355 accessories_writer.Quit();
356 accessories_writer_thread.join();
357
358 ::aos::Cleanup();
359 }
360};
361
362} // namespace wpilib
363} // namespace y2012
364
365
Brian Silverman5090c432016-01-02 14:44:26 -0800366AOS_ROBOT_CLASS(::y2012::wpilib::WPILibRobot);