blob: 16102f4ba1e67d3fc0162a97ec0891cb29dc0def [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080069namespace y2019::wpilib {
Sabina Davisabeae332019-02-01 21:12:57 -080070namespace {
71
72constexpr double kMaxBringupPower = 12.0;
73
74// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
75// DMA stuff and then removing the * 2.0 in *_translate.
76// The low bit is direction.
77
78// TODO(brian): Use ::std::max instead once we have C++14 so that can be
79// constexpr.
80template <typename T>
81constexpr T max(T a, T b) {
82 return (a > b) ? a : b;
83}
84
85template <typename T, typename... Rest>
86constexpr T max(T a, T b, T c, Rest... rest) {
87 return max(max(a, b), c, rest...);
88}
89
90double drivetrain_translate(int32_t in) {
Sabina Davis7be49f32019-02-02 00:30:19 -080091 return ((static_cast<double>(in) /
92 Values::kDrivetrainEncoderCountsPerRevolution()) *
Sabina Davisabeae332019-02-01 21:12:57 -080093 (2.0 * M_PI)) *
94 Values::kDrivetrainEncoderRatio() *
Sabina Davis7be49f32019-02-02 00:30:19 -080095 control_loops::drivetrain::kWheelRadius;
Sabina Davisabeae332019-02-01 21:12:57 -080096}
97
98double drivetrain_velocity_translate(double in) {
Sabina Davis7be49f32019-02-02 00:30:19 -080099 return (((1.0 / in) / Values::kDrivetrainCyclesPerRevolution()) *
Sabina Davisabeae332019-02-01 21:12:57 -0800100 (2.0 * M_PI)) *
101 Values::kDrivetrainEncoderRatio() *
Sabina Davis7be49f32019-02-02 00:30:19 -0800102 control_loops::drivetrain::kWheelRadius;
Sabina Davisabeae332019-02-01 21:12:57 -0800103}
104
Alex Perry5fb5ff22019-02-09 21:53:17 -0800105double elevator_pot_translate(double voltage) {
106 return voltage * Values::kElevatorPotRatio() *
Austin Schuhed7f8632019-02-15 23:12:20 -0800107 (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800108}
109
110double wrist_pot_translate(double voltage) {
Austin Schuhed7f8632019-02-15 23:12:20 -0800111 return voltage * Values::kWristPotRatio() * (5.0 /*turns*/ / 5.0 /*volts*/) *
Alex Perry5fb5ff22019-02-09 21:53:17 -0800112 (2 * M_PI /*radians*/);
113}
114
115double stilts_pot_translate(double voltage) {
116 return voltage * Values::kStiltsPotRatio() *
117 (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
118}
119
Sabina Davisabeae332019-02-01 21:12:57 -0800120constexpr double kMaxFastEncoderPulsesPerSecond =
Alex Perry5fb5ff22019-02-09 21:53:17 -0800121 max(Values::kMaxDrivetrainEncoderPulsesPerSecond(),
122 Values::kMaxIntakeEncoderPulsesPerSecond());
Sabina Davisabeae332019-02-01 21:12:57 -0800123static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
124 "fast encoders are too fast");
Sabina Davisabeae332019-02-01 21:12:57 -0800125constexpr double kMaxMediumEncoderPulsesPerSecond =
Alex Perry5fb5ff22019-02-09 21:53:17 -0800126 max(Values::kMaxElevatorEncoderPulsesPerSecond(),
127 Values::kMaxWristEncoderPulsesPerSecond());
Theo Bafrali00e42272019-02-12 01:07:46 -0800128
Sabina Davisabeae332019-02-01 21:12:57 -0800129static_assert(kMaxMediumEncoderPulsesPerSecond <= 400000,
130 "medium encoders are too fast");
131
132// Class to send position messages with sensor readings to our loops.
Sabina Davisadc58542019-02-01 22:23:00 -0800133class SensorReader : public ::frc971::wpilib::SensorReader {
Sabina Davisabeae332019-02-01 21:12:57 -0800134 public:
Austin Schuh217a9782019-12-21 23:02:50 -0800135 SensorReader(::aos::ShmEventLoop *event_loop)
Austin Schuha250b2d2019-05-27 16:14:02 -0700136 : ::frc971::wpilib::SensorReader(event_loop),
137 auto_mode_sender_(
138 event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800139 "/autonomous")),
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700140 superstructure_position_sender_(
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800141 event_loop->MakeSender<superstructure::PositionStatic>(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700142 "/superstructure")),
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700143 drivetrain_position_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700144 event_loop
145 ->MakeSender<::frc971::control_loops::drivetrain::Position>(
146 "/drivetrain")) {
Sabina Davisabeae332019-02-01 21:12:57 -0800147 // Set to filter out anything shorter than 1/4 of the minimum pulse width
148 // we should ever see.
Austin Schuh45a549f2019-02-02 15:43:56 -0800149 UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
150 UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);
Sabina Davisabeae332019-02-01 21:12:57 -0800151 }
152
Alex Perry5fb5ff22019-02-09 21:53:17 -0800153 // Elevator
154
155 void set_elevator_encoder(::std::unique_ptr<frc::Encoder> encoder) {
156 medium_encoder_filter_.Add(encoder.get());
157 elevator_encoder_.set_encoder(::std::move(encoder));
158 }
159
160 void set_elevator_absolute_pwm(
161 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
162 elevator_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
163 }
164
165 void set_elevator_potentiometer(
166 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
167 elevator_encoder_.set_potentiometer(::std::move(potentiometer));
168 }
169
170 // Intake
171
172 void set_intake_encoder(::std::unique_ptr<frc::Encoder> encoder) {
173 medium_encoder_filter_.Add(encoder.get());
174 intake_encoder_.set_encoder(::std::move(encoder));
175 }
176
177 void set_intake_absolute_pwm(
178 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
179 intake_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
180 }
181
182 // Wrist
183
184 void set_wrist_encoder(::std::unique_ptr<frc::Encoder> encoder) {
185 medium_encoder_filter_.Add(encoder.get());
186 wrist_encoder_.set_encoder(::std::move(encoder));
187 }
188
189 void set_wrist_absolute_pwm(
190 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
191 wrist_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
192 }
193
194 void set_wrist_potentiometer(
195 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
196 wrist_encoder_.set_potentiometer(::std::move(potentiometer));
197 }
198
199 // Stilts
200
201 void set_stilts_encoder(::std::unique_ptr<frc::Encoder> encoder) {
202 medium_encoder_filter_.Add(encoder.get());
203 stilts_encoder_.set_encoder(::std::move(encoder));
204 }
205
206 void set_stilts_absolute_pwm(
207 ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
208 stilts_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
209 }
210
211 void set_stilts_potentiometer(
212 ::std::unique_ptr<frc::AnalogInput> potentiometer) {
213 stilts_encoder_.set_potentiometer(::std::move(potentiometer));
214 }
215
Austin Schuhe2f22482019-04-13 23:05:43 -0700216 void set_platform_left_detect(
217 ::std::unique_ptr<frc::DigitalInput> platform_left_detect) {
218 platform_left_detect_ = ::std::move(platform_left_detect);
219 }
220
221 void set_platform_right_detect(
222 ::std::unique_ptr<frc::DigitalInput> platform_right_detect) {
223 platform_right_detect_ = ::std::move(platform_right_detect);
224 }
225
Austin Schuh461e1182019-02-17 14:56:44 -0800226 // Vacuum pressure sensor
227 void set_vacuum_sensor(int port) {
228 vacuum_sensor_ = make_unique<frc::AnalogInput>(port);
229 }
230
Austin Schuha9644062019-03-28 14:31:52 -0700231 // Auto mode switches.
232 void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
233 autonomous_modes_.at(i) = ::std::move(sensor);
234 }
235
Sabina Davis399dbd82019-02-01 23:06:08 -0800236 void RunIteration() override {
Sabina Davisabeae332019-02-01 21:12:57 -0800237 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700238 auto builder = drivetrain_position_sender_.MakeBuilder();
239 frc971::control_loops::drivetrain::Position::Builder drivetrain_builder =
240 builder.MakeBuilder<frc971::control_loops::drivetrain::Position>();
241 drivetrain_builder.add_left_encoder(
242 drivetrain_translate(drivetrain_left_encoder_->GetRaw()));
243 drivetrain_builder.add_left_speed(
244 drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));
Sabina Davisabeae332019-02-01 21:12:57 -0800245
Alex Perrycb7da4b2019-08-28 19:35:56 -0700246 drivetrain_builder.add_right_encoder(
247 -drivetrain_translate(drivetrain_right_encoder_->GetRaw()));
248 drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
249 drivetrain_right_encoder_->GetPeriod()));
Sabina Davisabeae332019-02-01 21:12:57 -0800250
milind1f1dca32021-07-03 13:50:07 -0700251 builder.CheckOk(builder.Send(drivetrain_builder.Finish()));
Sabina Davisabeae332019-02-01 21:12:57 -0800252 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800253 const auto values = constants::GetValues();
254
255 {
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800256 aos::Sender<superstructure::PositionStatic>::StaticBuilder builder =
257 superstructure_position_sender_.MakeStaticBuilder();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800258
259 // Elevator
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800260 CopyPosition(elevator_encoder_, builder->add_elevator(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800261 Values::kElevatorEncoderCountsPerRevolution(),
262 Values::kElevatorEncoderRatio(), elevator_pot_translate,
263 false, values.elevator.potentiometer_offset);
264 // Intake
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800265 CopyPosition(intake_encoder_, builder->add_intake_joint(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800266 Values::kIntakeEncoderCountsPerRevolution(),
267 Values::kIntakeEncoderRatio(), false);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800268 // Wrist
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800269 CopyPosition(wrist_encoder_, builder->add_wrist(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800270 Values::kWristEncoderCountsPerRevolution(),
271 Values::kWristEncoderRatio(), wrist_pot_translate, false,
272 values.wrist.potentiometer_offset);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800273 // Stilts
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800274 CopyPosition(stilts_encoder_, builder->add_stilts(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800275 Values::kStiltsEncoderCountsPerRevolution(),
276 Values::kStiltsEncoderRatio(), stilts_pot_translate, false,
277 values.stilts.potentiometer_offset);
278
Austin Schuh461e1182019-02-17 14:56:44 -0800279 // Suction
280 constexpr float kMinVoltage = 0.5;
281 constexpr float kMaxVoltage = 2.1;
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800282 builder->set_suction_pressure(
Austin Schuh461e1182019-02-17 14:56:44 -0800283 (vacuum_sensor_->GetVoltage() - kMinVoltage) /
Alex Perrycb7da4b2019-08-28 19:35:56 -0700284 (kMaxVoltage - kMinVoltage));
Austin Schuh461e1182019-02-17 14:56:44 -0800285
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800286 builder->set_platform_left_detect(!platform_left_detect_->Get());
287 builder->set_platform_right_detect(!platform_right_detect_->Get());
Austin Schuhe2f22482019-04-13 23:05:43 -0700288
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800289 builder.CheckOk(builder.Send());
Alex Perry5fb5ff22019-02-09 21:53:17 -0800290 }
Austin Schuha9644062019-03-28 14:31:52 -0700291
292 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 auto builder = auto_mode_sender_.MakeBuilder();
294
295 uint32_t mode = 0;
Austin Schuha9644062019-03-28 14:31:52 -0700296 for (size_t i = 0; i < autonomous_modes_.size(); ++i) {
297 if (autonomous_modes_[i] && autonomous_modes_[i]->Get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700298 mode |= 1 << i;
Austin Schuha9644062019-03-28 14:31:52 -0700299 }
300 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700301
302 auto auto_mode_builder =
303 builder.MakeBuilder<frc971::autonomous::AutonomousMode>();
304
305 auto_mode_builder.add_mode(mode);
306
milind1f1dca32021-07-03 13:50:07 -0700307 builder.CheckOk(builder.Send(auto_mode_builder.Finish()));
Austin Schuha9644062019-03-28 14:31:52 -0700308 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800309 }
310
311 private:
Austin Schuha250b2d2019-05-27 16:14:02 -0700312 ::aos::Sender<::frc971::autonomous::AutonomousMode> auto_mode_sender_;
Maxwell Hendersoncb78f352024-01-15 00:27:16 -0800313 ::aos::Sender<superstructure::PositionStatic> superstructure_position_sender_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700314 ::aos::Sender<::frc971::control_loops::drivetrain::Position>
Austin Schuhbd0a40f2019-06-30 14:56:31 -0700315 drivetrain_position_sender_;
Austin Schuha250b2d2019-05-27 16:14:02 -0700316
Alex Perry5fb5ff22019-02-09 21:53:17 -0800317 ::frc971::wpilib::AbsoluteEncoderAndPotentiometer elevator_encoder_,
318 wrist_encoder_, stilts_encoder_;
319
Austin Schuhe2f22482019-04-13 23:05:43 -0700320 ::std::unique_ptr<frc::DigitalInput> platform_left_detect_;
321 ::std::unique_ptr<frc::DigitalInput> platform_right_detect_;
322
Austin Schuh461e1182019-02-17 14:56:44 -0800323 ::std::unique_ptr<frc::AnalogInput> vacuum_sensor_;
324
Austin Schuha9644062019-03-28 14:31:52 -0700325 ::std::array<::std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
326
Alex Perry5fb5ff22019-02-09 21:53:17 -0800327 ::frc971::wpilib::AbsoluteEncoder intake_encoder_;
Alex Perry5fb5ff22019-02-09 21:53:17 -0800328};
329
Brian Silvermanf8b75252019-02-24 16:13:58 -0800330class CameraReader {
331 public:
Austin Schuh8a633d52019-05-12 15:04:01 -0700332 CameraReader(::aos::EventLoop *event_loop)
333 : camera_frame_sender_(
334 event_loop
335 ->MakeSender<::y2019::control_loops::drivetrain::CameraFrame>(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800336 "/camera")),
Austin Schuh5671a8c2019-05-19 17:01:04 -0700337 camera_log_fetcher_(
Austin Schuhed5b26d2019-12-05 20:51:59 -0800338 event_loop->MakeFetcher<::y2019::CameraLog>("/camera")) {}
Austin Schuh8a633d52019-05-12 15:04:01 -0700339
Brian Silvermanf8b75252019-02-24 16:13:58 -0800340 CameraReader(const CameraReader &) = delete;
341 CameraReader &operator=(const CameraReader &) = delete;
342
343 void set_spi(frc::SPI *spi) {
344 spi_ = spi;
345 spi_->SetClockRate(1e6);
346 spi_->SetChipSelectActiveHigh();
James Kuszmaul9776b392023-01-14 14:08:08 -0800347 spi_->SetMode(frc::SPI::Mode::kMode3);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800348 }
349
Brian Silverman7ecf0672019-03-02 15:30:03 -0800350 void set_activate_usb(std::unique_ptr<frc::DigitalInput> activate_usb) {
351 activate_usb_ = std::move(activate_usb);
352 }
353
354 void set_activate_passthrough(
355 std::unique_ptr<frc::DigitalInput> activate_passthrough) {
356 activate_passthrough_ = std::move(activate_passthrough);
357 }
358
Brian Silvermanf8b75252019-02-24 16:13:58 -0800359 void DoSpiTransaction() {
360 using namespace frc971::jevois;
361 RoborioToTeensy to_teensy{};
362 to_teensy.realtime_now = aos::realtime_clock::now();
Austin Schuh5671a8c2019-05-19 17:01:04 -0700363 camera_log_fetcher_.Fetch();
Brian Silverman7ecf0672019-03-02 15:30:03 -0800364 if (activate_usb_ && !activate_usb_->Get()) {
365 to_teensy.camera_command = CameraCommand::kUsb;
366 } else if (activate_passthrough_ && !activate_passthrough_->Get()) {
367 to_teensy.camera_command = CameraCommand::kCameraPassthrough;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700368 } else if (camera_log_fetcher_.get() && camera_log_fetcher_->log()) {
Austin Schuh4e2629d2019-03-28 14:44:37 -0700369 to_teensy.camera_command = CameraCommand::kLog;
Brian Silverman7ecf0672019-03-02 15:30:03 -0800370 } else {
371 to_teensy.camera_command = CameraCommand::kNormal;
372 }
Brian Silvermanf8b75252019-02-24 16:13:58 -0800373
374 std::array<char, spi_transfer_size() + 1> to_send{};
375 {
376 const auto to_send_data =
Austin Schuhb72be802022-01-02 12:26:28 -0800377 absl::MakeSpan(to_send).last(spi_transfer_size());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800378 const auto encoded = SpiPackToTeensy(to_teensy);
379 std::copy(encoded.begin(), encoded.end(), to_send_data.begin());
380 }
381 rx_clearer_.ClearRxFifo();
382 // First, send recieve a dummy byte because the Teensy can't control what it
383 // sends for the first byte.
384 std::array<char, spi_transfer_size() + 1> to_receive;
Austin Schuhb72be802022-01-02 12:26:28 -0800385 DoTransaction(absl::Span<char>(to_send), absl::Span<char>(to_receive));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800386 const auto unpacked = SpiUnpackToRoborio(
Austin Schuhb72be802022-01-02 12:26:28 -0800387 absl::MakeSpan(to_receive).last(spi_transfer_size()));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800388 if (!unpacked) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700389 AOS_LOG(INFO, "Decoding SPI data failed\n");
Brian Silvermanf8b75252019-02-24 16:13:58 -0800390 return;
391 }
392
Alex Perrycb7da4b2019-08-28 19:35:56 -0700393 const aos::monotonic_clock::time_point now = aos::monotonic_clock::now();
Brian Silvermanc41fb862019-03-02 21:14:46 -0800394 for (const auto &received : unpacked->frames) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700395 auto builder = camera_frame_sender_.MakeBuilder();
396
397 std::array<
398 flatbuffers::Offset<y2019::control_loops::drivetrain::CameraTarget>,
399 3>
400 targets;
401
402 for (size_t i = 0; i < received.targets.size(); ++i) {
403 y2019::control_loops::drivetrain::CameraTarget::Builder
404 camera_target_builder = builder.MakeBuilder<
405 y2019::control_loops::drivetrain::CameraTarget>();
406
407 camera_target_builder.add_distance(received.targets[i].distance);
408 camera_target_builder.add_height(received.targets[i].height);
409 camera_target_builder.add_heading(received.targets[i].heading);
410 camera_target_builder.add_skew(received.targets[i].skew);
411
412 targets[i] = camera_target_builder.Finish();
413 }
414
415 flatbuffers::Offset<flatbuffers::Vector<
416 flatbuffers::Offset<y2019::control_loops::drivetrain::CameraTarget>>>
417 targets_offset = builder.fbb()->CreateVector(targets.begin(),
418 received.targets.size());
419
420 y2019::control_loops::drivetrain::CameraFrame::Builder
421 camera_frame_builder =
422 builder
423 .MakeBuilder<y2019::control_loops::drivetrain::CameraFrame>();
424
425 camera_frame_builder.add_targets(targets_offset);
426
James Kuszmaule08f04e2019-05-01 21:46:50 -0500427 // Add an extra 10ms delay to account for unmodeled delays that Austin
428 // thinks exists.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700429 camera_frame_builder.add_timestamp(
James Kuszmaule08f04e2019-05-01 21:46:50 -0500430 std::chrono::nanoseconds(
431 (now - received.age - ::std::chrono::milliseconds(10))
Alex Perrycb7da4b2019-08-28 19:35:56 -0700432 .time_since_epoch())
433 .count());
434 camera_frame_builder.add_camera(received.camera_index);
milind1f1dca32021-07-03 13:50:07 -0700435 builder.CheckOk(builder.Send(camera_frame_builder.Finish()));
Brian Silvermanc41fb862019-03-02 21:14:46 -0800436 }
Brian Silvermanf8b75252019-02-24 16:13:58 -0800437
438 if (dummy_spi_) {
439 uint8_t dummy_send, dummy_receive;
440 dummy_spi_->Transaction(&dummy_send, &dummy_receive, 1);
441 }
442 }
443
Austin Schuhb72be802022-01-02 12:26:28 -0800444 void DoTransaction(absl::Span<char> to_send, absl::Span<char> to_receive) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700445 AOS_CHECK_EQ(to_send.size(), to_receive.size());
Austin Schuhb72be802022-01-02 12:26:28 -0800446 const int result = spi_->Transaction(
Brian Silvermanf8b75252019-02-24 16:13:58 -0800447 reinterpret_cast<uint8_t *>(to_send.data()),
448 reinterpret_cast<uint8_t *>(to_receive.data()), to_send.size());
Austin Schuhb72be802022-01-02 12:26:28 -0800449 if (result == static_cast<int>(to_send.size())) {
Brian Silvermanf8b75252019-02-24 16:13:58 -0800450 return;
451 }
452 if (result == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700453 AOS_LOG(INFO, "SPI::Transaction of %zd bytes failed\n", to_send.size());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800454 return;
455 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700456 AOS_LOG(FATAL, "SPI::Transaction returned something weird\n");
Brian Silvermanf8b75252019-02-24 16:13:58 -0800457 }
458
459 void SetDummySPI(frc::SPI::Port port) {
460 dummy_spi_.reset(new frc::SPI(port));
461 // Pick the same settings here in case the roboRIO decides to try something
462 // stupid when switching.
463 if (dummy_spi_) {
464 dummy_spi_->SetClockRate(1e5);
465 dummy_spi_->SetChipSelectActiveLow();
James Kuszmaul9776b392023-01-14 14:08:08 -0800466 dummy_spi_->SetMode(frc::SPI::Mode::kMode3);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800467 }
468 }
469
470 private:
Austin Schuh8a633d52019-05-12 15:04:01 -0700471 ::aos::Sender<::y2019::control_loops::drivetrain::CameraFrame>
472 camera_frame_sender_;
Austin Schuh5671a8c2019-05-19 17:01:04 -0700473 ::aos::Fetcher<::y2019::CameraLog> camera_log_fetcher_;
Austin Schuh8a633d52019-05-12 15:04:01 -0700474
Brian Silvermanf8b75252019-02-24 16:13:58 -0800475 frc::SPI *spi_ = nullptr;
476 ::std::unique_ptr<frc::SPI> dummy_spi_;
477
Brian Silverman7ecf0672019-03-02 15:30:03 -0800478 std::unique_ptr<frc::DigitalInput> activate_usb_;
479 std::unique_ptr<frc::DigitalInput> activate_passthrough_;
480
Brian Silvermanf8b75252019-02-24 16:13:58 -0800481 frc971::wpilib::SpiRxClearer rx_clearer_;
482};
483
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700484class SuperstructureWriter
Alex Perrycb7da4b2019-08-28 19:35:56 -0700485 : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
Alex Perry5fb5ff22019-02-09 21:53:17 -0800486 public:
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800487 SuperstructureWriter(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -0700488 : ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
489 event_loop, "/superstructure"),
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800490 robot_state_fetcher_(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700491 event_loop->MakeFetcher<::aos::RobotState>("/aos")) {}
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800492
Alex Perry5fb5ff22019-02-09 21:53:17 -0800493 void set_elevator_victor(::std::unique_ptr<::frc::VictorSP> t) {
494 elevator_victor_ = ::std::move(t);
495 }
496
Austin Schuh461e1182019-02-17 14:56:44 -0800497 void set_suction_victor(::std::unique_ptr<::frc::VictorSP> t) {
498 suction_victor_ = ::std::move(t);
499 }
500
Alex Perry5fb5ff22019-02-09 21:53:17 -0800501 void set_intake_victor(::std::unique_ptr<::frc::VictorSP> t) {
502 intake_victor_ = ::std::move(t);
503 }
Alex Perry5fb5ff22019-02-09 21:53:17 -0800504
505 void set_wrist_victor(::std::unique_ptr<::frc::VictorSP> t) {
506 wrist_victor_ = ::std::move(t);
507 }
508
509 void set_stilts_victor(::std::unique_ptr<::frc::VictorSP> t) {
510 stilts_victor_ = ::std::move(t);
511 }
512
513 private:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 void Write(const superstructure::Output &output) override {
515 elevator_victor_->SetSpeed(::aos::Clip(output.elevator_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800516 -kMaxBringupPower,
517 kMaxBringupPower) /
518 12.0);
519
Alex Perrycb7da4b2019-08-28 19:35:56 -0700520 intake_victor_->SetSpeed(::aos::Clip(output.intake_joint_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800521 -kMaxBringupPower, kMaxBringupPower) /
522 12.0);
523
Alex Perrycb7da4b2019-08-28 19:35:56 -0700524 wrist_victor_->SetSpeed(::aos::Clip(-output.wrist_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800525 -kMaxBringupPower, kMaxBringupPower) /
526 12.0);
527
Alex Perrycb7da4b2019-08-28 19:35:56 -0700528 stilts_victor_->SetSpeed(::aos::Clip(output.stilts_voltage(),
Alex Perry5fb5ff22019-02-09 21:53:17 -0800529 -kMaxBringupPower, kMaxBringupPower) /
530 12.0);
Austin Schuh461e1182019-02-17 14:56:44 -0800531
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800532 robot_state_fetcher_.Fetch();
533 const double battery_voltage = robot_state_fetcher_.get()
Alex Perrycb7da4b2019-08-28 19:35:56 -0700534 ? robot_state_fetcher_->voltage_battery()
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800535 : 12.0;
Austin Schuhc2ee66b2019-02-19 13:37:46 -0800536
537 // Throw a fast low pass filter on the battery voltage so we don't respond
538 // too fast to noise.
539 filtered_battery_voltage_ =
540 0.5 * filtered_battery_voltage_ + 0.5 * battery_voltage;
541
542 suction_victor_->SetSpeed(::aos::Clip(
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 output.pump_voltage() / filtered_battery_voltage_, -1.0, 1.0));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800544 }
545
Austin Schuh461e1182019-02-17 14:56:44 -0800546 void Stop() override {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700547 AOS_LOG(WARNING, "Superstructure output too old.\n");
Alex Perry5fb5ff22019-02-09 21:53:17 -0800548
549 elevator_victor_->SetDisabled();
550 intake_victor_->SetDisabled();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800551 wrist_victor_->SetDisabled();
552 stilts_victor_->SetDisabled();
Austin Schuh461e1182019-02-17 14:56:44 -0800553 suction_victor_->SetDisabled();
Alex Perry5fb5ff22019-02-09 21:53:17 -0800554 }
555
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800556 ::aos::Fetcher<::aos::RobotState> robot_state_fetcher_;
557
Alex Perry5fb5ff22019-02-09 21:53:17 -0800558 ::std::unique_ptr<::frc::VictorSP> elevator_victor_, intake_victor_,
Austin Schuh461e1182019-02-17 14:56:44 -0800559 wrist_victor_, stilts_victor_, suction_victor_;
Austin Schuhc2ee66b2019-02-19 13:37:46 -0800560
561 double filtered_battery_voltage_ = 12.0;
Sabina Davisabeae332019-02-01 21:12:57 -0800562};
563
Austin Schuhc1d6f832019-02-15 23:22:17 -0800564class SolenoidWriter {
565 public:
Austin Schuhff973552019-05-19 16:49:28 -0700566 SolenoidWriter(::aos::EventLoop *event_loop)
567 : event_loop_(event_loop),
Alex Perrycb7da4b2019-08-28 19:35:56 -0700568 superstructure_fetcher_(
569 event_loop->MakeFetcher<superstructure::Output>("/superstructure")),
570 status_light_fetcher_(
571 event_loop->MakeFetcher<::y2019::StatusLight>("/superstructure")),
572 pneumatics_to_log_sender_(
573 event_loop->MakeSender<::frc971::wpilib::PneumaticsToLog>("/aos")) {
Austin Schuh315275b2021-06-20 14:30:31 -0700574 event_loop_->SetRuntimeRealtimePriority(27);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700575
576 event_loop_->AddPhasedLoop([this](int iterations) { Loop(iterations); },
577 ::std::chrono::milliseconds(20),
578 ::std::chrono::milliseconds(1));
579 }
Austin Schuhc1d6f832019-02-15 23:22:17 -0800580
Austin Schuh461e1182019-02-17 14:56:44 -0800581 void set_big_suction_cup(int index0, int index1) {
582 big_suction_cup0_ = pcm_.MakeSolenoid(index0);
583 big_suction_cup1_ = pcm_.MakeSolenoid(index1);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800584 }
Austin Schuh461e1182019-02-17 14:56:44 -0800585 void set_small_suction_cup(int index0, int index1) {
586 small_suction_cup0_ = pcm_.MakeSolenoid(index0);
587 small_suction_cup1_ = pcm_.MakeSolenoid(index1);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800588 }
589
590 void set_intake_roller_talon(
591 ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonSRX> t) {
592 intake_rollers_talon_ = ::std::move(t);
Austin Schuh23a51632019-02-19 16:50:36 -0800593 intake_rollers_talon_->ConfigContinuousCurrentLimit(10.0, 0);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800594 intake_rollers_talon_->EnableCurrentLimit(true);
595 }
596
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700597 void Loop(const int iterations) {
598 if (iterations != 1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700599 AOS_LOG(DEBUG, "Solenoids skipped %d iterations\n", iterations - 1);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700600 }
Austin Schuhc1d6f832019-02-15 23:22:17 -0800601
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700602 {
603 superstructure_fetcher_.Fetch();
604 if (superstructure_fetcher_.get()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700605 big_suction_cup0_->Set(
606 !superstructure_fetcher_->intake_suction_bottom());
607 big_suction_cup1_->Set(
608 !superstructure_fetcher_->intake_suction_bottom());
609 small_suction_cup0_->Set(superstructure_fetcher_->intake_suction_top());
610 small_suction_cup1_->Set(superstructure_fetcher_->intake_suction_top());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700611
612 intake_rollers_talon_->Set(
613 ctre::phoenix::motorcontrol::ControlMode::PercentOutput,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700614 ::aos::Clip(superstructure_fetcher_->intake_roller_voltage(),
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700615 -kMaxBringupPower, kMaxBringupPower) /
616 12.0);
617 }
618 }
619
620 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700621 auto builder = pneumatics_to_log_sender_.MakeBuilder();
622
623 ::frc971::wpilib::PneumaticsToLog::Builder to_log_builder =
624 builder.MakeBuilder<frc971::wpilib::PneumaticsToLog>();
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700625
626 pcm_.Flush();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700627 to_log_builder.add_read_solenoids(pcm_.GetAll());
milind1f1dca32021-07-03 13:50:07 -0700628 (void)builder.Send(to_log_builder.Finish());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700629 }
630
631 status_light_fetcher_.Fetch();
632 // If we don't have a light request (or it's an old one), we are borked.
633 // Flash the red light slowly.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700634 StatusLightT color;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700635 if (!status_light_fetcher_.get() ||
Austin Schuhad154822019-12-27 15:45:13 -0800636 status_light_fetcher_.context().monotonic_event_time +
Alex Perrycb7da4b2019-08-28 19:35:56 -0700637 chrono::milliseconds(100) <
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700638 event_loop_->monotonic_now()) {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700639 color.red = 0.0;
640 color.green = 0.0;
641 color.blue = 0.0;
642
643 ++light_flash_;
644 if (light_flash_ > 10) {
645 color.red = 0.5;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800646 }
647
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700648 if (light_flash_ > 20) {
649 light_flash_ = 0;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800650 }
651
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700652 } else {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700653 status_light_fetcher_->UnPackTo(&color);
Sabina Davisc6329342019-03-01 20:44:42 -0800654 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700655 SetColor(color);
Sabina Davisc6329342019-03-01 20:44:42 -0800656 }
657
Alex Perrycb7da4b2019-08-28 19:35:56 -0700658 void SetColor(const StatusLightT status_light) {
Sabina Davisc6329342019-03-01 20:44:42 -0800659 // Save CAN bandwidth and CPU at the cost of RT. Only change the light when
660 // it actually changes. This is pretty low priority anyways.
661 static int time_since_last_send = 0;
662 ++time_since_last_send;
663 if (time_since_last_send > 10) {
664 time_since_last_send = 0;
665 }
666 if (status_light.green != last_green_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800667 canifier_.SetLEDOutput(status_light.green,
668 ::ctre::phoenix::CANifier::LEDChannelA);
Sabina Davisc6329342019-03-01 20:44:42 -0800669 last_green_ = status_light.green;
670 }
671
672 if (status_light.blue != last_blue_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800673 canifier_.SetLEDOutput(status_light.blue,
674 ::ctre::phoenix::CANifier::LEDChannelC);
Sabina Davisc6329342019-03-01 20:44:42 -0800675 last_blue_ = status_light.blue;
676 }
677
678 if (status_light.red != last_red_ || time_since_last_send == 0) {
Sabina Davis77a11cf2019-03-09 18:20:26 -0800679 canifier_.SetLEDOutput(status_light.red,
680 ::ctre::phoenix::CANifier::LEDChannelB);
Sabina Davisc6329342019-03-01 20:44:42 -0800681 last_red_ = status_light.red;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800682 }
683 }
684
Austin Schuhc1d6f832019-02-15 23:22:17 -0800685 private:
Austin Schuhff973552019-05-19 16:49:28 -0700686 ::aos::EventLoop *event_loop_;
687
Austin Schuhc1d6f832019-02-15 23:22:17 -0800688 ::frc971::wpilib::BufferedPcm pcm_;
689
Austin Schuh461e1182019-02-17 14:56:44 -0800690 ::std::unique_ptr<::frc971::wpilib::BufferedSolenoid> big_suction_cup0_,
691 big_suction_cup1_, small_suction_cup0_, small_suction_cup1_;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800692
693 ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonSRX>
694 intake_rollers_talon_;
695
Alex Perrycb7da4b2019-08-28 19:35:56 -0700696 ::aos::Fetcher<::y2019::control_loops::superstructure::Output>
Austin Schuhff973552019-05-19 16:49:28 -0700697 superstructure_fetcher_;
698 ::aos::Fetcher<::y2019::StatusLight> status_light_fetcher_;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800699
Alex Perrycb7da4b2019-08-28 19:35:56 -0700700 aos::Sender<::frc971::wpilib::PneumaticsToLog> pneumatics_to_log_sender_;
701
Sabina Davisc6329342019-03-01 20:44:42 -0800702 ::ctre::phoenix::CANifier canifier_{0};
703
Sabina Davisc6329342019-03-01 20:44:42 -0800704 double last_red_ = -1.0;
705 double last_green_ = -1.0;
706 double last_blue_ = -1.0;
707
708 int light_flash_ = 0;
Austin Schuhc1d6f832019-02-15 23:22:17 -0800709};
710
Sabina Davisabeae332019-02-01 21:12:57 -0800711class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
712 public:
713 ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
714 return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
715 frc::Encoder::k4X);
716 }
717
718 void Run() override {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700719 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Austin Schuhc5fa6d92022-02-25 14:36:28 -0800720 aos::configuration::ReadConfig("aos_config.json");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700721
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700722 // Thread 1.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700723 ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700724 ::frc971::wpilib::JoystickSender joystick_sender(
725 &joystick_sender_event_loop);
726 AddLoop(&joystick_sender_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800727
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700728 // Thread 2.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700729 ::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700730 ::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
731 AddLoop(&pdp_fetcher_event_loop);
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800732
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700733 // Thread 3.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700734 ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700735 SensorReader sensor_reader(&sensor_reader_event_loop);
736 sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
737 sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
Sabina Davisabeae332019-02-01 21:12:57 -0800738
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700739 sensor_reader.set_elevator_encoder(make_encoder(4));
740 sensor_reader.set_elevator_absolute_pwm(make_unique<frc::DigitalInput>(4));
741 sensor_reader.set_elevator_potentiometer(make_unique<frc::AnalogInput>(4));
Sabina Davisabeae332019-02-01 21:12:57 -0800742
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700743 sensor_reader.set_wrist_encoder(make_encoder(5));
744 sensor_reader.set_wrist_absolute_pwm(make_unique<frc::DigitalInput>(5));
745 sensor_reader.set_wrist_potentiometer(make_unique<frc::AnalogInput>(5));
Sabina Davisabeae332019-02-01 21:12:57 -0800746
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700747 sensor_reader.set_intake_encoder(make_encoder(2));
748 sensor_reader.set_intake_absolute_pwm(make_unique<frc::DigitalInput>(2));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800749
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700750 sensor_reader.set_stilts_encoder(make_encoder(3));
751 sensor_reader.set_stilts_absolute_pwm(make_unique<frc::DigitalInput>(3));
752 sensor_reader.set_stilts_potentiometer(make_unique<frc::AnalogInput>(3));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800753
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700754 sensor_reader.set_pwm_trigger(true);
755 sensor_reader.set_vacuum_sensor(7);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800756
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700757 sensor_reader.set_platform_right_detect(make_unique<frc::DigitalInput>(6));
758 sensor_reader.set_platform_left_detect(make_unique<frc::DigitalInput>(7));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800759
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700760 sensor_reader.set_autonomous_mode(0, make_unique<frc::DigitalInput>(22));
761 sensor_reader.set_autonomous_mode(0, make_unique<frc::DigitalInput>(23));
762 AddLoop(&sensor_reader_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800763
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700764 // Thread 4.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700765 ::aos::ShmEventLoop imu_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700766 CameraReader camera_reader(&imu_event_loop);
Brian Silvermanf8b75252019-02-24 16:13:58 -0800767 frc::SPI camera_spi(frc::SPI::Port::kOnboardCS3);
768 camera_reader.set_spi(&camera_spi);
769 camera_reader.SetDummySPI(frc::SPI::Port::kOnboardCS2);
Brian Silverman7ecf0672019-03-02 15:30:03 -0800770 // Austin says 8, 9, 24, and 25 are good options to choose from for these.
771 camera_reader.set_activate_usb(make_unique<frc::DigitalInput>(24));
772 camera_reader.set_activate_passthrough(make_unique<frc::DigitalInput>(25));
Brian Silvermanf8b75252019-02-24 16:13:58 -0800773
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800774 auto imu_trigger = make_unique<frc::DigitalInput>(0);
James Kuszmaul7077d342021-06-09 20:23:58 -0700775 ::frc971::wpilib::ADIS16448 imu(
776 &imu_event_loop, frc::SPI::Port::kOnboardCS1, imu_trigger.get());
Brian Silvermanf8b75252019-02-24 16:13:58 -0800777 imu.set_spi_idle_callback(
778 [&camera_reader]() { camera_reader.DoSpiTransaction(); });
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800779 auto imu_reset = make_unique<frc::DigitalOutput>(1);
Sabina Davisabeae332019-02-01 21:12:57 -0800780 imu.set_reset(imu_reset.get());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700781 AddLoop(&imu_event_loop);
Sabina Davisabeae332019-02-01 21:12:57 -0800782
783 // While as of 2/9/18 the drivetrain Victors are SPX, it appears as though
784 // they are identical, as far as DrivetrainWriter is concerned, to the SP
785 // variety so all the Victors are written as SPs.
786
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700787 // Thread 5.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700788 ::aos::ShmEventLoop output_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700789 ::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
Sabina Davisd004fd62019-02-02 23:51:46 -0800790 drivetrain_writer.set_left_controller0(
Sabina Davis1b84afa2019-02-09 01:20:21 -0800791 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), true);
Sabina Davisd004fd62019-02-02 23:51:46 -0800792 drivetrain_writer.set_right_controller0(
Sabina Davis1b84afa2019-02-09 01:20:21 -0800793 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);
Sabina Davisabeae332019-02-01 21:12:57 -0800794
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700795 SuperstructureWriter superstructure_writer(&output_event_loop);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800796 superstructure_writer.set_elevator_victor(
Alex Perry5fb5ff22019-02-09 21:53:17 -0800797 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(4)));
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800798 // TODO(austin): Do the vacuum
Austin Schuh461e1182019-02-17 14:56:44 -0800799 superstructure_writer.set_suction_victor(
800 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(6)));
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800801 superstructure_writer.set_intake_victor(
802 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(2)));
Alex Perry5fb5ff22019-02-09 21:53:17 -0800803 superstructure_writer.set_wrist_victor(
804 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(5)));
805 superstructure_writer.set_stilts_victor(
Austin Schuh3e3d4ba2019-02-15 23:14:52 -0800806 ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(3)));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700807 AddLoop(&output_event_loop);
Alex Perry5fb5ff22019-02-09 21:53:17 -0800808
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700809 // Thread 6.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700810 ::aos::ShmEventLoop solenoid_writer_event_loop(&config.message());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700811 SolenoidWriter solenoid_writer(&solenoid_writer_event_loop);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800812 solenoid_writer.set_intake_roller_talon(
813 make_unique<::ctre::phoenix::motorcontrol::can::TalonSRX>(10));
Austin Schuh461e1182019-02-17 14:56:44 -0800814 solenoid_writer.set_big_suction_cup(0, 1);
815 solenoid_writer.set_small_suction_cup(2, 3);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700816 AddLoop(&solenoid_writer_event_loop);
Austin Schuhc1d6f832019-02-15 23:22:17 -0800817
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700818 RunLoops();
Sabina Davisabeae332019-02-01 21:12:57 -0800819 }
820};
821
822} // namespace
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800823} // namespace y2019::wpilib
Sabina Davisabeae332019-02-01 21:12:57 -0800824
825AOS_ROBOT_CLASS(::y2019::wpilib::WPILibRobot);