blob: 03ca2757986ad6e2b3be30df79830af8579a0e6d [file] [log] [blame]
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -08001#include <unistd.h>
2
3#include <array>
4#include <chrono>
5#include <cinttypes>
6#include <cmath>
7#include <cstdio>
8#include <cstring>
9#include <functional>
10#include <memory>
11#include <mutex>
12#include <thread>
13
Austin Schuh99f7c6a2024-06-25 22:07:44 -070014#include "absl/flags/flag.h"
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080015#include "ctre/phoenix/CANifier.h"
16
17#include "frc971/wpilib/ahal/AnalogInput.h"
18#include "frc971/wpilib/ahal/Counter.h"
19#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
20#include "frc971/wpilib/ahal/DriverStation.h"
21#include "frc971/wpilib/ahal/Encoder.h"
22#include "frc971/wpilib/ahal/Servo.h"
23#include "frc971/wpilib/ahal/TalonFX.h"
24#include "frc971/wpilib/ahal/VictorSP.h"
25#undef ERROR
26
27#include "ctre/phoenix/cci/Diagnostics_CCI.h"
28#include "ctre/phoenix6/TalonFX.hpp"
29
30#include "aos/commonmath.h"
31#include "aos/containers/sized_array.h"
32#include "aos/events/event_loop.h"
33#include "aos/events/shm_event_loop.h"
34#include "aos/init.h"
35#include "aos/logging/logging.h"
36#include "aos/realtime.h"
37#include "aos/time/time.h"
38#include "aos/util/log_interval.h"
39#include "aos/util/phased_loop.h"
40#include "aos/util/wrapping_counter.h"
41#include "frc971/autonomous/auto_mode_generated.h"
42#include "frc971/can_configuration_generated.h"
43#include "frc971/control_loops/drivetrain/drivetrain_can_position_generated.h"
Maxwell Hendersondfa609a2024-01-12 20:48:36 -080044#include "frc971/control_loops/drivetrain/drivetrain_can_position_static.h"
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080045#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
46#include "frc971/input/robot_state_generated.h"
47#include "frc971/queues/gyro_generated.h"
48#include "frc971/wpilib/ADIS16448.h"
49#include "frc971/wpilib/buffered_pcm.h"
50#include "frc971/wpilib/buffered_solenoid.h"
51#include "frc971/wpilib/can_drivetrain_writer.h"
52#include "frc971/wpilib/can_sensor_reader.h"
53#include "frc971/wpilib/dma.h"
54#include "frc971/wpilib/drivetrain_writer.h"
55#include "frc971/wpilib/encoder_and_potentiometer.h"
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080056#include "frc971/wpilib/joystick_sender.h"
57#include "frc971/wpilib/logging_generated.h"
58#include "frc971/wpilib/loop_output_handler.h"
59#include "frc971/wpilib/pdp_fetcher.h"
60#include "frc971/wpilib/sensor_reader.h"
Maxwell Henderson10ed5c32024-01-09 12:40:54 -080061#include "frc971/wpilib/talonfx.h"
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080062#include "frc971/wpilib/wpilib_robot_base.h"
63#include "y2024_defense/constants.h"
64
Austin Schuh99f7c6a2024-06-25 22:07:44 -070065ABSL_FLAG(bool, ctre_diag_server, false,
66 "If true, enable the diagnostics server for interacting with "
67 "devices on the CAN bus using Phoenix Tuner");
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080068
69using ::aos::monotonic_clock;
70using ::frc971::CANConfiguration;
71using ::y2024_defense::constants::Values;
72
Maxwell Hendersondfa609a2024-01-12 20:48:36 -080073using frc971::control_loops::drivetrain::CANPositionStatic;
Maxwell Henderson10ed5c32024-01-09 12:40:54 -080074using frc971::wpilib::TalonFX;
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080075
76using std::make_unique;
77
Stephan Pleinesf63bde82024-01-13 15:59:33 -080078namespace y2024_defense::wpilib {
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -080079namespace {
80
81constexpr double kMaxBringupPower = 12.0;
82
83double drivetrain_velocity_translate(double in) {
84 return (((1.0 / in) / Values::kDrivetrainCyclesPerRevolution()) *
85 (2.0 * M_PI)) *
86 Values::kDrivetrainEncoderRatio() *
87 control_loops::drivetrain::kWheelRadius;
88}
89
90constexpr double kMaxFastEncoderPulsesPerSecond = std::max({
91 Values::kMaxDrivetrainEncoderPulsesPerSecond(),
92});
93static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
94 "fast encoders are too fast");
95
96} // namespace
97
98// Class to send position messages with sensor readings to our loops.
99class SensorReader : public ::frc971::wpilib::SensorReader {
100 public:
101 SensorReader(::aos::ShmEventLoop *event_loop,
102 std::shared_ptr<const Values> values)
103 : ::frc971::wpilib::SensorReader(event_loop),
104 values_(std::move(values)),
105 auto_mode_sender_(
106 event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
107 "/autonomous")),
108 drivetrain_position_sender_(
109 event_loop
110 ->MakeSender<::frc971::control_loops::drivetrain::Position>(
111 "/drivetrain")),
112 gyro_sender_(event_loop->MakeSender<::frc971::sensors::GyroReading>(
113 "/drivetrain")) {
114 // Set to filter out anything shorter than 1/4 of the minimum pulse width
115 // we should ever see.
116 UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
117 event_loop->SetRuntimeAffinity(aos::MakeCpusetFromCpus({0}));
118 }
119
120 void Start() override { AddToDMA(&imu_yaw_rate_reader_); }
121
122 // Auto mode switches.
123 void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
124 autonomous_modes_.at(i) = ::std::move(sensor);
125 }
126
127 void set_yaw_rate_input(::std::unique_ptr<frc::DigitalInput> sensor) {
128 imu_yaw_rate_input_ = ::std::move(sensor);
129 imu_yaw_rate_reader_.set_input(imu_yaw_rate_input_.get());
130 }
131
132 void RunIteration() override {
133 superstructure_reading_->Set(true);
134 {
135 {
136 auto builder = drivetrain_position_sender_.MakeBuilder();
137 frc971::control_loops::drivetrain::Position::Builder
138 drivetrain_builder =
139 builder
140 .MakeBuilder<frc971::control_loops::drivetrain::Position>();
141 drivetrain_builder.add_left_encoder(
142 constants::Values::DrivetrainEncoderToMeters(
143 drivetrain_left_encoder_->GetRaw()));
144 drivetrain_builder.add_left_speed(drivetrain_velocity_translate(
145 drivetrain_left_encoder_->GetPeriod()));
146
147 drivetrain_builder.add_right_encoder(
148 -constants::Values::DrivetrainEncoderToMeters(
149 drivetrain_right_encoder_->GetRaw()));
150 drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
151 drivetrain_right_encoder_->GetPeriod()));
152
153 builder.CheckOk(builder.Send(drivetrain_builder.Finish()));
154 }
155
156 {
157 auto builder = gyro_sender_.MakeBuilder();
158 ::frc971::sensors::GyroReading::Builder gyro_reading_builder =
159 builder.MakeBuilder<::frc971::sensors::GyroReading>();
160 // +/- 2000 deg / sec
161 constexpr double kMaxVelocity = 4000; // degrees / second
162 constexpr double kVelocityRadiansPerSecond =
163 kMaxVelocity / 360 * (2.0 * M_PI);
164
165 // Only part of the full range is used to prevent being 100% on or off.
166 constexpr double kScaledRangeLow = 0.1;
167 constexpr double kScaledRangeHigh = 0.9;
168
169 constexpr double kPWMFrequencyHz = 200;
170 double velocity_duty_cycle =
171 imu_yaw_rate_reader_.last_width() * kPWMFrequencyHz;
172
173 constexpr double kDutyCycleScale =
174 1 / (kScaledRangeHigh - kScaledRangeLow);
175 // scale from 0.1 - 0.9 to 0 - 1
176 double rescaled_velocity_duty_cycle =
177 (velocity_duty_cycle - kScaledRangeLow) * kDutyCycleScale;
178
179 if (!std::isnan(rescaled_velocity_duty_cycle)) {
180 gyro_reading_builder.add_velocity(
181 (rescaled_velocity_duty_cycle - 0.5) * kVelocityRadiansPerSecond);
182 }
183 builder.CheckOk(builder.Send(gyro_reading_builder.Finish()));
184 }
185
186 {
187 auto builder = auto_mode_sender_.MakeBuilder();
188
189 uint32_t mode = 0;
190 for (size_t i = 0; i < autonomous_modes_.size(); ++i) {
191 if (autonomous_modes_[i] && autonomous_modes_[i]->Get()) {
192 mode |= 1 << i;
193 }
194 }
195
196 auto auto_mode_builder =
197 builder.MakeBuilder<frc971::autonomous::AutonomousMode>();
198
199 auto_mode_builder.add_mode(mode);
200
201 builder.CheckOk(builder.Send(auto_mode_builder.Finish()));
202 }
203 }
204 }
205
206 std::shared_ptr<frc::DigitalOutput> superstructure_reading_;
207
208 void set_superstructure_reading(
209 std::shared_ptr<frc::DigitalOutput> superstructure_reading) {
210 superstructure_reading_ = superstructure_reading;
211 }
212
213 private:
214 std::shared_ptr<const Values> values_;
215
216 aos::Sender<frc971::autonomous::AutonomousMode> auto_mode_sender_;
217 aos::Sender<frc971::control_loops::drivetrain::Position>
218 drivetrain_position_sender_;
219 ::aos::Sender<::frc971::sensors::GyroReading> gyro_sender_;
220
221 std::array<std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
222
223 std::unique_ptr<frc::DigitalInput> imu_yaw_rate_input_;
224
225 frc971::wpilib::DMAPulseWidthReader imu_yaw_rate_reader_;
226};
227
228class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
229 public:
230 ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
231 return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
232 frc::Encoder::k4X);
233 }
234
235 void Run() override {
236 std::shared_ptr<const Values> values =
237 std::make_shared<const Values>(constants::MakeValues());
238
239 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
240 aos::configuration::ReadConfig("aos_config.json");
241
242 // Thread 1.
243 ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
244 ::frc971::wpilib::JoystickSender joystick_sender(
245 &joystick_sender_event_loop);
246 AddLoop(&joystick_sender_event_loop);
247
248 // Thread 2.
249 ::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
250 ::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
251 AddLoop(&pdp_fetcher_event_loop);
252
253 // Thread 3.
254 ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
255 SensorReader sensor_reader(&sensor_reader_event_loop, values);
256 std::shared_ptr<frc::DigitalOutput> superstructure_reading =
257 make_unique<frc::DigitalOutput>(25);
258
259 sensor_reader.set_pwm_trigger(true);
260 sensor_reader.set_drivetrain_left_encoder(make_encoder(1));
261 sensor_reader.set_drivetrain_right_encoder(make_encoder(0));
262 sensor_reader.set_superstructure_reading(superstructure_reading);
263 sensor_reader.set_yaw_rate_input(make_unique<frc::DigitalInput>(0));
264
265 AddLoop(&sensor_reader_event_loop);
266
267 // Thread 4.
268 std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry;
269
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800270 std::shared_ptr<TalonFX> right_front = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800271 1, true, "Drivetrain Bus", &signals_registry,
272 constants::Values::kDrivetrainStatorCurrentLimit(),
273 constants::Values::kDrivetrainSupplyCurrentLimit());
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800274 std::shared_ptr<TalonFX> right_back = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800275 2, true, "Drivetrain Bus", &signals_registry,
276 constants::Values::kDrivetrainStatorCurrentLimit(),
277 constants::Values::kDrivetrainSupplyCurrentLimit());
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800278 std::shared_ptr<TalonFX> right_under = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800279 3, true, "Drivetrain Bus", &signals_registry,
280 constants::Values::kDrivetrainStatorCurrentLimit(),
281 constants::Values::kDrivetrainSupplyCurrentLimit());
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800282 std::shared_ptr<TalonFX> left_front = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800283 4, false, "Drivetrain Bus", &signals_registry,
284 constants::Values::kDrivetrainStatorCurrentLimit(),
285 constants::Values::kDrivetrainSupplyCurrentLimit());
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800286 std::shared_ptr<TalonFX> left_back = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800287 5, false, "Drivetrain Bus", &signals_registry,
288 constants::Values::kDrivetrainStatorCurrentLimit(),
289 constants::Values::kDrivetrainSupplyCurrentLimit());
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800290 std::shared_ptr<TalonFX> left_under = std::make_shared<TalonFX>(
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800291 6, false, "Drivetrain Bus", &signals_registry,
292 constants::Values::kDrivetrainStatorCurrentLimit(),
293 constants::Values::kDrivetrainSupplyCurrentLimit());
294
295 // Setting up CAN.
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700296 if (!absl::GetFlag(FLAGS_ctre_diag_server)) {
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800297 c_Phoenix_Diagnostics_SetSecondsToStart(-1);
298 c_Phoenix_Diagnostics_Dispose();
299 }
300
301 // Creating list of falcons for CANSensorReader
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800302 std::vector<std::shared_ptr<TalonFX>> falcons;
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800303 for (auto falcon : {right_front, right_back, right_under, left_front,
304 left_back, left_under}) {
305 falcons.push_back(falcon);
306 }
307
308 ctre::phoenix::platform::can::CANComm_SetRxSchedPriority(
309 constants::Values::kDrivetrainRxPriority, true, "Drivetrain Bus");
310 ctre::phoenix::platform::can::CANComm_SetTxSchedPriority(
311 constants::Values::kDrivetrainTxPriority, true, "Drivetrain Bus");
312
313 ::aos::ShmEventLoop can_sensor_reader_event_loop(&config.message());
314 can_sensor_reader_event_loop.set_name("CANSensorReader");
315
Maxwell Hendersondfa609a2024-01-12 20:48:36 -0800316 aos::Sender<CANPositionStatic> can_position_sender =
317 can_sensor_reader_event_loop.MakeSender<CANPositionStatic>(
318 "/drivetrain");
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800319
320 frc971::wpilib::CANSensorReader can_sensor_reader(
321 &can_sensor_reader_event_loop, std::move(signals_registry), falcons,
322 [falcons, &can_position_sender](ctre::phoenix::StatusCode status) {
Maxwell Hendersondfa609a2024-01-12 20:48:36 -0800323 aos::Sender<CANPositionStatic>::StaticBuilder builder =
324 can_position_sender.MakeStaticBuilder();
325
326 auto falcon_vector = builder->add_talonfxs();
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800327
Maxwell Henderson9116e5b2024-01-21 12:14:26 -0800328 CHECK(falcon_vector->reserve(falcons.size()));
329
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800330 for (auto falcon : falcons) {
331 falcon->SerializePosition(
Maxwell Hendersondfa609a2024-01-12 20:48:36 -0800332 falcon_vector->emplace_back(),
333 control_loops::drivetrain::kHighOutputRatio);
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800334 }
335
Maxwell Hendersondfa609a2024-01-12 20:48:36 -0800336 builder->set_status(static_cast<int>(status));
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800337
Maxwell Hendersondfa609a2024-01-12 20:48:36 -0800338 builder.CheckOk(builder.Send());
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800339 });
340
341 AddLoop(&can_sensor_reader_event_loop);
342
343 // Thread 5.
344 ::aos::ShmEventLoop can_drivetrain_writer_event_loop(&config.message());
345 can_drivetrain_writer_event_loop.set_name("CANDrivetrainWriter");
346
347 frc971::wpilib::CANDrivetrainWriter can_drivetrain_writer(
348 &can_drivetrain_writer_event_loop);
349
Maxwell Henderson10ed5c32024-01-09 12:40:54 -0800350 can_drivetrain_writer.set_talonfxs({right_front, right_back, right_under},
351 {left_front, left_back, left_under});
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800352
353 can_drivetrain_writer_event_loop.MakeWatcher(
354 "/roborio", [&can_drivetrain_writer](
355 const frc971::CANConfiguration &configuration) {
356 can_drivetrain_writer.HandleCANConfiguration(configuration);
357 });
358
359 AddLoop(&can_drivetrain_writer_event_loop);
360
361 RunLoops();
362 }
363};
364
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800365} // namespace y2024_defense::wpilib
Maxwell Hendersonc3d063a2023-12-26 17:37:22 -0800366
367AOS_ROBOT_CLASS(::y2024_defense::wpilib::WPILibRobot);