blob: b3a5953998a3c6ad038d126d6785445029b5b0ec [file] [log] [blame]
Sabina Davisabeae332019-02-01 21:12:57 -08001#include <unistd.h>
2
3#include <array>
4#include <chrono>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07005#include <cinttypes>
Sabina Davisabeae332019-02-01 21:12:57 -08006#include <cmath>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07007#include <cstdio>
8#include <cstring>
Sabina Davisabeae332019-02-01 21:12:57 -08009#include <functional>
Tyler Chatowbf0609c2021-07-31 16:13:27 -070010#include <memory>
Sabina Davisabeae332019-02-01 21:12:57 -080011#include <mutex>
12#include <thread>
13
James Kuszmaul7077d342021-06-09 20:23:58 -070014#include "ctre/phoenix/CANifier.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070015
Sabina Davisabeae332019-02-01 21:12:57 -080016#include "frc971/wpilib/ahal/AnalogInput.h"
17#include "frc971/wpilib/ahal/Counter.h"
18#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
19#include "frc971/wpilib/ahal/DriverStation.h"
20#include "frc971/wpilib/ahal/Encoder.h"
21#include "frc971/wpilib/ahal/VictorSP.h"
22#undef ERROR
23
Philipp Schrader790cb542023-07-05 21:06:52 -070024#include "ctre/phoenix/motorcontrol/can/TalonSRX.h"
25
Sabina Davisabeae332019-02-01 21:12:57 -080026#include "aos/commonmath.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070027#include "aos/events/event_loop.h"
28#include "aos/events/shm_event_loop.h"
Sabina Davisabeae332019-02-01 21:12:57 -080029#include "aos/init.h"
30#include "aos/logging/logging.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070031#include "aos/realtime.h"
Sabina Davisabeae332019-02-01 21:12:57 -080032#include "aos/time/time.h"
Sabina Davisabeae332019-02-01 21:12:57 -080033#include "aos/util/log_interval.h"
34#include "aos/util/phased_loop.h"
35#include "aos/util/wrapping_counter.h"
Austin Schuhed5b26d2019-12-05 20:51:59 -080036#include "frc971/autonomous/auto_mode_generated.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070037#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
James Kuszmaul7077d342021-06-09 20:23:58 -070038#include "frc971/input/robot_state_generated.h"
Sabina Davisabeae332019-02-01 21:12:57 -080039#include "frc971/wpilib/ADIS16448.h"
Austin Schuhc1d6f832019-02-15 23:22:17 -080040#include "frc971/wpilib/buffered_pcm.h"
41#include "frc971/wpilib/buffered_solenoid.h"
Sabina Davisabeae332019-02-01 21:12:57 -080042#include "frc971/wpilib/dma.h"
Sabina Davisd004fd62019-02-02 23:51:46 -080043#include "frc971/wpilib/drivetrain_writer.h"
Sabina Davisabeae332019-02-01 21:12:57 -080044#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisabeae332019-02-01 21:12:57 -080045#include "frc971/wpilib/joystick_sender.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070046#include "frc971/wpilib/logging_generated.h"
Sabina Davisabeae332019-02-01 21:12:57 -080047#include "frc971/wpilib/loop_output_handler.h"
48#include "frc971/wpilib/pdp_fetcher.h"
Sabina Davisadc58542019-02-01 22:23:00 -080049#include "frc971/wpilib/sensor_reader.h"
Sabina Davisabeae332019-02-01 21:12:57 -080050#include "frc971/wpilib/wpilib_robot_base.h"
Austin Schuhed5b26d2019-12-05 20:51:59 -080051#include "y2019/camera_log_generated.h"
Sabina Davis7be49f32019-02-02 00:30:19 -080052#include "y2019/constants.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070053#include "y2019/control_loops/drivetrain/camera_generated.h"
54#include "y2019/control_loops/superstructure/superstructure_output_generated.h"
Maxwell Hendersoncb78f352024-01-15 00:27:16 -080055#include "y2019/control_loops/superstructure/superstructure_position_static.h"
Brian Silvermanf8b75252019-02-24 16:13:58 -080056#include "y2019/jevois/spi.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070057#include "y2019/status_light_generated.h"
Sabina Davisabeae332019-02-01 21:12:57 -080058
59#ifndef M_PI
60#define M_PI 3.14159265358979323846
61#endif
62
Sabina Davisabeae332019-02-01 21:12:57 -080063using ::aos::monotonic_clock;
James Kuszmaul7077d342021-06-09 20:23:58 -070064using ::y2019::constants::Values;
Alex Perrycb7da4b2019-08-28 19:35:56 -070065namespace superstructure = ::y2019::control_loops::superstructure;
Sabina Davisabeae332019-02-01 21:12:57 -080066namespace chrono = ::std::chrono;
Vinay Sivae52a6b32021-07-10 15:19:26 -070067using std::make_unique;
Sabina Davisabeae332019-02-01 21:12:57 -080068
69namespace y2019 {
70namespace wpilib {
71namespace {
72
73constexpr double kMaxBringupPower = 12.0;
74
75// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
76// DMA stuff and then removing the * 2.0 in *_translate.
77// The low bit is direction.
78
79// TODO(brian): Use ::std::max instead once we have C++14 so that can be
80// constexpr.
81template <typename T>
82constexpr T max(T a, T b) {
83 return (a > b) ? a : b;
84}
85
86template <typename T, typename... Rest>
87constexpr T max(T a, T b, T c, Rest... rest) {
88 return max(max(a, b), c, rest...);
89}
90
91double drivetrain_translate(int32_t in) {
Sabina Davis7be49f32019-02-02 00:30:19 -080092 return ((static_cast<double>(in) /
93 Values::kDrivetrainEncoderCountsPerRevolution()) *
Sabina Davisabeae332019-02-01 21:12:57 -080094 (2.0 * M_PI)) *
95 Values::kDrivetrainEncoderRatio() *
Sabina Davis7be49f32019-02-02 00:30:19 -080096 control_loops::drivetrain::kWheelRadius;
Sabina Davisabeae332019-02-01 21:12:57 -080097}
98
99double drivetrain_velocity_translate(double in) {
Sabina Davis7be49f32019-02-02 00:30:19 -0800100 return (((1.0 / in) / Values::kDrivetrainCyclesPerRevolution()) *
Sabina Davisabeae332019-02-01 21:12:57 -0800101 (2.0 * M_PI)) *
102 Values::kDrivetrainEncoderRatio() *
Sabina Davis7be49f32019-02-02 00:30:19 -0800103 control_loops::drivetrain::kWheelRadius;
Sabina Davisabeae332019-02-01 21:12:57 -0800104}
105
Alex Perry5fb5ff22019-02-09 21:53:17 -0800106double elevator_pot_translate(double voltage) {
107 return voltage * Values::kElevatorPotRatio() *
Austin Schuhed7f8632019-02-15 23:12:20 -0800108 (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800109}
110
111double wrist_pot_translate(double voltage) {
Austin Schuhed7f8632019-02-15 23:12:20 -0800112 return voltage * Values::kWristPotRatio() * (5.0 /*turns*/ / 5.0 /*volts*/) *
Alex Perry5fb5ff22019-02-09 21:53:17 -0800113 (2 * M_PI /*radians*/);
114}
115
116double stilts_pot_translate(double voltage) {
117 return voltage * Values::kStiltsPotRatio() *
118 (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
119}
120
Sabina Davisabeae332019-02-01 21:12:57 -0800121constexpr double kMaxFastEncoderPulsesPerSecond =
Alex Perry5fb5ff22019-02-09 21:53:17 -0800122 max(Values::kMaxDrivetrainEncoderPulsesPerSecond(),
123 Values::kMaxIntakeEncoderPulsesPerSecond());
Sabina Davisabeae332019-02-01 21:12:57 -0800124static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
125 "fast encoders are too fast");
Sabina Davisabeae332019-02-01 21:12:57 -0800126constexpr double kMaxMediumEncoderPulsesPerSecond =
Alex Perry5fb5ff22019-02-09 21:53:17 -0800127 max(Values::kMaxElevatorEncoderPulsesPerSecond(),
128 Values::kMaxWristEncoderPulsesPerSecond());
Theo Bafrali00e42272019-02-12 01:07:46 -0800129
Sabina Davisabeae332019-02-01 21:12:57 -0800130static_assert(kMaxMediumEncoderPulsesPerSecond <= 400000,
131 "medium encoders are too fast");
132
133// Class to send position messages with sensor readings to our loops.
Sabina Davisadc58542019-02-01 22:23:00 -0800134class SensorReader : public ::frc971::wpilib::SensorReader {
Sabina Davisabeae332019-02-01 21:12:57 -0800135 public:
Austin Schuh217a9782019-12-21 23:02:50 -0800136 SensorReader(::aos::ShmEventLoop *event_loop)
Austin Schuha250b2d2019-05-27 16:14:02 -0700137 : ::frc971::wpilib::SensorReader(event_loop),
138 auto_mode_sender_(
139 event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800140 "/autonomous")),
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700141 superstructure_position_sender_(
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800142 event_loop->MakeSender<superstructure::PositionStatic>(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700143 "/superstructure")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700144 drivetrain_position_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700145 event_loop
146 ->MakeSender<::frc971::control_loops::drivetrain::Position>(
147 "/drivetrain")) {
Sabina Davisabeae332019-02-01 21:12:57 -0800148 // Set to filter out anything shorter than 1/4 of the minimum pulse width
149 // we should ever see.
Austin Schuh45a549f2019-02-02 15:43:56 -0800150 UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
151 UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);
Sabina Davisabeae332019-02-01 21:12:57 -0800152 }
153
Alex Perry5fb5ff22019-02-09 21:53:17 -0800154 // Elevator
155
156 void set_elevator_encoder(::std::unique_ptr<frc::Encoder> encoder) {
157 medium_encoder_filter_.Add(encoder.get());
158 elevator_encoder_.set_encoder(::std::move(encoder));
159 }
160
161 void set_elevator_absolute_pwm(
162 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
163 elevator_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
164 }
165
166 void set_elevator_potentiometer(
167 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
168 elevator_encoder_.set_potentiometer(::std::move(potentiometer));
169 }
170
171 // Intake
172
173 void set_intake_encoder(::std::unique_ptr<frc::Encoder> encoder) {
174 medium_encoder_filter_.Add(encoder.get());
175 intake_encoder_.set_encoder(::std::move(encoder));
176 }
177
178 void set_intake_absolute_pwm(
179 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
180 intake_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
181 }
182
183 // Wrist
184
185 void set_wrist_encoder(::std::unique_ptr<frc::Encoder> encoder) {
186 medium_encoder_filter_.Add(encoder.get());
187 wrist_encoder_.set_encoder(::std::move(encoder));
188 }
189
190 void set_wrist_absolute_pwm(
191 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
192 wrist_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
193 }
194
195 void set_wrist_potentiometer(
196 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
197 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
198 }
199
200 // Stilts
201
202 void set_stilts_encoder(::std::unique_ptr<frc::Encoder> encoder) {
203 medium_encoder_filter_.Add(encoder.get());
204 stilts_encoder_.set_encoder(::std::move(encoder));
205 }
206
207 void set_stilts_absolute_pwm(
208 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
209 stilts_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
210 }
211
212 void set_stilts_potentiometer(
213 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
214 stilts_encoder_.set_potentiometer(::std::move(potentiometer));
215 }
216
Austin Schuhe2f22482019-04-13 23:05:43 -0700217 void set_platform_left_detect(
218 ::std::unique_ptr<frc::DigitalInput> platform_left_detect) {
219 platform_left_detect_ = ::std::move(platform_left_detect);
220 }
221
222 void set_platform_right_detect(
223 ::std::unique_ptr<frc::DigitalInput> platform_right_detect) {
224 platform_right_detect_ = ::std::move(platform_right_detect);
225 }
226
Austin Schuh461e1182019-02-17 14:56:44 -0800227 // Vacuum pressure sensor
228 void set_vacuum_sensor(int port) {
229 vacuum_sensor_ = make_unique<frc::AnalogInput>(port);
230 }
231
Austin Schuha9644062019-03-28 14:31:52 -0700232 // Auto mode switches.
233 void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
234 autonomous_modes_.at(i) = ::std::move(sensor);
235 }
236
Sabina Davis399dbd82019-02-01 23:06:08 -0800237 void RunIteration() override {
Sabina Davisabeae332019-02-01 21:12:57 -0800238 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700239 auto builder = drivetrain_position_sender_.MakeBuilder();
240 frc971::control_loops::drivetrain::Position::Builder drivetrain_builder =
241 builder.MakeBuilder<frc971::control_loops::drivetrain::Position>();
242 drivetrain_builder.add_left_encoder(
243 drivetrain_translate(drivetrain_left_encoder_->GetRaw()));
244 drivetrain_builder.add_left_speed(
245 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));
Sabina Davisabeae332019-02-01 21:12:57 -0800246
Alex Perrycb7da4b2019-08-28 19:35:56 -0700247 drivetrain_builder.add_right_encoder(
248 -drivetrain_translate(drivetrain_right_encoder_->GetRaw()));
249 drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
250 drivetrain_right_encoder_->GetPeriod()));
Sabina Davisabeae332019-02-01 21:12:57 -0800251
milind1f1dca32021-07-03 13:50:07 -0700252 builder.CheckOk(builder.Send(drivetrain_builder.Finish()));
Sabina Davisabeae332019-02-01 21:12:57 -0800253 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800254 const auto values = constants::GetValues();
255
256 {
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800257 aos::Sender<superstructure::PositionStatic>::StaticBuilder builder =
258 superstructure_position_sender_.MakeStaticBuilder();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800259
260 // Elevator
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800261 CopyPosition(elevator_encoder_, builder->add_elevator(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800262 Values::kElevatorEncoderCountsPerRevolution(),
263 Values::kElevatorEncoderRatio(), elevator_pot_translate,
264 false, values.elevator.potentiometer_offset);
265 // Intake
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800266 CopyPosition(intake_encoder_, builder->add_intake_joint(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800267 Values::kIntakeEncoderCountsPerRevolution(),
268 Values::kIntakeEncoderRatio(), false);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800269 // Wrist
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800270 CopyPosition(wrist_encoder_, builder->add_wrist(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800271 Values::kWristEncoderCountsPerRevolution(),
272 Values::kWristEncoderRatio(), wrist_pot_translate, false,
273 values.wrist.potentiometer_offset);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800274 // Stilts
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800275 CopyPosition(stilts_encoder_, builder->add_stilts(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800276 Values::kStiltsEncoderCountsPerRevolution(),
277 Values::kStiltsEncoderRatio(), stilts_pot_translate, false,
278 values.stilts.potentiometer_offset);
279
Austin Schuh461e1182019-02-17 14:56:44 -0800280 // Suction
281 constexpr float kMinVoltage = 0.5;
282 constexpr float kMaxVoltage = 2.1;
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800283 builder->set_suction_pressure(
Austin Schuh461e1182019-02-17 14:56:44 -0800284 (vacuum_sensor_->GetVoltage() - kMinVoltage) /
Alex Perrycb7da4b2019-08-28 19:35:56 -0700285 (kMaxVoltage - kMinVoltage));
Austin Schuh461e1182019-02-17 14:56:44 -0800286
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800287 builder->set_platform_left_detect(!platform_left_detect_->Get());
288 builder->set_platform_right_detect(!platform_right_detect_->Get());
Austin Schuhe2f22482019-04-13 23:05:43 -0700289
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800290 builder.CheckOk(builder.Send());
Alex Perry5fb5ff22019-02-09 21:53:17 -0800291 }
Austin Schuha9644062019-03-28 14:31:52 -0700292
293 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700294 auto builder = auto_mode_sender_.MakeBuilder();
295
296 uint32_t mode = 0;
Austin Schuha9644062019-03-28 14:31:52 -0700297 for (size_t i = 0; i < autonomous_modes_.size(); ++i) {
298 if (autonomous_modes_[i] && autonomous_modes_[i]->Get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700299 mode |= 1 << i;
Austin Schuha9644062019-03-28 14:31:52 -0700300 }
301 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700302
303 auto auto_mode_builder =
304 builder.MakeBuilder<frc971::autonomous::AutonomousMode>();
305
306 auto_mode_builder.add_mode(mode);
307
milind1f1dca32021-07-03 13:50:07 -0700308 builder.CheckOk(builder.Send(auto_mode_builder.Finish()));
Austin Schuha9644062019-03-28 14:31:52 -0700309 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800310 }
311
312 private:
Austin Schuha250b2d2019-05-27 16:14:02 -0700313 ::aos::Sender<::frc971::autonomous::AutonomousMode> auto_mode_sender_;
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800314 ::aos::Sender<superstructure::PositionStatic> superstructure_position_sender_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700315 ::aos::Sender<::frc971::control_loops::drivetrain::Position>
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700316 drivetrain_position_sender_;
Austin Schuha250b2d2019-05-27 16:14:02 -0700317
Alex Perry5fb5ff22019-02-09 21:53:17 -0800318 ::frc971::wpilib::AbsoluteEncoderAndPotentiometer elevator_encoder_,
319 wrist_encoder_, stilts_encoder_;
320
Austin Schuhe2f22482019-04-13 23:05:43 -0700321 ::std::unique_ptr<frc::DigitalInput> platform_left_detect_;
322 ::std::unique_ptr<frc::DigitalInput> platform_right_detect_;
323
Austin Schuh461e1182019-02-17 14:56:44 -0800324 ::std::unique_ptr<frc::AnalogInput> vacuum_sensor_;
325
Austin Schuha9644062019-03-28 14:31:52 -0700326 ::std::array<::std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
327
Alex Perry5fb5ff22019-02-09 21:53:17 -0800328 ::frc971::wpilib::AbsoluteEncoder intake_encoder_;
Alex Perry5fb5ff22019-02-09 21:53:17 -0800329};
330
Brian Silvermanf8b75252019-02-24 16:13:58 -0800331class CameraReader {
332 public:
Austin Schuh8a633d52019-05-12 15:04:01 -0700333 CameraReader(::aos::EventLoop *event_loop)
334 : camera_frame_sender_(
335 event_loop
336 ->MakeSender<::y2019::control_loops::drivetrain::CameraFrame>(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800337 "/camera")),
Austin Schuh5671a8c2019-05-19 17:01:04 -0700338 camera_log_fetcher_(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800339 event_loop->MakeFetcher<::y2019::CameraLog>("/camera")) {}
Austin Schuh8a633d52019-05-12 15:04:01 -0700340
Brian Silvermanf8b75252019-02-24 16:13:58 -0800341 CameraReader(const CameraReader &) = delete;
342 CameraReader &operator=(const CameraReader &) = delete;
343
344 void set_spi(frc::SPI *spi) {
345 spi_ = spi;
346 spi_->SetClockRate(1e6);
347 spi_->SetChipSelectActiveHigh();
James Kuszmaul9776b392023-01-14 14:08:08 -0800348 spi_->SetMode(frc::SPI::Mode::kMode3);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800349 }
350
Brian Silverman7ecf0672019-03-02 15:30:03 -0800351 void set_activate_usb(std::unique_ptr<frc::DigitalInput> activate_usb) {
352 activate_usb_ = std::move(activate_usb);
353 }
354
355 void set_activate_passthrough(
356 std::unique_ptr<frc::DigitalInput> activate_passthrough) {
357 activate_passthrough_ = std::move(activate_passthrough);
358 }
359
Brian Silvermanf8b75252019-02-24 16:13:58 -0800360 void DoSpiTransaction() {
361 using namespace frc971::jevois;
362 RoborioToTeensy to_teensy{};
363 to_teensy.realtime_now = aos::realtime_clock::now();
Austin Schuh5671a8c2019-05-19 17:01:04 -0700364 camera_log_fetcher_.Fetch();
Brian Silverman7ecf0672019-03-02 15:30:03 -0800365 if (activate_usb_ && !activate_usb_->Get()) {
366 to_teensy.camera_command = CameraCommand::kUsb;
367 } else if (activate_passthrough_ && !activate_passthrough_->Get()) {
368 to_teensy.camera_command = CameraCommand::kCameraPassthrough;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700369 } else if (camera_log_fetcher_.get() && camera_log_fetcher_->log()) {
Austin Schuh4e2629d2019-03-28 14:44:37 -0700370 to_teensy.camera_command = CameraCommand::kLog;
Brian Silverman7ecf0672019-03-02 15:30:03 -0800371 } else {
372 to_teensy.camera_command = CameraCommand::kNormal;
373 }
Brian Silvermanf8b75252019-02-24 16:13:58 -0800374
375 std::array<char, spi_transfer_size() + 1> to_send{};
376 {
377 const auto to_send_data =
Austin Schuhb72be802022-01-02 12:26:28 -0800378 absl::MakeSpan(to_send).last(spi_transfer_size());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800379 const auto encoded = SpiPackToTeensy(to_teensy);
380 std::copy(encoded.begin(), encoded.end(), to_send_data.begin());
381 }
382 rx_clearer_.ClearRxFifo();
383 // First, send recieve a dummy byte because the Teensy can't control what it
384 // sends for the first byte.
385 std::array<char, spi_transfer_size() + 1> to_receive;
Austin Schuhb72be802022-01-02 12:26:28 -0800386 DoTransaction(absl::Span<char>(to_send), absl::Span<char>(to_receive));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800387 const auto unpacked = SpiUnpackToRoborio(
Austin Schuhb72be802022-01-02 12:26:28 -0800388 absl::MakeSpan(to_receive).last(spi_transfer_size()));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800389 if (!unpacked) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700390 AOS_LOG(INFO, "Decoding SPI data failed\n");
Brian Silvermanf8b75252019-02-24 16:13:58 -0800391 return;
392 }
393
Alex Perrycb7da4b2019-08-28 19:35:56 -0700394 const aos::monotonic_clock::time_point now = aos::monotonic_clock::now();
Brian Silvermanc41fb862019-03-02 21:14:46 -0800395 for (const auto &received : unpacked->frames) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700396 auto builder = camera_frame_sender_.MakeBuilder();
397
398 std::array<
399 flatbuffers::Offset<y2019::control_loops::drivetrain::CameraTarget>,
400 3>
401 targets;
402
403 for (size_t i = 0; i < received.targets.size(); ++i) {
404 y2019::control_loops::drivetrain::CameraTarget::Builder
405 camera_target_builder = builder.MakeBuilder<
406 y2019::control_loops::drivetrain::CameraTarget>();
407
408 camera_target_builder.add_distance(received.targets[i].distance);
409 camera_target_builder.add_height(received.targets[i].height);
410 camera_target_builder.add_heading(received.targets[i].heading);
411 camera_target_builder.add_skew(received.targets[i].skew);
412
413 targets[i] = camera_target_builder.Finish();
414 }
415
416 flatbuffers::Offset<flatbuffers::Vector<
417 flatbuffers::Offset<y2019::control_loops::drivetrain::CameraTarget>>>
418 targets_offset = builder.fbb()->CreateVector(targets.begin(),
419 received.targets.size());
420
421 y2019::control_loops::drivetrain::CameraFrame::Builder
422 camera_frame_builder =
423 builder
424 .MakeBuilder<y2019::control_loops::drivetrain::CameraFrame>();
425
426 camera_frame_builder.add_targets(targets_offset);
427
James Kuszmaule08f04e2019-05-01 21:46:50 -0500428 // Add an extra 10ms delay to account for unmodeled delays that Austin
429 // thinks exists.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700430 camera_frame_builder.add_timestamp(
James Kuszmaule08f04e2019-05-01 21:46:50 -0500431 std::chrono::nanoseconds(
432 (now - received.age - ::std::chrono::milliseconds(10))
Alex Perrycb7da4b2019-08-28 19:35:56 -0700433 .time_since_epoch())
434 .count());
435 camera_frame_builder.add_camera(received.camera_index);
milind1f1dca32021-07-03 13:50:07 -0700436 builder.CheckOk(builder.Send(camera_frame_builder.Finish()));
Brian Silvermanc41fb862019-03-02 21:14:46 -0800437 }
Brian Silvermanf8b75252019-02-24 16:13:58 -0800438
439 if (dummy_spi_) {
440 uint8_t dummy_send, dummy_receive;
441 dummy_spi_->Transaction(&dummy_send, &dummy_receive, 1);
442 }
443 }
444
Austin Schuhb72be802022-01-02 12:26:28 -0800445 void DoTransaction(absl::Span<char> to_send, absl::Span<char> to_receive) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700446 AOS_CHECK_EQ(to_send.size(), to_receive.size());
Austin Schuhb72be802022-01-02 12:26:28 -0800447 const int result = spi_->Transaction(
Brian Silvermanf8b75252019-02-24 16:13:58 -0800448 reinterpret_cast<uint8_t *>(to_send.data()),
449 reinterpret_cast<uint8_t *>(to_receive.data()), to_send.size());
Austin Schuhb72be802022-01-02 12:26:28 -0800450 if (result == static_cast<int>(to_send.size())) {
Brian Silvermanf8b75252019-02-24 16:13:58 -0800451 return;
452 }
453 if (result == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700454 AOS_LOG(INFO, "SPI::Transaction of %zd bytes failed\n", to_send.size());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800455 return;
456 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700457 AOS_LOG(FATAL, "SPI::Transaction returned something weird\n");
Brian Silvermanf8b75252019-02-24 16:13:58 -0800458 }
459
460 void SetDummySPI(frc::SPI::Port port) {
461 dummy_spi_.reset(new frc::SPI(port));
462 // Pick the same settings here in case the roboRIO decides to try something
463 // stupid when switching.
464 if (dummy_spi_) {
465 dummy_spi_->SetClockRate(1e5);
466 dummy_spi_->SetChipSelectActiveLow();
James Kuszmaul9776b392023-01-14 14:08:08 -0800467 dummy_spi_->SetMode(frc::SPI::Mode::kMode3);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800468 }
469 }
470
471 private:
Austin Schuh8a633d52019-05-12 15:04:01 -0700472 ::aos::Sender<::y2019::control_loops::drivetrain::CameraFrame>
473 camera_frame_sender_;
Austin Schuh5671a8c2019-05-19 17:01:04 -0700474 ::aos::Fetcher<::y2019::CameraLog> camera_log_fetcher_;
Austin Schuh8a633d52019-05-12 15:04:01 -0700475
Brian Silvermanf8b75252019-02-24 16:13:58 -0800476 frc::SPI *spi_ = nullptr;
477 ::std::unique_ptr<frc::SPI> dummy_spi_;
478
Brian Silverman7ecf0672019-03-02 15:30:03 -0800479 std::unique_ptr<frc::DigitalInput> activate_usb_;
480 std::unique_ptr<frc::DigitalInput> activate_passthrough_;
481
Brian Silvermanf8b75252019-02-24 16:13:58 -0800482 frc971::wpilib::SpiRxClearer rx_clearer_;
483};
484
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700485class SuperstructureWriter
Alex Perrycb7da4b2019-08-28 19:35:56 -0700486 : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
Alex Perry5fb5ff22019-02-09 21:53:17 -0800487 public:
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800488 SuperstructureWriter(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -0700489 : ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
490 event_loop, "/superstructure"),
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800491 robot_state_fetcher_(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700492 event_loop->MakeFetcher<::aos::RobotState>("/aos")) {}
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800493
Alex Perry5fb5ff22019-02-09 21:53:17 -0800494 void set_elevator_victor(::std::unique_ptr<::frc::VictorSP> t) {
495 elevator_victor_ = ::std::move(t);
496 }
497
Austin Schuh461e1182019-02-17 14:56:44 -0800498 void set_suction_victor(::std::unique_ptr<::frc::VictorSP> t) {
499 suction_victor_ = ::std::move(t);
500 }
501
Alex Perry5fb5ff22019-02-09 21:53:17 -0800502 void set_intake_victor(::std::unique_ptr<::frc::VictorSP> t) {
503 intake_victor_ = ::std::move(t);
504 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800505
506 void set_wrist_victor(::std::unique_ptr<::frc::VictorSP> t) {
507 wrist_victor_ = ::std::move(t);
508 }
509
510 void set_stilts_victor(::std::unique_ptr<::frc::VictorSP> t) {
511 stilts_victor_ = ::std::move(t);
512 }
513
514 private:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700515 void Write(const superstructure::Output &output) override {
516 elevator_victor_->SetSpeed(::aos::Clip(output.elevator_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800517 -kMaxBringupPower,
518 kMaxBringupPower) /
519 12.0);
520
Alex Perrycb7da4b2019-08-28 19:35:56 -0700521 intake_victor_->SetSpeed(::aos::Clip(output.intake_joint_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800522 -kMaxBringupPower, kMaxBringupPower) /
523 12.0);
524
Alex Perrycb7da4b2019-08-28 19:35:56 -0700525 wrist_victor_->SetSpeed(::aos::Clip(-output.wrist_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800526 -kMaxBringupPower, kMaxBringupPower) /
527 12.0);
528
Alex Perrycb7da4b2019-08-28 19:35:56 -0700529 stilts_victor_->SetSpeed(::aos::Clip(output.stilts_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800530 -kMaxBringupPower, kMaxBringupPower) /
531 12.0);
Austin Schuh461e1182019-02-17 14:56:44 -0800532
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800533 robot_state_fetcher_.Fetch();
534 const double battery_voltage = robot_state_fetcher_.get()
Alex Perrycb7da4b2019-08-28 19:35:56 -0700535 ? robot_state_fetcher_->voltage_battery()
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800536 : 12.0;
Austin Schuhc2ee66b2019-02-19 13:37:46 -0800537
538 // Throw a fast low pass filter on the battery voltage so we don't respond
539 // too fast to noise.
540 filtered_battery_voltage_ =
541 0.5 * filtered_battery_voltage_ + 0.5 * battery_voltage;
542
543 suction_victor_->SetSpeed(::aos::Clip(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700544 output.pump_voltage() / filtered_battery_voltage_, -1.0, 1.0));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800545 }
546
Austin Schuh461e1182019-02-17 14:56:44 -0800547 void Stop() override {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700548 AOS_LOG(WARNING, "Superstructure output too old.\n");
Alex Perry5fb5ff22019-02-09 21:53:17 -0800549
550 elevator_victor_->SetDisabled();
551 intake_victor_->SetDisabled();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800552 wrist_victor_->SetDisabled();
553 stilts_victor_->SetDisabled();
Austin Schuh461e1182019-02-17 14:56:44 -0800554 suction_victor_->SetDisabled();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800555 }
556
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800557 ::aos::Fetcher<::aos::RobotState> robot_state_fetcher_;
558
Alex Perry5fb5ff22019-02-09 21:53:17 -0800559 ::std::unique_ptr<::frc::VictorSP> elevator_victor_, intake_victor_,
Austin Schuh461e1182019-02-17 14:56:44 -0800560 wrist_victor_, stilts_victor_, suction_victor_;
Austin Schuhc2ee66b2019-02-19 13:37:46 -0800561
562 double filtered_battery_voltage_ = 12.0;
Sabina Davisabeae332019-02-01 21:12:57 -0800563};
564
Austin Schuhc1d6f832019-02-15 23:22:17 -0800565class SolenoidWriter {
566 public:
Austin Schuhff973552019-05-19 16:49:28 -0700567 SolenoidWriter(::aos::EventLoop *event_loop)
568 : event_loop_(event_loop),
Alex Perrycb7da4b2019-08-28 19:35:56 -0700569 superstructure_fetcher_(
570 event_loop->MakeFetcher<superstructure::Output>("/superstructure")),
571 status_light_fetcher_(
572 event_loop->MakeFetcher<::y2019::StatusLight>("/superstructure")),
573 pneumatics_to_log_sender_(
574 event_loop->MakeSender<::frc971::wpilib::PneumaticsToLog>("/aos")) {
Austin Schuh315275b2021-06-20 14:30:31 -0700575 event_loop_->SetRuntimeRealtimePriority(27);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700576
577 event_loop_->AddPhasedLoop([this](int iterations) { Loop(iterations); },
578 ::std::chrono::milliseconds(20),
579 ::std::chrono::milliseconds(1));
580 }
Austin Schuhc1d6f832019-02-15 23:22:17 -0800581
Austin Schuh461e1182019-02-17 14:56:44 -0800582 void set_big_suction_cup(int index0, int index1) {
583 big_suction_cup0_ = pcm_.MakeSolenoid(index0);
584 big_suction_cup1_ = pcm_.MakeSolenoid(index1);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800585 }
Austin Schuh461e1182019-02-17 14:56:44 -0800586 void set_small_suction_cup(int index0, int index1) {
587 small_suction_cup0_ = pcm_.MakeSolenoid(index0);
588 small_suction_cup1_ = pcm_.MakeSolenoid(index1);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800589 }
590
591 void set_intake_roller_talon(
592 ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonSRX> t) {
593 intake_rollers_talon_ = ::std::move(t);
Austin Schuh23a51632019-02-19 16:50:36 -0800594 intake_rollers_talon_->ConfigContinuousCurrentLimit(10.0, 0);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800595 intake_rollers_talon_->EnableCurrentLimit(true);
596 }
597
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700598 void Loop(const int iterations) {
599 if (iterations != 1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700600 AOS_LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700601 }
Austin Schuhc1d6f832019-02-15 23:22:17 -0800602
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700603 {
604 superstructure_fetcher_.Fetch();
605 if (superstructure_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700606 big_suction_cup0_->Set(
607 !superstructure_fetcher_->intake_suction_bottom());
608 big_suction_cup1_->Set(
609 !superstructure_fetcher_->intake_suction_bottom());
610 small_suction_cup0_->Set(superstructure_fetcher_->intake_suction_top());
611 small_suction_cup1_->Set(superstructure_fetcher_->intake_suction_top());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700612
613 intake_rollers_talon_->Set(
614 ctre::phoenix::motorcontrol::ControlMode::PercentOutput,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700615 ::aos::Clip(superstructure_fetcher_->intake_roller_voltage(),
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700616 -kMaxBringupPower, kMaxBringupPower) /
617 12.0);
618 }
619 }
620
621 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700622 auto builder = pneumatics_to_log_sender_.MakeBuilder();
623
624 ::frc971::wpilib::PneumaticsToLog::Builder to_log_builder =
625 builder.MakeBuilder<frc971::wpilib::PneumaticsToLog>();
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700626
627 pcm_.Flush();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 to_log_builder.add_read_solenoids(pcm_.GetAll());
milind1f1dca32021-07-03 13:50:07 -0700629 (void)builder.Send(to_log_builder.Finish());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700630 }
631
632 status_light_fetcher_.Fetch();
633 // If we don't have a light request (or it's an old one), we are borked.
634 // Flash the red light slowly.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700635 StatusLightT color;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700636 if (!status_light_fetcher_.get() ||
Austin Schuhad154822019-12-27 15:45:13 -0800637 status_light_fetcher_.context().monotonic_event_time +
Alex Perrycb7da4b2019-08-28 19:35:56 -0700638 chrono::milliseconds(100) <
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700639 event_loop_->monotonic_now()) {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700640 color.red = 0.0;
641 color.green = 0.0;
642 color.blue = 0.0;
643
644 ++light_flash_;
645 if (light_flash_ > 10) {
646 color.red = 0.5;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800647 }
648
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700649 if (light_flash_ > 20) {
650 light_flash_ = 0;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800651 }
652
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700653 } else {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700654 status_light_fetcher_->UnPackTo(&color);
Sabina Davisc6329342019-03-01 20:44:42 -0800655 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700656 SetColor(color);
Sabina Davisc6329342019-03-01 20:44:42 -0800657 }
658
Alex Perrycb7da4b2019-08-28 19:35:56 -0700659 void SetColor(const StatusLightT status_light) {
Sabina Davisc6329342019-03-01 20:44:42 -0800660 // Save CAN bandwidth and CPU at the cost of RT. Only change the light when
661 // it actually changes. This is pretty low priority anyways.
662 static int time_since_last_send = 0;
663 ++time_since_last_send;
664 if (time_since_last_send > 10) {
665 time_since_last_send = 0;
666 }
667 if (status_light.green != last_green_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800668 canifier_.SetLEDOutput(status_light.green,
669 ::ctre::phoenix::CANifier::LEDChannelA);
Sabina Davisc6329342019-03-01 20:44:42 -0800670 last_green_ = status_light.green;
671 }
672
673 if (status_light.blue != last_blue_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800674 canifier_.SetLEDOutput(status_light.blue,
675 ::ctre::phoenix::CANifier::LEDChannelC);
Sabina Davisc6329342019-03-01 20:44:42 -0800676 last_blue_ = status_light.blue;
677 }
678
679 if (status_light.red != last_red_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800680 canifier_.SetLEDOutput(status_light.red,
681 ::ctre::phoenix::CANifier::LEDChannelB);
Sabina Davisc6329342019-03-01 20:44:42 -0800682 last_red_ = status_light.red;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800683 }
684 }
685
Austin Schuhc1d6f832019-02-15 23:22:17 -0800686 private:
Austin Schuhff973552019-05-19 16:49:28 -0700687 ::aos::EventLoop *event_loop_;
688
Austin Schuhc1d6f832019-02-15 23:22:17 -0800689 ::frc971::wpilib::BufferedPcm pcm_;
690
Austin Schuh461e1182019-02-17 14:56:44 -0800691 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> big_suction_cup0_,
692 big_suction_cup1_, small_suction_cup0_, small_suction_cup1_;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800693
694 ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonSRX>
695 intake_rollers_talon_;
696
Alex Perrycb7da4b2019-08-28 19:35:56 -0700697 ::aos::Fetcher<::y2019::control_loops::superstructure::Output>
Austin Schuhff973552019-05-19 16:49:28 -0700698 superstructure_fetcher_;
699 ::aos::Fetcher<::y2019::StatusLight> status_light_fetcher_;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800700
Alex Perrycb7da4b2019-08-28 19:35:56 -0700701 aos::Sender<::frc971::wpilib::PneumaticsToLog> pneumatics_to_log_sender_;
702
Sabina Davisc6329342019-03-01 20:44:42 -0800703 ::ctre::phoenix::CANifier canifier_{0};
704
Sabina Davisc6329342019-03-01 20:44:42 -0800705 double last_red_ = -1.0;
706 double last_green_ = -1.0;
707 double last_blue_ = -1.0;
708
709 int light_flash_ = 0;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800710};
711
Sabina Davisabeae332019-02-01 21:12:57 -0800712class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
713 public:
714 ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
715 return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
716 frc::Encoder::k4X);
717 }
718
719 void Run() override {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700720 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Austin Schuhc5fa6d92022-02-25 14:36:28 -0800721 aos::configuration::ReadConfig("aos_config.json");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700722
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700723 // Thread 1.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700724 ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700725 ::frc971::wpilib::JoystickSender joystick_sender(
726 &joystick_sender_event_loop);
727 AddLoop(&joystick_sender_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800728
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700729 // Thread 2.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700730 ::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700731 ::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
732 AddLoop(&pdp_fetcher_event_loop);
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800733
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700734 // Thread 3.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700735 ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700736 SensorReader sensor_reader(&sensor_reader_event_loop);
737 sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
738 sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
Sabina Davisabeae332019-02-01 21:12:57 -0800739
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700740 sensor_reader.set_elevator_encoder(make_encoder(4));
741 sensor_reader.set_elevator_absolute_pwm(make_unique<frc::DigitalInput>(4));
742 sensor_reader.set_elevator_potentiometer(make_unique<frc::AnalogInput>(4));
Sabina Davisabeae332019-02-01 21:12:57 -0800743
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700744 sensor_reader.set_wrist_encoder(make_encoder(5));
745 sensor_reader.set_wrist_absolute_pwm(make_unique<frc::DigitalInput>(5));
746 sensor_reader.set_wrist_potentiometer(make_unique<frc::AnalogInput>(5));
Sabina Davisabeae332019-02-01 21:12:57 -0800747
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700748 sensor_reader.set_intake_encoder(make_encoder(2));
749 sensor_reader.set_intake_absolute_pwm(make_unique<frc::DigitalInput>(2));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800750
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700751 sensor_reader.set_stilts_encoder(make_encoder(3));
752 sensor_reader.set_stilts_absolute_pwm(make_unique<frc::DigitalInput>(3));
753 sensor_reader.set_stilts_potentiometer(make_unique<frc::AnalogInput>(3));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800754
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700755 sensor_reader.set_pwm_trigger(true);
756 sensor_reader.set_vacuum_sensor(7);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800757
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700758 sensor_reader.set_platform_right_detect(make_unique<frc::DigitalInput>(6));
759 sensor_reader.set_platform_left_detect(make_unique<frc::DigitalInput>(7));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800760
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700761 sensor_reader.set_autonomous_mode(0, make_unique<frc::DigitalInput>(22));
762 sensor_reader.set_autonomous_mode(0, make_unique<frc::DigitalInput>(23));
763 AddLoop(&sensor_reader_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800764
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700765 // Thread 4.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700766 ::aos::ShmEventLoop imu_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700767 CameraReader camera_reader(&imu_event_loop);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800768 frc::SPI camera_spi(frc::SPI::Port::kOnboardCS3);
769 camera_reader.set_spi(&camera_spi);
770 camera_reader.SetDummySPI(frc::SPI::Port::kOnboardCS2);
Brian Silverman7ecf0672019-03-02 15:30:03 -0800771 // Austin says 8, 9, 24, and 25 are good options to choose from for these.
772 camera_reader.set_activate_usb(make_unique<frc::DigitalInput>(24));
773 camera_reader.set_activate_passthrough(make_unique<frc::DigitalInput>(25));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800774
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800775 auto imu_trigger = make_unique<frc::DigitalInput>(0);
James Kuszmaul7077d342021-06-09 20:23:58 -0700776 ::frc971::wpilib::ADIS16448 imu(
777 &imu_event_loop, frc::SPI::Port::kOnboardCS1, imu_trigger.get());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800778 imu.set_spi_idle_callback(
779 [&camera_reader]() { camera_reader.DoSpiTransaction(); });
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800780 auto imu_reset = make_unique<frc::DigitalOutput>(1);
Sabina Davisabeae332019-02-01 21:12:57 -0800781 imu.set_reset(imu_reset.get());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700782 AddLoop(&imu_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800783
784 // While as of 2/9/18 the drivetrain Victors are SPX, it appears as though
785 // they are identical, as far as DrivetrainWriter is concerned, to the SP
786 // variety so all the Victors are written as SPs.
787
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700788 // Thread 5.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700789 ::aos::ShmEventLoop output_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700790 ::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
Sabina Davisd004fd62019-02-02 23:51:46 -0800791 drivetrain_writer.set_left_controller0(
Sabina Davis1b84afa2019-02-09 01:20:21 -0800792 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), true);
Sabina Davisd004fd62019-02-02 23:51:46 -0800793 drivetrain_writer.set_right_controller0(
Sabina Davis1b84afa2019-02-09 01:20:21 -0800794 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);
Sabina Davisabeae332019-02-01 21:12:57 -0800795
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700796 SuperstructureWriter superstructure_writer(&output_event_loop);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800797 superstructure_writer.set_elevator_victor(
Alex Perry5fb5ff22019-02-09 21:53:17 -0800798 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(4)));
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800799 // TODO(austin): Do the vacuum
Austin Schuh461e1182019-02-17 14:56:44 -0800800 superstructure_writer.set_suction_victor(
801 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(6)));
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800802 superstructure_writer.set_intake_victor(
803 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(2)));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800804 superstructure_writer.set_wrist_victor(
805 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(5)));
806 superstructure_writer.set_stilts_victor(
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800807 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(3)));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700808 AddLoop(&output_event_loop);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800809
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700810 // Thread 6.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700811 ::aos::ShmEventLoop solenoid_writer_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700812 SolenoidWriter solenoid_writer(&solenoid_writer_event_loop);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800813 solenoid_writer.set_intake_roller_talon(
814 make_unique<::ctre::phoenix::motorcontrol::can::TalonSRX>(10));
Austin Schuh461e1182019-02-17 14:56:44 -0800815 solenoid_writer.set_big_suction_cup(0, 1);
816 solenoid_writer.set_small_suction_cup(2, 3);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700817 AddLoop(&solenoid_writer_event_loop);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800818
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700819 RunLoops();
Sabina Davisabeae332019-02-01 21:12:57 -0800820 }
821};
822
823} // namespace
824} // namespace wpilib
825} // namespace y2019
826
827AOS_ROBOT_CLASS(::y2019::wpilib::WPILibRobot);