blob: b5be8f4cc0916e241e1e0f19d48a25503ceb097b [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
Brian Silvermanf819b442019-01-20 16:51:04 -080022#include "aos/init.h"
John Park33858a32018-09-28 23:05:48 -070023#include "aos/logging/logging.h"
24#include "aos/logging/queue_logging.h"
Brian Silvermanf819b442019-01-20 16:51:04 -080025#include "aos/make_unique.h"
26#include "aos/robot_state/robot_state.q.h"
27#include "aos/stl_mutex/stl_mutex.h"
John Park33858a32018-09-28 23:05:48 -070028#include "aos/time/time.h"
29#include "aos/util/log_interval.h"
30#include "aos/util/phased_loop.h"
31#include "aos/util/wrapping_counter.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080032
Austin Schuh2a671df2016-11-26 15:00:06 -080033#include "frc971/control_loops/drivetrain/drivetrain.q.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080034#include "frc971/wpilib/buffered_pcm.h"
Austin Schuh2a671df2016-11-26 15:00:06 -080035#include "frc971/wpilib/buffered_solenoid.h"
Brian Silvermanb5b46ca2016-03-13 01:14:17 -050036#include "frc971/wpilib/dma.h"
Austin Schuh2a671df2016-11-26 15:00:06 -080037#include "frc971/wpilib/dma_edge_counting.h"
38#include "frc971/wpilib/encoder_and_potentiometer.h"
39#include "frc971/wpilib/gyro_sender.h"
40#include "frc971/wpilib/interrupt_edge_counting.h"
41#include "frc971/wpilib/joystick_sender.h"
42#include "frc971/wpilib/logging.q.h"
43#include "frc971/wpilib/loop_output_handler.h"
44#include "frc971/wpilib/wpilib_interface.h"
45#include "y2012/control_loops/accessories/accessories.q.h"
Brian Silvermanc71537c2016-01-01 13:43:14 -080046
47#ifndef M_PI
48#define M_PI 3.14159265358979323846
49#endif
50
Austin Schuh2a671df2016-11-26 15:00:06 -080051using ::frc971::control_loops::drivetrain_queue;
Brian Silvermanc71537c2016-01-01 13:43:14 -080052using ::y2012::control_loops::accessories_queue;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080053using namespace frc;
Brian Silvermanf819b442019-01-20 16:51:04 -080054using aos::make_unique;
Brian Silvermanc71537c2016-01-01 13:43:14 -080055
56namespace y2012 {
57namespace wpilib {
58
Brian Silvermanc71537c2016-01-01 13:43:14 -080059double drivetrain_translate(int32_t in) {
60 return -static_cast<double>(in) /
61 (256.0 /*cpr*/ * 4.0 /*4x*/) *
62 1 *
63 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
64}
65
66double drivetrain_velocity_translate(double in) {
67 return (1.0 / in) / 256.0 /*cpr*/ *
68 1 *
69 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI) * 2.0 / 2.0;
70}
71
Brian Silvermanc71537c2016-01-01 13:43:14 -080072class SensorReader {
73 public:
74 SensorReader() {}
75
76 void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
77 drivetrain_left_encoder_ = ::std::move(encoder);
78 drivetrain_left_encoder_->SetMaxPeriod(0.005);
79 }
80
81 void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
82 drivetrain_right_encoder_ = ::std::move(encoder);
83 drivetrain_right_encoder_->SetMaxPeriod(0.005);
84 }
85
86 void operator()() {
87 ::aos::SetCurrentThreadName("SensorReader");
88
89 my_pid_ = getpid();
Brian Silverman5090c432016-01-02 14:44:26 -080090
Austin Schuh8aec1ed2016-05-01 13:29:20 -070091 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
92 ::std::chrono::milliseconds(4));
Brian Silvermanc71537c2016-01-01 13:43:14 -080093
Brian Silverman5090c432016-01-02 14:44:26 -080094 ::aos::SetCurrentThreadRealtimePriority(40);
Brian Silvermanc71537c2016-01-01 13:43:14 -080095 while (run_) {
96 {
97 const int iterations = phased_loop.SleepUntilNext();
98 if (iterations != 1) {
99 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
100 }
101 }
102 RunIteration();
103 }
104 }
105
106 void RunIteration() {
Austin Schuh94f51e92017-10-30 19:25:32 -0700107 ::frc971::wpilib::SendRobotState(my_pid_);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800108
109 {
110 auto drivetrain_message = drivetrain_queue.position.MakeMessage();
111 drivetrain_message->right_encoder =
112 drivetrain_translate(drivetrain_right_encoder_->GetRaw());
113 drivetrain_message->left_encoder =
114 -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
115 drivetrain_message->left_speed =
116 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
117 drivetrain_message->right_speed =
118 drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
119
120 drivetrain_message.Send();
121 }
122
123 accessories_queue.position.MakeMessage().Send();
124 }
125
126 void Quit() { run_ = false; }
127
128 private:
Brian Silvermanc71537c2016-01-01 13:43:14 -0800129 int32_t my_pid_;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800130
131 ::std::unique_ptr<Encoder> drivetrain_left_encoder_;
132 ::std::unique_ptr<Encoder> drivetrain_right_encoder_;
133 ::std::atomic<bool> run_{true};
134};
135
136class SolenoidWriter {
137 public:
138 SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
139 : pcm_(pcm),
140 drivetrain_(".y2012.control_loops.drivetrain_queue.output"),
141 accessories_(".y2012.control_loops.accessories_queue.output") {}
142
143 void set_drivetrain_high(
144 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
145 drivetrain_high_ = ::std::move(s);
146 }
147
148 void set_drivetrain_low(
149 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
150 drivetrain_low_ = ::std::move(s);
151 }
152
153 void set_s1(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
154 s1_ = ::std::move(s);
155 }
156
157 void set_s2(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
158 s2_ = ::std::move(s);
159 }
160
161 void set_s3(::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s) {
162 s3_ = ::std::move(s);
163 }
164
165 void operator()() {
166 ::aos::SetCurrentThreadName("Solenoids");
Brian Silverman5090c432016-01-02 14:44:26 -0800167 ::aos::SetCurrentThreadRealtimePriority(27);
168
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700169 ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(20),
170 ::std::chrono::milliseconds(1));
Brian Silvermanc71537c2016-01-01 13:43:14 -0800171
172 while (run_) {
Brian Silverman5090c432016-01-02 14:44:26 -0800173 {
174 const int iterations = phased_loop.SleepUntilNext();
175 if (iterations != 1) {
176 LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
177 }
178 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800179
180 {
181 accessories_.FetchLatest();
182 if (accessories_.get()) {
183 LOG_STRUCT(DEBUG, "solenoids", *accessories_);
184 s1_->Set(accessories_->solenoids[0]);
185 s2_->Set(accessories_->solenoids[1]);
186 s3_->Set(accessories_->solenoids[2]);
187 }
188 }
189
190 {
191 drivetrain_.FetchLatest();
192 if (drivetrain_.get()) {
193 LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
194 const bool high = drivetrain_->left_high || drivetrain_->right_high;
195 drivetrain_high_->Set(high);
196 drivetrain_low_->Set(!high);
197 }
198 }
199
200 {
201 ::frc971::wpilib::PneumaticsToLog to_log;
202 pcm_->Flush();
203 to_log.read_solenoids = pcm_->GetAll();
204 LOG_STRUCT(DEBUG, "pneumatics info", to_log);
205 }
206 }
207 }
208
209 void Quit() { run_ = false; }
210
211 private:
212 const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm_;
213
214 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_high_;
215 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> drivetrain_low_;
216 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> s1_, s2_, s3_;
217
218 ::std::unique_ptr<Compressor> compressor_;
219
Austin Schuh2a671df2016-11-26 15:00:06 -0800220 ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800221 ::aos::Queue<::y2012::control_loops::AccessoriesQueue::Message> accessories_;
222
223 ::std::atomic<bool> run_{true};
224};
225
226class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler {
227 public:
228 void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
229 left_drivetrain_talon_ = ::std::move(t);
230 }
231
232 void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
233 right_drivetrain_talon_ = ::std::move(t);
234 }
235
236 private:
237 virtual void Read() override {
Austin Schuh2a671df2016-11-26 15:00:06 -0800238 drivetrain_queue.output.FetchAnother();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800239 }
240
241 virtual void Write() override {
Austin Schuh2a671df2016-11-26 15:00:06 -0800242 auto &queue = drivetrain_queue.output;
Brian Silvermanc71537c2016-01-01 13:43:14 -0800243 LOG_STRUCT(DEBUG, "will output", *queue);
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800244 left_drivetrain_talon_->SetSpeed(-queue->left_voltage / 12.0);
245 right_drivetrain_talon_->SetSpeed(queue->right_voltage / 12.0);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800246 }
247
248 virtual void Stop() override {
249 LOG(WARNING, "drivetrain output too old\n");
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800250 left_drivetrain_talon_->SetDisabled();
251 right_drivetrain_talon_->SetDisabled();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800252 }
253
254 ::std::unique_ptr<Talon> left_drivetrain_talon_;
255 ::std::unique_ptr<Talon> right_drivetrain_talon_;
256};
257
258class AccessoriesWriter : public ::frc971::wpilib::LoopOutputHandler {
259 public:
260 void set_talon1(::std::unique_ptr<Talon> t) {
261 talon1_ = ::std::move(t);
262 }
263
264 void set_talon2(::std::unique_ptr<Talon> t) {
265 talon2_ = ::std::move(t);
266 }
267
268 private:
269 virtual void Read() override {
270 ::y2012::control_loops::accessories_queue.output.FetchAnother();
271 }
272
273 virtual void Write() override {
274 auto &queue = ::y2012::control_loops::accessories_queue.output;
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800275 talon1_->SetSpeed(queue->sticks[0]);
276 talon2_->SetSpeed(queue->sticks[1]);
Brian Silvermanc71537c2016-01-01 13:43:14 -0800277 LOG_STRUCT(DEBUG, "will output", *queue);
278 }
279
280 virtual void Stop() override {
281 LOG(WARNING, "shooter output too old\n");
Brian Silverman6eaa2d82017-02-04 20:48:30 -0800282 talon1_->SetDisabled();
283 talon2_->SetDisabled();
Brian Silvermanc71537c2016-01-01 13:43:14 -0800284 }
285
286 ::std::unique_ptr<Talon> talon1_, talon2_;
287};
288
Brian Silverman5090c432016-01-02 14:44:26 -0800289class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800290 public:
291 ::std::unique_ptr<Encoder> make_encoder(int index) {
292 return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
293 Encoder::k4X);
294 }
295
Brian Silverman5090c432016-01-02 14:44:26 -0800296 void Run() override {
Brian Silvermanc71537c2016-01-01 13:43:14 -0800297 ::aos::InitNRT();
298 ::aos::SetCurrentThreadName("StartCompetition");
299
300 ::frc971::wpilib::JoystickSender joystick_sender;
301 ::std::thread joystick_thread(::std::ref(joystick_sender));
302
303 SensorReader reader;
304
305 reader.set_drivetrain_left_encoder(make_encoder(0));
306 reader.set_drivetrain_right_encoder(make_encoder(1));
307
308 ::std::thread reader_thread(::std::ref(reader));
309
310 DrivetrainWriter drivetrain_writer;
311 drivetrain_writer.set_left_drivetrain_talon(
312 ::std::unique_ptr<Talon>(new Talon(3)));
313 drivetrain_writer.set_right_drivetrain_talon(
314 ::std::unique_ptr<Talon>(new Talon(4)));
315 ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
316
317 ::y2012::wpilib::AccessoriesWriter accessories_writer;
318 accessories_writer.set_talon1(::std::unique_ptr<Talon>(new Talon(5)));
319 accessories_writer.set_talon2(::std::unique_ptr<Talon>(new Talon(6)));
320 ::std::thread accessories_writer_thread(::std::ref(accessories_writer));
321
322 ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
323 new ::frc971::wpilib::BufferedPcm());
324 SolenoidWriter solenoid_writer(pcm);
325 solenoid_writer.set_drivetrain_high(pcm->MakeSolenoid(0));
326 solenoid_writer.set_drivetrain_low(pcm->MakeSolenoid(2));
327 solenoid_writer.set_s1(pcm->MakeSolenoid(1));
328 solenoid_writer.set_s2(pcm->MakeSolenoid(3));
329 solenoid_writer.set_s3(pcm->MakeSolenoid(4));
330
331 ::std::thread solenoid_thread(::std::ref(solenoid_writer));
332
333 // Wait forever. Not much else to do...
Brian Silverman5090c432016-01-02 14:44:26 -0800334 while (true) {
335 const int r = select(0, nullptr, nullptr, nullptr, nullptr);
336 if (r != 0) {
337 PLOG(WARNING, "infinite select failed");
338 } else {
339 PLOG(WARNING, "infinite select succeeded??\n");
340 }
341 }
Brian Silvermanc71537c2016-01-01 13:43:14 -0800342
343 LOG(ERROR, "Exiting WPILibRobot\n");
344
345 joystick_sender.Quit();
346 joystick_thread.join();
347 reader.Quit();
348 reader_thread.join();
349
350 drivetrain_writer.Quit();
351 drivetrain_writer_thread.join();
352 accessories_writer.Quit();
353 accessories_writer_thread.join();
354
355 ::aos::Cleanup();
356 }
357};
358
359} // namespace wpilib
360} // namespace y2012
361
362
Brian Silverman5090c432016-01-02 14:44:26 -0800363AOS_ROBOT_CLASS(::y2012::wpilib::WPILibRobot);